You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2002/02/28 19:00:50 UTC
cvs commit: xml-cocoon2/src/java/org/apache/cocoon/environment WriteableSource.java
sylvain 02/02/28 10:00:50
Modified: src/java/org/apache/cocoon/components/source
AbstractStreamWriteableSource.java FileSource.java
src/java/org/apache/cocoon/environment WriteableSource.java
Log:
Add cancel methods on WriteableSource and FileSource
Revision Changes Path
1.2 +135 -26 xml-cocoon2/src/java/org/apache/cocoon/components/source/AbstractStreamWriteableSource.java
Index: AbstractStreamWriteableSource.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/source/AbstractStreamWriteableSource.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- AbstractStreamWriteableSource.java 22 Feb 2002 23:25:18 -0000 1.1
+++ AbstractStreamWriteableSource.java 28 Feb 2002 18:00:50 -0000 1.2
@@ -85,7 +85,7 @@
* <code>getOutputStream()</code>.
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version $Id: AbstractStreamWriteableSource.java,v 1.1 2002/02/22 23:25:18 sylvain Exp $
+ * @version $Id: AbstractStreamWriteableSource.java,v 1.2 2002/02/28 18:00:50 sylvain Exp $
*/
public abstract class AbstractStreamWriteableSource extends AbstractStreamSource implements WriteableSource {
@@ -93,52 +93,161 @@
protected AbstractStreamWriteableSource(ComponentManager manager) {
super(manager);
}
+
+ /**
+ * Checks if the <code>OutputStream</code> under <code>handler</code> can be cancelled.
+ *
+ * @see #canCancel(OutputStream)
+ */
+ public boolean canCancel(ContentHandler handler) {
+ if (handler instanceof WritingPipe) {
+ WritingPipe pipe = (WritingPipe)handler;
+ if (pipe.getSource() == this) {
+ return pipe.canCancel();
+ }
+ }
+
+ // Not a valid handler for this source
+ throw new IllegalArgumentException("The handler is not associated to this source");
+ }
+
+ /**
+ * Always return <code>false</code>. To be redefined by implementations that support
+ * <code>cancel()</code>.
+ */
+ public boolean canCancel(OutputStream stream) {
+ return false;
+ }
+
+ /**
+ * Cancels the <code>OutputStream</code> under <code>handler</code>.
+ *
+ * @see #cancel(OutputStream)
+ */
+ public void cancel(ContentHandler handler) throws Exception {
+ if (handler instanceof WritingPipe) {
+ WritingPipe pipe = (WritingPipe)handler;
+ if (pipe.getSource() == this) {
+ pipe.cancel();
+ return;
+ }
+ }
+
+ // Not a valid handler for this source
+ throw new IllegalArgumentException("The handler is not associated to this source");
+ }
+
+ /**
+ * Always throw <code>UnsupportedOperationException</code>. To be redefined by
+ * implementations that support <code>cancel()</code>.
+ */
+ public void cancel(OutputStream stream) throws Exception {
+ throw new UnsupportedOperationException("Cancel is not implemented on " +
+ this.getClass().getName());
+ }
/**
* Get a <code>ContentHandler</code> to write a SAX stream to this source. It
- * uses the 'xml' serializer to serialize events, and thus this serializer
- * must exist in this source's component manager.
+ * uses either the 'xml' or 'html' serializer depending on the result of
+ * {@link #isHTMLContent()} to serialize events, and thus these serializers must
+ * exist in this source's component manager.
*/
public ContentHandler getContentHandler() throws SAXException, ProcessingException {
Serializer serializer;
+ ComponentSelector selector;
+
+ String serializerName = this.isHTMLContent() ? "html" : "xml";
// Get the serializer
try {
- ComponentSelector selector =
+ selector =
(ComponentSelector)this.manager.lookup(Serializer.ROLE + "Selector");
- serializer = (Serializer)selector.select("xml");
+ serializer = (Serializer)selector.select(serializerName);
} catch(ComponentException ce) {
- throw new ProcessingException("Cannot get 'xml' serializer");
+ throw new ProcessingException("Cannot get '" + serializerName + "' serializer");
}
- // Connect the output stream to the serializer
- final OutputStream output;
try {
- output = getOutputStream();
- serializer.setOutputStream(getOutputStream());
+ return new WritingPipe(getOutputStream(), selector, serializer);
} catch(IOException ioe) {
+ selector.release(serializer);
throw new ProcessingException("Cannot open stream for " + this.getSystemId(), ioe);
- }
+ }
+ }
+
+ /**
+ * A pipe that closes the outputstream at the end of the document and handles cancel().
+ */
+ private class WritingPipe extends AbstractXMLPipe {
+
+ // The output stream
+ private OutputStream output;
+
+ // Serialier and its selector for proper release
+ private Serializer serializer;
+ private ComponentSelector selector;
+
+ public WritingPipe(OutputStream output, ComponentSelector selector, Serializer serializer)
+ throws IOException {
+ this.output = output;
+ this.selector = selector;
+ this.serializer = serializer;
+
+ // Connect this pipe, the serializer and the output stream
+ this.setConsumer(this.serializer);
+ this.serializer.setOutputStream(this.output);
+ }
+
+ public WriteableSource getSource() {
+ return AbstractStreamWriteableSource.this;
+ }
- // Wrap the serializer in a pipe that will close the output stream
- // at the end of the document
- AbstractXMLPipe result = new AbstractXMLPipe() {
-
- public void endDocument() throws SAXException {
- super.endDocument();
- try {
- output.close();
- }
- catch(Exception e) {
- throw new SAXException("Error while closing output stream", e);
- }
+ /**
+ * Close the underlying stream
+ */
+ public void endDocument() throws SAXException {
+ super.endDocument();
+ try {
+ close();
}
- };
+ catch(Exception e) {
+ throw new SAXException("Error while closing output stream", e);
+ }
+ }
+
+ public boolean canCancel() {
+ return this.output != null;
+ }
+
+ /**
+ * Cancel the wrapped output stream
+ */
+ public void cancel() throws Exception {
+ AbstractStreamWriteableSource.this.cancel(output);
+ close();
+ }
- result.setConsumer(serializer);
+ private void close() throws IOException {
+ if (this.serializer != null) {
+ // Disconnect serializer;
+ this.recycle();
+ // and release it
+ this.selector.release(this.serializer);
+ this.serializer = null;
+ }
+
+ if (this.output != null) {
+ this.output.close();
+ this.output = null;
+ }
+ }
- return result;
+ // Ensure all is closed properly
+ protected void finalize() throws Throwable {
+ close();
+ super.finalize();
+ }
}
}
1.2 +94 -27 xml-cocoon2/src/java/org/apache/cocoon/components/source/FileSource.java
Index: FileSource.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/source/FileSource.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- FileSource.java 22 Feb 2002 23:25:18 -0000 1.1
+++ FileSource.java 28 Feb 2002 18:00:50 -0000 1.2
@@ -75,7 +75,7 @@
* A <code>WriteableSource</code> for 'file:/' system IDs.
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
- * @version $Id: FileSource.java,v 1.1 2002/02/22 23:25:18 sylvain Exp $
+ * @version $Id: FileSource.java,v 1.2 2002/02/28 18:00:50 sylvain Exp $
*/
public class FileSource extends AbstractStreamWriteableSource implements WriteableSource {
@@ -107,6 +107,10 @@
this.file = new File(url.substring(5)); // 5 == "file:".length()
}
+ public boolean exists() {
+ return this.file.exists();
+ }
+
/**
* Returns <code>true</code> if the file name ends with ".htm" or ".html".
*/
@@ -157,7 +161,7 @@
// Create a temp file. It will replace the right one when writing terminates,
// and serve as a lock to prevent concurrent writes.
- final File tmpFile = new File(this.file.getPath() + ".tmp");
+ File tmpFile = new File(this.file.getPath() + ".tmp");
// Ensure the directory exists
tmpFile.getParentFile().mkdirs();
@@ -174,37 +178,100 @@
}
// Return a stream that will rename the temp file on close.
- return new FilterOutputStream(new FileOutputStream(tmpFile)) {
- boolean closed = false;
+ return new FileSourceOutputStream(tmpFile);
+ }
+
+ /**
+ * Always return <code>false</code>. To be redefined by implementations that support
+ * <code>cancel()</code>.
+ */
+ public boolean canCancel(OutputStream stream) {
+ if (stream instanceof FileSourceOutputStream) {
+ FileSourceOutputStream fsos = (FileSourceOutputStream)stream;
+ if (fsos.getSource() == this) {
+ return fsos.canCancel();
+ }
+ }
- public void close() throws IOException {
- super.close();
+ // Not a valid stream for this source
+ throw new IllegalArgumentException("The stream is not associated to this source");
+ }
- try {
- // Delete destination file
- if (FileSource.this.file.exists()) {
- FileSource.this.file.delete();
- }
- // Rename temp file to destination file
- tmpFile.renameTo(FileSource.this.file);
-
- } finally {
- // Ensure temp file is deleted, ie lock is released.
- // If there was a failure above, written data is lost.
- if (tmpFile.exists()) {
- tmpFile.delete();
- }
- this.closed = true;
- }
+ /**
+ * Cancels the output stream.
+ */
+ public void cancel(OutputStream stream) throws Exception {
+ if (stream instanceof FileSourceOutputStream) {
+ FileSourceOutputStream fsos = (FileSourceOutputStream)stream;
+ if (fsos.getSource() == this) {
+ fsos.cancel();
+ return;
}
-
- public void finalize() {
- if (!this.closed && tmpFile.exists()) {
- // Something wrong happened while writing : delete temp file
+ }
+
+ // Not a valid stream for this source
+ throw new IllegalArgumentException("The stream is not associated to this source");
+ }
+
+ /**
+ * A file outputStream that will rename the temp file to the destination file upon close()
+ * and discard the temp file upon cancel().
+ */
+ private class FileSourceOutputStream extends FileOutputStream {
+
+ private File tmpFile;
+ private boolean isClosed = false;
+
+ public FileSourceOutputStream(File tmpFile) throws IOException {
+ super(tmpFile);
+ this.tmpFile = tmpFile;
+ }
+
+ public FileSource getSource() {
+ return FileSource.this;
+ }
+
+ public void close() throws IOException {
+ super.close();
+
+ try {
+ // Delete destination file
+ if (FileSource.this.file.exists()) {
+ FileSource.this.file.delete();
+ }
+ // Rename temp file to destination file
+ tmpFile.renameTo(FileSource.this.file);
+
+ } finally {
+ // Ensure temp file is deleted, ie lock is released.
+ // If there was a failure above, written data is lost.
+ if (tmpFile.exists()) {
tmpFile.delete();
}
+ this.isClosed = true;
}
- };
+ }
+
+ public boolean canCancel() {
+ return !this.isClosed;
+ }
+
+ public void cancel() throws Exception {
+ if (this.isClosed) {
+ throw new IllegalStateException("Cannot cancel : outputstrem is already closed");
+ }
+
+ this.isClosed = true;
+ super.close();
+ this.tmpFile.delete();
+ }
+
+ public void finalize() {
+ if (!this.isClosed && tmpFile.exists()) {
+ // Something wrong happened while writing : delete temp file
+ tmpFile.delete();
+ }
+ }
}
}
1.2 +41 -3 xml-cocoon2/src/java/org/apache/cocoon/environment/WriteableSource.java
Index: WriteableSource.java
===================================================================
RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/environment/WriteableSource.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- WriteableSource.java 22 Feb 2002 23:25:19 -0000 1.1
+++ WriteableSource.java 28 Feb 2002 18:00:50 -0000 1.2
@@ -75,7 +75,7 @@
* SAX events to a byte stream.
*
* @author <a href="sylvain@apache.org">Sylvain Wallez</a>
- * @version CVS $Id: WriteableSource.java,v 1.1 2002/02/22 23:25:19 sylvain Exp $
+ * @version CVS $Id: WriteableSource.java,v 1.2 2002/02/28 18:00:50 sylvain Exp $
*/
public interface WriteableSource extends ModifiableSource {
@@ -83,6 +83,13 @@
// such as user/password, headers, etc ?
/**
+ * Does this source actually exist ?
+ *
+ * @return true if the resource exists.
+ */
+ boolean exists();
+
+ /**
* Get a <code>ContentHandler</code> where an XML document can
* be written using SAX events.
* <p>
@@ -93,7 +100,7 @@
* @return a handler for SAX events
*/
ContentHandler getContentHandler() throws SAXException, ProcessingException;
-
+
/**
* Get an <code>InputStream</code> where raw bytes can be written to.
* The signification of these bytes is implementation-dependent and
@@ -102,5 +109,36 @@
* @return a stream to write to
*/
OutputStream getOutputStream() throws IOException, ProcessingException;
-
+
+ /**
+ * Can the data sent to a <code>ContentHandler</code> returned by
+ * {@link #getContentHandler()} be cancelled ?
+ *
+ * @return true if the handler can be cancelled
+ */
+ boolean canCancel(ContentHandler handler);
+
+ /**
+ * Can the data sent to an <code>OutputStream</code> returned by
+ * {@link #getOutputStream()} be cancelled ?
+ *
+ * @return true if the stream can be cancelled
+ */
+ boolean canCancel(OutputStream stream);
+
+ /**
+ * Cancel the data sent to a <code>ContentHandler</code> returned by
+ * {@link #getContentHandler()}.
+ * <p>
+ * After cancel, the handler should no more be used.
+ */
+ void cancel(ContentHandler handler) throws Exception;
+
+ /**
+ * Cancel the data sent to an <code>OutputStream</code> returned by
+ * {@link #getOutputStream()}.
+ * <p>
+ * After cancel, the stream should no more be used.
+ */
+ void cancel(OutputStream stream) throws Exception;
}
----------------------------------------------------------------------
In case of troubles, e-mail: webmaster@xml.apache.org
To unsubscribe, e-mail: cocoon-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-cvs-help@xml.apache.org