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.geoserver.ows;
006:
007: import java.io.File;
008: import java.io.FileInputStream;
009: import java.io.OutputStream;
010:
011: import javax.servlet.http.HttpServletRequest;
012: import javax.servlet.http.HttpServletResponse;
013:
014: import org.geoserver.ows.util.EncodingInfo;
015: import org.geoserver.ows.util.XmlCharsetDetector;
016: import org.geoserver.platform.GeoServerResourceLoader;
017: import org.springframework.web.servlet.ModelAndView;
018: import org.springframework.web.servlet.mvc.AbstractController;
019:
020: /**
021: * Controller which publishes files through a web interface.
022: * <p>
023: * To use this controller, it should be mapped to a particular url in the url
024: * mapping of the spring dispatcher servlet. Example:
025: * <pre>
026: * <code>
027: * <bean id="filePublisher" class="org.geoserver.ows.FilePublisher"/>
028: * <bean id="dispatcherMappings"
029: * <property name="alwaysUseFullPath" value="true"/>
030: * class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
031: * <property name="mappings">
032: * <prop key="/schemas/** /*.xsd">filePublisher</prop>
033: * <prop key="/schemas/** /*.dtd">filePublisher</prop>
034: * <prop key="/styles/*">filePublisher</prop>
035: * </property>
036: * </bean>
037: * </code>
038: * </pre>
039: * </p>
040: *
041: * @author Justin Deoliveira, The Open Planning Project
042: *
043: */
044: public class FilePublisher extends AbstractController {
045: /**
046: * Resource loader
047: */
048: protected GeoServerResourceLoader loader;
049:
050: /**
051: * Creates the new file publisher.
052: *
053: * @param loader The loader used to locate files.
054: */
055: public FilePublisher(GeoServerResourceLoader loader) {
056: this .loader = loader;
057: }
058:
059: protected ModelAndView handleRequestInternal(
060: HttpServletRequest request, HttpServletResponse response)
061: throws Exception {
062: String ctxPath = request.getContextPath();
063: String reqPath = request.getRequestURI();
064: reqPath = reqPath.substring(ctxPath.length());
065:
066: if ((reqPath.length() > 1) && reqPath.startsWith("/")) {
067: reqPath = reqPath.substring(1);
068: }
069:
070: // sigh, in order to serve the file we have to open it 2 times
071: // 1) to determine its mime type
072: // 2) to determine its encoding and really serve it
073: // we can't coalish 1) because we don't have a way to give jmimemagic the bytes at the
074: // beginning of the file without disabling extension quick matching
075:
076: //load the file
077: File file = loader.find(reqPath);
078:
079: if (file == null) {
080: //return a 404
081: response.sendError(HttpServletResponse.SC_NOT_FOUND);
082:
083: return null;
084: }
085:
086: String mime = getServletContext().getMimeType(file.getName());
087: if (mime == null) {
088: //return a 415: Unsupported Media Type
089: response
090: .sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
091:
092: return null;
093: }
094: response.setContentType(mime);
095:
096: // Guessing the charset (and closing the stream)
097: EncodingInfo encInfo = null;
098: FileInputStream input = null;
099: OutputStream output = null;
100: final byte[] b4 = new byte[4];
101: int count = 0;
102: try {
103: // open the output
104: input = new FileInputStream(file);
105:
106: // Read the first four bytes, and determine charset encoding
107: count = input.read(b4);
108: encInfo = XmlCharsetDetector.getEncodingName(b4, count);
109: response
110: .setCharacterEncoding(encInfo.getEncoding() != null ? encInfo
111: .getEncoding()
112: : "UTF-8");
113:
114: // send out the first four bytes read
115: output = response.getOutputStream();
116: output.write(b4, 0, count);
117:
118: // copy the content to the output
119: byte[] buffer = new byte[8192];
120: int n = -1;
121: while ((n = input.read(buffer)) != -1) {
122: output.write(buffer, 0, n);
123: }
124: } finally {
125: if (output != null)
126: output.flush();
127: if (input != null)
128: input.close();
129: }
130:
131: return null;
132: }
133: }
|