001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.vfny.geoserver.servlets;
006:
007: import org.geoserver.ows.DispatcherOutputStream;
008: import org.geoserver.ows.ServiceStrategy;
009: import java.io.BufferedInputStream;
010: import java.io.BufferedOutputStream;
011: import java.io.File;
012: import java.io.FileInputStream;
013: import java.io.FileOutputStream;
014: import java.io.IOException;
015: import java.io.InputStream;
016: import java.io.OutputStream;
017: import java.util.logging.Logger;
018: import javax.servlet.http.HttpServletResponse;
019:
020: /**
021: * A safe ServiceConfig strategy that uses a temporary file until writeTo
022: * completes.
023: *
024: * @author $author$
025: * @version $Revision: 1.23 $
026: */
027: public class FileStrategy implements ServiceStrategy {
028: public String getId() {
029: return "FILE";
030: }
031:
032: /** Buffer size used to copy safe to response.getOutputStream() */
033: private static int BUFF_SIZE = 4096;
034:
035: /** Temporary file number */
036: static int sequence = 0;
037:
038: /** Class logger */
039: protected static Logger LOGGER = org.geotools.util.logging.Logging
040: .getLogger("org.vfny.geoserver.servlets");
041:
042: /** OutputStream provided to writeTo method */
043: private OutputStream safe;
044:
045: /** Temporary file used by safe */
046: private File temp;
047:
048: /**
049: * Provides a outputs stream on a temporary file.
050: *
051: * <p>
052: * I have changed this to use a BufferedWriter to agree with SpeedStrategy.
053: * </p>
054: *
055: * @param response Response being handled
056: *
057: * @return Outputstream for a temporary file
058: *
059: * @throws IOException If temporary file could not be created.
060: */
061: public DispatcherOutputStream getDestination(
062: HttpServletResponse response) throws IOException {
063: // REVISIT: Should do more than sequence here
064: // (In case we are running two GeoServers at once)
065: // - Could we use response.getHandle() in the filename?
066: // - ProcessID is traditional, I don't know how to find that in Java
067: sequence++;
068:
069: // lets check for file permissions first so we can throw a clear error
070: try {
071: temp = File.createTempFile("wfs" + sequence, "tmp");
072:
073: if (!temp.canRead() || !temp.canWrite()) {
074: String errorMsg = "Temporary-file permission problem for location: "
075: + temp.getPath();
076: throw new IOException(errorMsg);
077: }
078: } catch (IOException e) {
079: String errorMsg = "Possible file permission problem. Root cause: \n"
080: + e.toString();
081: IOException newE = new IOException(errorMsg);
082: throw newE;
083: }
084:
085: temp.deleteOnExit();
086: safe = new BufferedOutputStream(new FileOutputStream(temp));
087:
088: return new DispatcherOutputStream(safe);
089: }
090:
091: /**
092: * Closes safe output stream, copies resulting file to response.
093: *
094: * @throws IOException If temporay file or response is unavailable
095: * @throws IllegalStateException if flush is called before getDestination
096: */
097: public void flush(HttpServletResponse response) throws IOException {
098: if ((temp == null) || (response == null) || (safe == null)
099: || !temp.exists()) {
100: LOGGER.fine("temp is " + temp + ", response is " + response
101: + " safe is " + safe + ", temp exists "
102: + temp.exists());
103: throw new IllegalStateException(
104: "flush should only be called after getDestination");
105: }
106:
107: InputStream copy = null;
108:
109: try {
110: safe.flush();
111: safe.close();
112: safe = null;
113:
114: // service succeeded in producing a response!
115: // copy result to the real output stream
116: copy = new BufferedInputStream(new FileInputStream(temp));
117:
118: OutputStream out = response.getOutputStream();
119: out = new BufferedOutputStream(out, 1024 * 1024);
120:
121: byte[] buffer = new byte[BUFF_SIZE];
122: int b;
123:
124: while ((b = copy.read(buffer, 0, BUFF_SIZE)) > 0) {
125: out.write(buffer, 0, b);
126: }
127:
128: // Speed Writer closes output Stream
129: // I would prefer to leave that up to doService...
130: out.flush();
131:
132: // out.close();
133: } catch (IOException ioe) {
134: throw ioe;
135: } finally {
136: if (copy != null) {
137: try {
138: copy.close();
139: } catch (Exception ex) {
140: }
141: }
142:
143: copy = null;
144:
145: if ((temp != null) && temp.exists()) {
146: temp.delete();
147: }
148:
149: temp = null;
150: response = null;
151: safe = null;
152: }
153: }
154:
155: /**
156: * Clean up after writeTo fails.
157: *
158: * @see org.geoserver.ows.ServiceStrategy#abort()
159: */
160: public void abort() {
161: if (safe != null) {
162: try {
163: safe.close();
164: } catch (IOException ioException) {
165: }
166:
167: safe = null;
168: }
169:
170: if ((temp != null) && temp.exists()) {
171: temp.delete();
172: }
173:
174: temp = null;
175: }
176:
177: public Object clone() throws CloneNotSupportedException {
178: return new FileStrategy();
179: }
180: }
|