/*
* eXist Open Source Native XML Database
* Copyright (C) 2010 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id$
*/
package org.exist.webdav;
import org.apache.log4j.Logger;
import com.bradmcevoy.http.Resource;
import com.bradmcevoy.http.ResourceFactory;
import java.net.URISyntaxException;
import org.exist.EXistException;
import org.exist.collections.Collection;
import org.exist.dom.DocumentImpl;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.lock.Lock;
import org.exist.xmldb.XmldbURI;
/**
* Class for constructing Milton WebDAV framework resource objects .
*
* @author Dannes Wessels (dizzzz_at_exist-db.org)
*/
public class ExistResourceFactory implements ResourceFactory {
private final static Logger LOG = Logger.getLogger(ExistResourceFactory.class);
private BrokerPool brokerPool = null;
private enum ResourceType {
DOCUMENT, COLLECTION, IGNORABLE, NOT_EXISTING
};
/**
* Default constructor. Get access to instance of exist-db brokerpool.
*/
public ExistResourceFactory() {
try {
brokerPool = BrokerPool.getInstance(BrokerPool.DEFAULT_INSTANCE_NAME);
} catch (EXistException e) {
LOG.error("Unable to initialize WebDAV interface.", e);
}
}
/*
* Construct Resource for path. A Document or Collection resource is returned, NULL if type
* could not be detected.
*/
//@Override
public Resource getResource(String host, String path) {
// DWES: work around if no /db is available return nothing.
if (!path.contains("/db")) {
LOG.error("path should at least contain /db");
return null;
}
// Construct path as eXist-db XmldbURI
XmldbURI xmldbUri = null;
try {
// Strip preceding path, all up to /db
path = path.substring(path.indexOf("/db"));
// Strip last slash if available
if (path.endsWith("/")) {
path = path.substring(0, path.lastIndexOf("/"));
}
if(LOG.isDebugEnabled())
LOG.debug("host='" + host + "' path='" + path + "'");
// Create uri inside database
xmldbUri = XmldbURI.xmldbUriFor(path);
// MacOsX finder specific files
String documentSeqment = xmldbUri.lastSegment().toString();
if(documentSeqment.startsWith("._") || documentSeqment.equals(".DS_Store")){
LOG.debug("skipping MacOsX file '"+xmldbUri.lastSegment().toString()+"'");
}
} catch (URISyntaxException e) {
LOG.error("Unable to convert path '" + path + "'into a XmldbURI representation.");
return null;
}
// Return appropriate resource
switch (getResourceType(brokerPool, xmldbUri)) {
case DOCUMENT:
return new MiltonDocument(host, xmldbUri, brokerPool);
case COLLECTION:
return new MiltonCollection(host, xmldbUri, brokerPool);
case IGNORABLE:
if(LOG.isDebugEnabled())
LOG.debug("ignoring file");
return null;
case NOT_EXISTING:
if(LOG.isDebugEnabled())
LOG.debug("Resource does not exist: '" + xmldbUri + "'");
return null;
default:
LOG.error("Unkown resource type for " + xmldbUri);
return null;
}
}
/*
* Returns the resource type indicated by the path: either COLLECTION, DOCUMENT or NOT_EXISTING.
*/
private ResourceType getResourceType(BrokerPool brokerPool, XmldbURI xmldbUri) {
DBBroker broker = null;
Collection collection = null;
DocumentImpl document = null;
ResourceType type = ResourceType.NOT_EXISTING;
try {
if(LOG.isDebugEnabled())
LOG.debug("Path: " + xmldbUri.toString());
// Try to read as system user. Note that the actual user is not know
// yet. In MiltonResource the actual authentication and authorization
// is performed.
broker = brokerPool.get(brokerPool.getSecurityManager().SYSTEM_USER);
// First check if resource is a collection
collection = broker.openCollection(xmldbUri, Lock.READ_LOCK);
if (collection != null) {
type = ResourceType.COLLECTION;
collection.release(Lock.READ_LOCK);
collection = null;
} else {
// If it is not a collection, check if it is a document
document = broker.getXMLResource(xmldbUri, Lock.READ_LOCK);
if (document != null) {
// Document is found
type = ResourceType.DOCUMENT;
document.getUpdateLock().release(Lock.READ_LOCK);
document = null;
} else {
// No document and no collection.
type = ResourceType.NOT_EXISTING;
}
}
} catch (Exception ex) {
LOG.error("Error determining nature of resource " + xmldbUri.toString(), ex);
type = ResourceType.NOT_EXISTING;
} finally {
// Clean-up, just in case
if (collection != null) {
collection.release(Lock.READ_LOCK);
}
// Clean-up, just in case
if (document != null) {
document.getUpdateLock().release(Lock.READ_LOCK);
}
// Return broker to pool
brokerPool.release(broker);
}
if(LOG.isDebugEnabled())
LOG.debug("Resource type=" + type.toString());
return type;
}
}