blob: 42a7406cb1c0d96ecb05cbe2843e9ddaf0a5061a [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.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.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.
* </p>
*
* <p>
* Wrapped sources must implement ModifiableTraversableSource.
* </p>
*/
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;
// ---------------------------------------------------- Lifecycle
public RepositorySource(
final String prefix,
final ModifiableTraversableSource delegate,
final SourceDescriptor descriptor,
final Logger logger) throws SourceException {
m_prefix = prefix;
m_delegate = delegate;
m_descriptor = descriptor;
enableLogging(logger);
}
// ---------------------------------------------------- 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>
*/
public SourceValidity getValidity() {
SourceValidity val1;
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()
);
}
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()
)
);
}
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()
);
}
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();
}
}