001: package com.ibm.webdav.fileSystem;
002:
003: /*
004: * (C) Copyright IBM Corp. 2000 All rights reserved.
005: *
006: * The program is provided "AS IS" without any warranty express or
007: * implied, including the warranty of non-infringement and the implied
008: * warranties of merchantibility and fitness for a particular purpose.
009: * IBM will not be liable for any damages suffered by you as a result
010: * of using the Program. In no event will IBM be liable for any
011: * special, indirect or consequential damages or lost profits even if
012: * IBM has been advised of the possibility of their occurrence. IBM
013: * will not be liable for any third party claims against you.
014: *
015: * Portions Copyright (C) Simulacra Media Ltd, 2004.
016: */
017: import java.io.*;
018: import java.util.*;
019:
020: import javax.xml.parsers.*;
021:
022: import org.w3c.dom.*;
023:
024: import com.ibm.webdav.*;
025: import com.ibm.webdav.impl.*;
026:
027: /** PropertiesManager extends CachedProperties to implements its repository
028: * specific abstract methods.
029: * @author Jim Amsden <jamsden@us.ibm.com>
030: */
031: public class PropertiesManager extends CachedPropertiesManager {
032:
033: public static String propertiesSuffix = ".wdp"; // a WebDAV properties file
034:
035: protected Document cachedPropertiesDocument = null;
036: protected long cacheTimeStamp = 0;
037: private static final int bufferSize = 8192;
038:
039: public PropertiesManager() {
040: }
041:
042: // Constructors:
043:
044: public PropertiesManager(ResourceImpl resource,
045: com.ibm.webdav.impl.NamespaceManager namespaceManager) {
046: super (resource, namespaceManager);
047: }
048:
049: /** Delete all properties. Delete the properties file and
050: * flush the cache.
051: * @exception com.ibm.webdav.WebDAVException
052: *
053: */
054: public void deleteProperties() throws WebDAVException {
055: File propertiesFile = new File(getPropertiesFileName());
056: propertiesFile.delete();
057: cachedPropertiesDocument = null;
058: }
059:
060: /** Get the name of the properties file. The file name is the resource
061: * file name concatenated with PropertiesManager.propertiesSuffix.
062: * @return the properties file name
063: * @exception com.ibm.webdav.WebDAVException
064: */
065: private String getPropertiesFileName() throws WebDAVException {
066: String fileName = ResourceFactory
067: .getRealPath(resource.getURL());
068: // if the resource is a collection, strip off any trailing path separator
069: if (fileName.endsWith(File.separator)) {
070: fileName = fileName.substring(0, fileName.length() - 1);
071: }
072:
073: // create the properties file name by adding a .properties extension
074: return fileName + PropertiesManager.propertiesSuffix;
075: }
076:
077: public Vector loadPropertyDefinitions() throws WebDAVException {
078: return null;
079: }
080:
081: /** Load the properties document from the file system properties file.
082: * Check to see if the cache has expired.
083: * @return an XML document containing a properties element.
084: * @exception com.ibm.webdav.WebDAVException
085: */
086: public Document loadProperties() throws WebDAVException {
087: File propertiesFile = new File(getPropertiesFileName());
088: try {
089: // make sure the user is authorized to read the properties
090: if (propertiesFile.exists() && !propertiesFile.canRead()) {
091: throw new WebDAVException(WebDAVStatus.SC_UNAUTHORIZED,
092: "Insufficient permissions");
093: }
094:
095: if (cachedPropertiesDocument != null
096: && propertiesFile.lastModified() <= cacheTimeStamp) {
097: return cachedPropertiesDocument;
098: }
099: cacheTimeStamp = propertiesFile.lastModified();
100:
101: // read the properties file and parse it's contents
102: Reader reader = new InputStreamReader(new FileInputStream(
103: propertiesFile), Resource.defaultCharEncoding);
104: Reader is = new BufferedReader(reader);
105: WebDAVErrorHandler errorHandler = new WebDAVErrorHandler(
106: resource.getURL().toString());
107:
108: /*Parser xmlParser = new Parser(propertiesFile.getName(), errorListener, null);
109: xmlParser.setWarningNoDoctypeDecl(false);
110: xmlParser.setProcessNamespace(true);
111: cachedPropertiesDocument = xmlParser.readStream(is);*/
112: DocumentBuilder docbuilder = DocumentBuilderFactory
113: .newInstance().newDocumentBuilder();
114: docbuilder.setErrorHandler(errorHandler);
115: cachedPropertiesDocument = docbuilder
116: .parse(new org.xml.sax.InputSource(is));
117: if (errorHandler.getErrorCount() > 0) {
118: throw new WebDAVException(
119: WebDAVStatus.SC_INTERNAL_SERVER_ERROR,
120: "Syntax error in properties file");
121: }
122:
123: // get the properties element from the document so we can put it
124: // in a MultiStatus
125: Element properties = (Element) cachedPropertiesDocument
126: .getDocumentElement();
127: if (properties == null
128: || !properties.getTagName().equals("properties")) {
129: throw new WebDAVException(
130: WebDAVStatus.SC_INTERNAL_SERVER_ERROR,
131: "Bad properties file");
132: }
133: } catch (FileNotFoundException exc) {
134: if (propertiesFile.exists()) {
135: throw new WebDAVException(WebDAVStatus.SC_UNAUTHORIZED,
136: "Insufficient permissions");
137: } else {
138: // we have a resouce that doesn't have any properties yet
139: try {
140: cachedPropertiesDocument = DocumentBuilderFactory
141: .newInstance().newDocumentBuilder()
142: .newDocument();
143: } catch (Exception e) {
144: throw new WebDAVException(
145: WebDAVStatus.SC_PROCESSING, e.getMessage());
146: }
147: //cachedPropertiesDocument.setVersion(Resource.XMLVersion);
148: Element properties = cachedPropertiesDocument
149: .createElement("properties");
150: properties.setAttribute("xmlns:D", "DAV:");
151: cachedPropertiesDocument.appendChild(properties);
152: }
153: } catch (SecurityException exc) {
154: throw new WebDAVException(WebDAVStatus.SC_UNAUTHORIZED,
155: "Insufficient permissions");
156: } catch (Exception exc) {
157: exc.printStackTrace();
158: throw new WebDAVException(
159: WebDAVStatus.SC_INTERNAL_SERVER_ERROR,
160: "Can't read properties file");
161: }
162: return cachedPropertiesDocument;
163: }
164:
165: /** Remove the live DAV properties from the properties document that
166: * do not need to be saved. There is no reason to save them as long
167: * as they are recalculated each time the properties are loaded. This
168: * method removes the ones that are repository specific.
169: *
170: * @param propertiesDocument an XML document containing a properties element.
171: */
172: public void removeLiveProperties(Document propertiesDocument) {
173: Element properties = propertiesDocument.getDocumentElement();
174: Element p = null;
175: p = (Element) ((Element) properties).getElementsByTagNameNS(
176: "DAV:", "getcontentlength").item(0);
177: if (p != null)
178: properties.removeChild(p);
179: p = (Element) ((Element) properties).getElementsByTagNameNS(
180: "DAV:", "resourcetype").item(0);
181: if (p != null)
182: properties.removeChild(p);
183: p = (Element) ((Element) properties).getElementsByTagNameNS(
184: "DAV:", "getlastmodified").item(0);
185: if (p != null)
186: properties.removeChild(p);
187: // I haven't read this carefully, but getcontent type seems to be
188: // treated as a live property in the other methods, so treat it
189: // as such here. (jlc 991002)
190: p = (Element) ((Element) properties).getElementsByTagNameNS(
191: "DAV:", "getcontenttype").item(0);
192: if (p != null)
193: properties.removeChild(p);
194: }
195:
196: /** Save the properties to the persistent store.
197: *
198: * @param propertiesDocument an XML document containing a properties element.
199: * @exception com.ibm.webdav.WebDAVException
200: */
201: public void saveProperties(Document propertiesDocument)
202: throws WebDAVException {
203: File propertiesFile = new File(getPropertiesFileName());
204: try {
205: // make sure the user is authorized to read the properties
206: if (propertiesFile.exists() && !propertiesFile.canWrite()) {
207: throw new WebDAVException(WebDAVStatus.SC_UNAUTHORIZED,
208: "Insufficient permissions");
209: }
210:
211: // write the properties file
212: Writer writer = new OutputStreamWriter(
213: new FileOutputStream(propertiesFile),
214: Resource.defaultCharEncoding);
215: PrintWriter pout = new PrintWriter(writer, false);
216: pout.print(XMLUtility.printNode(propertiesDocument
217: .getDocumentElement()));
218: //propertiesDocument.print(pout);
219: pout.close();
220: } catch (Exception exc) {
221: exc.printStackTrace();
222: throw new WebDAVException(
223: WebDAVStatus.SC_INTERNAL_SERVER_ERROR,
224: "Can't write properties file");
225: }
226: }
227:
228: /** Update the live properties that are unique to the
229: * repository implementation
230: *
231: * @param document an XML document containing a properties to update.
232: * @exception com.ibm.webdav.WebDAVException
233: */
234: public void updateLiveProperties(Document document)
235: throws WebDAVException {
236: Element properties = document.getDocumentElement();
237:
238: // update the repository specific live properties
239: Element getContentLength = document
240: .createElement("D:getcontentlength");
241: long length = 0;
242: File file = new File(ResourceFactory.getRealPath(resource
243: .getURL()));
244: if (file.exists()) {
245: length = file.length();
246: }
247: // TODO: this doesn't account for the content length for text files
248: // which are encoded. The content length is therefore client specific
249: // because it depends on the encoding the client requests
250: getContentLength.appendChild(document.createTextNode(new Long(
251: length).toString()));
252: properties.appendChild(getContentLength);
253: Element resourceType = document.createElement("D:resourcetype");
254: if (file.exists() && file.isDirectory()) {
255: resourceType.appendChild(document
256: .createElement("D:collection"));
257: }
258: properties.appendChild(resourceType);
259: Element lastModifiedDate = document
260: .createElement("D:getlastmodified");
261: // TODO: bug, we can't assume that the value returned from file.lastModified can be used in the Date constructor. See the java.io.File.lastModified() documentation.
262: // TODO: we actually are supposed to insure that this is the same value returned by the main server in response to GET. I don't know if that's possible right now. It may return nothing at all. Check later.
263: String cdstring = new SimpleRFC1123DateFormat()
264: .format(new Date(file.lastModified()));
265: lastModifiedDate.appendChild(document.createTextNode(cdstring));
266: properties.appendChild(lastModifiedDate);
267:
268: Element contentType = document
269: .createElement("D:getcontenttype");
270: String mimetype = com.ibm.webdav.fileSystem.NamespaceManager
271: .guessAtContentTypeForName(ResourceFactory
272: .getRealPath(resource.getURL()));
273: contentType.appendChild(document.createTextNode(mimetype));
274: properties.appendChild(contentType);
275: }
276: }
|