blob: d33c2119c032b81275582797398709f1b400b8ff [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed 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.source.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.apache.cocoon.caching.validity.EventValidity;
import org.apache.cocoon.caching.validity.NamedEvent;
import org.apache.cocoon.components.source.InspectableSource;
import org.apache.cocoon.components.source.SourceDescriptor;
import org.apache.cocoon.components.source.helpers.SourceProperty;
import org.apache.excalibur.source.ModifiableTraversableSource;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceException;
import org.apache.excalibur.source.SourceNotFoundException;
import org.apache.excalibur.source.SourceValidity;
import org.apache.excalibur.source.impl.validity.AggregatedValidity;
/**
* Source wrapper that enhances the wrapped sources with additional capabilities.
*
* <p>
* Currently this Source optionally adds inspectability
* through the InspectableSource interface and event caching
* by handing out EventValidities based on the Source uri.
* </p>
*
* <p>
* Wrapped sources must implement ModifiableTraversableSource.
* </p>
*
* @author <a href="mailto:unico@apache.org">Unico Hommes</a>
*/
public class RepositorySource extends AbstractLogEnabled
implements Source, ModifiableTraversableSource, InspectableSource {
// the original source prefix
final String m_prefix;
// the wrapped source
final ModifiableTraversableSource m_delegate;
private final SourceDescriptor m_descriptor;
private final boolean m_useEventCaching;
// ---------------------------------------------------- Lifecycle
public RepositorySource(
final String prefix,
final ModifiableTraversableSource delegate,
final SourceDescriptor descriptor,
final Logger logger,
final boolean useEventCaching) throws SourceException {
m_prefix = prefix;
m_delegate = delegate;
m_descriptor = descriptor;
enableLogging(logger);
m_useEventCaching = useEventCaching;
}
// ---------------------------------------------------- InspectableSource implementation
/**
* Get all source properties that are defined on the wrapped source.
* If the wrapped source is itself an InspectableSource the implementation
* will return the aggregate set that results from combining the properties
* returned from a delegate call to the wrapped source with the
* properties returned by the source descriptor.
*/
public SourceProperty[] getSourceProperties() throws SourceException {
final List properties = new ArrayList();
if (m_delegate instanceof InspectableSource) {
properties.addAll(Arrays.asList(((InspectableSource) m_delegate).getSourceProperties()));
}
if (m_descriptor != null) {
properties.addAll(Arrays.asList(m_descriptor.getSourceProperties(m_delegate)));
}
return (SourceProperty[]) properties.toArray(new SourceProperty[properties.size()]);
}
/**
* Get the source property on the wrapped source. If the wrapped source implements
* InspectableSource the implementation will first try to get it from there.
* If it doesn't exist on the delegate it will try to find it using the source descriptor.
*/
public SourceProperty getSourceProperty(String uri, String name) throws SourceException {
SourceProperty property = null;
if (m_delegate instanceof InspectableSource) {
property = ((InspectableSource) m_delegate).getSourceProperty(uri,name);
}
if (property == null && m_descriptor != null) {
property = m_descriptor.getSourceProperty(m_delegate,uri,name);
}
return property;
}
/**
* Remove the source property on the wrapped source. If the wrapped source implements
* InspectableSource the implementation will try to remove the property on both
* the wrapped source directly and on the source descriptor.
*/
public void removeSourceProperty(String uri, String name) throws SourceException {
if (m_delegate instanceof InspectableSource) {
((InspectableSource) m_delegate).removeSourceProperty(uri,name);
}
if (m_descriptor != null) {
m_descriptor.removeSourceProperty(m_delegate,uri,name);
}
}
/**
* Set the source property on the wrapped source. If the wrapped source implements
* InspectableSource set the property directly on the wrapped source. Otherwise
* set it on the SourceDescriptor.
*/
public void setSourceProperty(SourceProperty property) throws SourceException {
if (m_delegate instanceof InspectableSource) {
((InspectableSource) m_delegate).setSourceProperty(property);
} else if (m_descriptor != null) {
m_descriptor.setSourceProperty(m_delegate, property);
}
}
// ---------------------------------------------------- Source implementation
public boolean exists() {
return m_delegate.exists();
}
public long getContentLength() {
return m_delegate.getContentLength();
}
public InputStream getInputStream()
throws IOException, SourceNotFoundException {
return m_delegate.getInputStream();
}
public long getLastModified() {
return m_delegate.getLastModified();
}
public String getMimeType() {
return m_delegate.getMimeType();
}
public String getScheme() {
return m_prefix;
}
public String getURI() {
return m_prefix + ":" + m_delegate.getURI();
}
/**
* Return a SourceValidity object describing
* the validity of this Source.
* <p>
* If the SourceDescriptor service is present, the resulting
* validity is an aggregated validity object containing both
* the validity describing the source itself _and_ one describing
* the validity of the SourceProperties managed by the SourceDescriptor.
* </p>
* When using event caching the SourceValidity describing the Source itself
* is an EventValidity that contains a NamedEvent which name is the wrapped
* Source URI.
*/
public SourceValidity getValidity() {
SourceValidity val1;
if (m_useEventCaching) {
val1 = new EventValidity(new NamedEvent(getURI()));
}
else {
val1 = m_delegate.getValidity();
}
if (val1 != null && m_descriptor != null) {
SourceValidity val2 = m_descriptor.getValidity(m_delegate);
if (val2 != null) {
AggregatedValidity result = new AggregatedValidity();
result.add(val1);
result.add(val2);
return result;
}
}
return val1;
}
public void refresh() {
m_delegate.refresh();
}
// ---------------------------------------------------- ModifiableTraversableSource
public Source getChild(String name) throws SourceException {
if (!m_delegate.isCollection()) return null;
ModifiableTraversableSource child = (ModifiableTraversableSource) m_delegate.getChild(name);
if (child == null) return null;
return new RepositorySource(
m_prefix,
child,
m_descriptor,
getLogger(),
m_useEventCaching
);
}
public Collection getChildren() throws SourceException {
if (!m_delegate.isCollection()) return null;
Collection result = new ArrayList();
Iterator iter = m_delegate.getChildren().iterator();
while(iter.hasNext()) {
ModifiableTraversableSource child = (ModifiableTraversableSource) iter.next();
result.add(
new RepositorySource(
m_prefix,
child,
m_descriptor,
getLogger(),
m_useEventCaching
)
);
}
return result;
}
public String getName() {
return m_delegate.getName();
}
public Source getParent() throws SourceException {
return new RepositorySource(
m_prefix,
(ModifiableTraversableSource) m_delegate.getParent(),
m_descriptor,
getLogger(),
m_useEventCaching
);
}
public boolean isCollection() {
return m_delegate.isCollection();
}
public void makeCollection() throws SourceException {
m_delegate.makeCollection();
}
public boolean canCancel(OutputStream out) {
return m_delegate.canCancel(out);
}
public void cancel(OutputStream out) throws IOException {
m_delegate.cancel(out);
}
public void delete() throws SourceException {
m_delegate.delete();
}
public OutputStream getOutputStream() throws IOException {
return m_delegate.getOutputStream();
}
// ---------------------------------------------------- LockableSource implementation
// public void addSourceLocks(SourceLock lock) throws SourceException {
// if (m_delegate instanceof LockableSource) {
// ((LockableSource) m_delegate).addSourceLocks(lock);
// }
// }
//
// public Enumeration getSourceLocks() throws SourceException {
// if (m_delegate instanceof LockableSource) {
// return ((LockableSource) m_delegate).getSourceLocks();
// }
// return null;
// }
// ---------------------------------------------------- VersionableSource implementation
// public String getLatestSourceRevision() throws SourceException {
// if (m_delegate instanceof VersionableSource) {
// return ((VersionableSource) m_delegate).getLatestSourceRevision();
// }
// return null;
// }
//
// public String getSourceRevision() throws SourceException {
// if (m_delegate instanceof VersionableSource) {
// return ((VersionableSource) m_delegate).getSourceRevision();
// }
// return null;
// }
//
// public String getSourceRevisionBranch() throws SourceException {
// if (m_delegate instanceof VersionableSource) {
// return ((VersionableSource) m_delegate).getSourceRevisionBranch();
// }
// return null;
// }
//
// public boolean isVersioned() throws SourceException {
// if (m_delegate instanceof VersionableSource) {
// return ((VersionableSource) m_delegate).isVersioned();
// }
// return false;
// }
//
// public void setSourceRevision(String revision) throws SourceException {
// if (m_delegate instanceof VersionableSource) {
// ((VersionableSource) m_delegate).setSourceRevision(revision);
// }
// }
//
// public void setSourceRevisionBranch(String branch) throws SourceException {
// if (m_delegate instanceof VersionableSource) {
// ((VersionableSource) m_delegate).setSourceRevisionBranch(branch);
// }
// }
// ---------------------------------------------------- RestrictableSource implementation
// public void addSourcePermission(SourcePermission permission)
// throws SourceException {
//
// if (m_delegate instanceof RestrictableSource) {
// ((RestrictableSource) m_delegate).addSourcePermission(permission);
// }
// }
//
// public SourceCredential getSourceCredential() throws SourceException {
// if (m_delegate instanceof RestrictableSource) {
// return ((RestrictableSource) m_delegate).getSourceCredential();
// }
// return null;
// }
//
// public SourcePermission[] getSourcePermissions() throws SourceException {
// if (m_delegate instanceof RestrictableSource) {
// return ((RestrictableSource) m_delegate).getSourcePermissions();
// }
// return null;
// }
//
// public void removeSourcePermission(SourcePermission permission)
// throws SourceException {
//
// if (m_delegate instanceof RestrictableSource) {
// ((RestrictableSource) m_delegate).removeSourcePermission(permission);
// }
// }
//
// public void setSourceCredential(SourceCredential credential)
// throws SourceException {
//
// if (m_delegate instanceof RestrictableSource) {
// ((RestrictableSource) m_delegate).setSourceCredential(credential);
// }
// }
}