blob: d9f966ccc9458a3d0e39c2052f06942c6ac81292 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.components.repository.impl;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.Properties;
import javax.xml.transform.OutputKeys;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.components.LifecycleHelper;
import org.apache.cocoon.components.repository.Repository;
import org.apache.cocoon.components.repository.helpers.CredentialsToken;
import org.apache.cocoon.components.repository.helpers.RepositoryTransactionHelper;
import org.apache.cocoon.components.repository.helpers.RepositoryPropertyHelper;
import org.apache.cocoon.components.repository.helpers.RepositoryVersioningHelper;
import org.apache.cocoon.components.webdav.WebDAVUtil;
import org.apache.cocoon.xml.XMLUtils;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.io.IOUtils;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.xml.dom.DOMParser;
import org.apache.webdav.lib.WebdavResource;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* A repository implementation for WebDAV.
*/
public class WebDAVRepository extends AbstractLogEnabled
implements Repository, Serviceable, Configurable, Initializable, Disposable, Component {
/** The name of the repository location configuration element */
public static final String REPO_BASE_CONF = "repo-base";
/* The ServiceManager */
private ServiceManager manager;
/* The RepositoryPropertyHelper */
private WebDAVRepositoryPropertyHelper propertyHelper;
/* The RepositoryTransactionHelper */
private WebDAVRepositoryTransactionHelper transactionHelper;
/* The RepositoryVersioningHelper */
private WebDAVRepositoryVersioningHelper versioningHelper;
/* The location of the repository */
private String repoBaseUrl;
/* The credentials to be used against the WebDAV repository */
private CredentialsToken credentials;
/* (non-Javadoc)
* @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
*/
public void service(ServiceManager manager) throws ServiceException {
this.manager = manager;
}
/* (non-Javadoc)
* @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
*/
public void configure(Configuration configuration) throws ConfigurationException {
this.repoBaseUrl = configuration.getChild(REPO_BASE_CONF).getValue();
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug("configuring repository location " + this.repoBaseUrl);
}
}
/* (non-Javadoc)
* @see org.apache.avalon.framework.activity.Initializable#initialize()
*/
public void initialize() throws Exception {
this.propertyHelper = new WebDAVRepositoryPropertyHelper(this.credentials, this);
this.transactionHelper = new WebDAVRepositoryTransactionHelper(this.credentials, this);
this.versioningHelper = new WebDAVRepositoryVersioningHelper(this.credentials, this);
LifecycleHelper lh = new LifecycleHelper(this.getLogger(),
null,
this.manager,
null,
null);
lh.setupComponent(this.propertyHelper, true);
lh.setupComponent(this.transactionHelper, true);
lh.setupComponent(this.versioningHelper, true);
}
/* (non-Javadoc)
* @see org.apache.avalon.framework.activity.Disposable#dispose()
*/
public void dispose() {
this.manager = null;
this.propertyHelper.dispose();
this.transactionHelper.dispose();
this.versioningHelper.dispose();
this.propertyHelper = null;
this.transactionHelper = null;
this.versioningHelper = null;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#getContentString(java.lang.String)
*/
public String getContentString(String uri) throws ProcessingException {
try {
return IOUtils.toString(this.getContentStream(uri));
} catch (IOException ioe) {
throw new ProcessingException ("Error loading resource: " + this.repoBaseUrl + uri, ioe);
}
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#getContentStream(java.lang.String)
*/
public InputStream getContentStream(String uri) throws ProcessingException {
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug("getting content of: " + uri);
}
try {
WebdavResource resource = WebDAVUtil.getWebdavResource(this.getAbsoluteURI(uri));
if (!resource.exists()) {
throw new HttpException(uri + " does not exist");
}
return new BufferedInputStream(resource.getMethodData());
} catch (MalformedURLException mue) {
throw new ProcessingException ("Bad URL for resource: " + this.repoBaseUrl + uri, mue);
} catch (IOException ioe) {
throw new ProcessingException ("Error loading resource: " + this.repoBaseUrl + uri, ioe);
}
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#getContentDOM(java.lang.String)
*/
public Document getContentDOM(String uri) throws ProcessingException {
DOMParser parser = null;
try {
parser = (DOMParser)this.manager.lookup( DOMParser.ROLE);
return parser.parseDocument(new InputSource(this.getContentStream(uri)));
} catch (SAXException se) {
throw new ProcessingException ("Error parsing: " + this.repoBaseUrl + uri, se);
} catch (IOException ioe) {
throw new ProcessingException ("Error getting: " + this.repoBaseUrl + uri, ioe);
} catch (ServiceException se) {
throw new ProcessingException ("Error getting DOMParser", se);
} finally {
this.manager.release(parser);
}
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#saveContent(java.lang.String, java.lang.String)
*/
public boolean saveContent(String uri, String content) {
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug("save content to " + uri);
}
try {
return WebDAVUtil.getWebdavResource(this.getAbsoluteURI(uri)).putMethod(content);
} catch (HttpException he) {
this.getLogger().error("Error saving: " + this.repoBaseUrl + uri, he);
} catch (IOException ioe) {
this.getLogger().error("Error saving: " + this.repoBaseUrl + uri, ioe);
}
return false;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#saveContent(java.lang.String, org.w3c.dom.Node)
*/
public boolean saveContent(String uri, Node node) {
try {
Properties format = new Properties();
format.put(OutputKeys.METHOD, "xml");
format.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
return this.saveContent(uri, XMLUtils.serializeNode(node, format));
} catch (ProcessingException pe) {
this.getLogger().error("Error saving dom to: " + this.repoBaseUrl + uri, pe);
}
return false;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#saveContent(java.lang.String, org.apache.excalibur.source.Source)
*/
public boolean saveContent(String uri, Source source) {
try {
return this.saveContent(uri, IOUtils.toString(source.getInputStream()));
} catch (IOException ioe) {
this.getLogger().error("Error saving source: " + source.getURI() +
" to "+ this.repoBaseUrl + uri, ioe);
}
return false;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#createResource(java.lang.String, java.lang.String)
*/
public boolean createResource(String uri, String content) {
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug("creating new resource " + uri);
}
try {
WebDAVUtil.createResource(this.getAbsoluteURI(uri), content);
return true;
} catch (HttpException he) {
this.getLogger().error("Error creating resource: " + this.repoBaseUrl + uri, he);
} catch (IOException ioe) {
this.getLogger().error("Error creating resource: " + this.repoBaseUrl + uri, ioe);
}
return false;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#exists(java.lang.String)
*/
public boolean exists(String uri) {
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug("checking existance of " + uri);
}
try {
return WebDAVUtil.getWebdavResource(this.getAbsoluteURI(uri)).exists();
} catch (HttpException he) {
this.getLogger().error("HTTP Error occurred while checking for existance of: " + uri, he);
} catch (IOException ioe) {
this.getLogger().error("IO Error occurred while checking for existance of: " + uri, ioe);
}
return false;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#copy(java.lang.String, java.lang.String, boolean)
*/
public boolean copy(String uri, String dest, boolean recurse, boolean overwrite) {
try {
WebDAVUtil.copyResource(this.getAbsoluteURI(uri), this.getAbsoluteURI(dest), recurse, overwrite);
return true;
} catch (HttpException he) {
this.getLogger().error("HTTP Error copying: " + this.repoBaseUrl + uri, he);
} catch (IOException ioe) {
this.getLogger().error("IO Error copying: " + this.repoBaseUrl + uri, ioe);
}
return false;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#move(java.lang.String, java.lang.String, boolean)
*/
public boolean move(String uri, String dest, boolean recurse, boolean overwrite) {
try {
WebDAVUtil.moveResource(this.getAbsoluteURI(uri), this.getAbsoluteURI(dest), recurse, overwrite);
return true;
} catch (HttpException he) {
this.getLogger().error("HTTP Error moving: " + this.repoBaseUrl + uri, he);
} catch (IOException ioe) {
this.getLogger().error("IO Error moving: " + this.repoBaseUrl + uri, ioe);
}
return false;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#remove(java.lang.String)
*/
public boolean remove(String uri) {
try {
return WebDAVUtil.getWebdavResource(this.getAbsoluteURI(uri)).deleteMethod();
} catch (HttpException he) {
this.getLogger().error("HTTP Error removing: " + this.repoBaseUrl + uri, he);
} catch (IOException ioe) {
this.getLogger().error("IO Error removing: " + this.repoBaseUrl + uri, ioe);
}
return false;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#makeCollection(java.lang.String, boolean)
*/
public boolean makeCollection(String uri, boolean recursive) {
try {
if (uri.endsWith("/")) uri = uri.substring(0, uri.length()-1);
if (recursive) {
WebDAVUtil.makePath(this.getAbsoluteURI(uri));
return true;
} else {
String parent = uri.substring(0, uri.lastIndexOf("/"));
String collection = uri.substring(uri.lastIndexOf("/")+1);
WebDAVUtil.makeCollection(this.getAbsoluteURI(parent), collection);
return true;
}
} catch (HttpException he) {
this.getLogger().error("HTTP Error making collection: " + this.repoBaseUrl + uri, he);
} catch (IOException ioe) {
this.getLogger().error("IO Error making collection: " + this.repoBaseUrl + uri, ioe);
}
return false;
}
/**
* get a WebDAV property helper
*
* @return a WebDAV property helper.
*/
public RepositoryPropertyHelper getPropertyHelper() {
return this.propertyHelper;
}
/**
* get a WebDAV transaction helper
*
* @return a WebDAV transaction helper.
*/
public RepositoryTransactionHelper getTransactionHelper() {
return this.transactionHelper;
}
/**
* get a WebDAV versioning helper
*
* @return a WebDAV versioning helper.
*/
public RepositoryVersioningHelper getVersioningHelper() {
return this.versioningHelper;
}
/**
* get the absolute URI of a given path
*
* @param uri the uri to get a versioning helper for.
* @return the absolute URI.
*/
public String getAbsoluteURI(String uri) {
return "http://"+this.credentials.getPrincipal().getName()
+":"+this.credentials.getCredentials()
+"@"+this.repoBaseUrl + uri;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#getCredentials()
*/
public CredentialsToken getCredentials() {
return this.credentials;
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.repository.Repository#setCredentials(org.apache.cocoon.components.repository.helpers.CredentialsToken)
*/
public void setCredentials(CredentialsToken credentials) {
this.credentials = credentials;
}
}