001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.source.impl;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.io.OutputStream;
022: import java.util.ArrayList;
023: import java.util.Arrays;
024: import java.util.Collection;
025: import java.util.Iterator;
026: import java.util.List;
027:
028: import org.apache.avalon.framework.logger.AbstractLogEnabled;
029: import org.apache.avalon.framework.logger.Logger;
030: import org.apache.cocoon.components.source.InspectableSource;
031: import org.apache.cocoon.components.source.SourceDescriptor;
032: import org.apache.cocoon.components.source.helpers.SourceProperty;
033: import org.apache.excalibur.source.ModifiableTraversableSource;
034: import org.apache.excalibur.source.Source;
035: import org.apache.excalibur.source.SourceException;
036: import org.apache.excalibur.source.SourceNotFoundException;
037: import org.apache.excalibur.source.SourceValidity;
038: import org.apache.excalibur.source.impl.validity.AggregatedValidity;
039:
040: /**
041: * Source wrapper that enhances the wrapped sources with additional capabilities.
042: *
043: * <p>
044: * Currently this Source optionally adds inspectability
045: * through the InspectableSource interface.
046: * </p>
047: *
048: * <p>
049: * Wrapped sources must implement ModifiableTraversableSource.
050: * </p>
051: */
052: public class RepositorySource extends AbstractLogEnabled implements
053: Source, ModifiableTraversableSource, InspectableSource {
054:
055: // the original source prefix
056: final String m_prefix;
057: // the wrapped source
058: final ModifiableTraversableSource m_delegate;
059: private final SourceDescriptor m_descriptor;
060:
061: // ---------------------------------------------------- Lifecycle
062:
063: public RepositorySource(final String prefix,
064: final ModifiableTraversableSource delegate,
065: final SourceDescriptor descriptor, final Logger logger)
066: throws SourceException {
067:
068: m_prefix = prefix;
069: m_delegate = delegate;
070: m_descriptor = descriptor;
071: enableLogging(logger);
072: }
073:
074: // ---------------------------------------------------- InspectableSource implementation
075:
076: /**
077: * Get all source properties that are defined on the wrapped source.
078: * If the wrapped source is itself an InspectableSource the implementation
079: * will return the aggregate set that results from combining the properties
080: * returned from a delegate call to the wrapped source with the
081: * properties returned by the source descriptor.
082: */
083: public SourceProperty[] getSourceProperties()
084: throws SourceException {
085:
086: final List properties = new ArrayList();
087: if (m_delegate instanceof InspectableSource) {
088: properties.addAll(Arrays
089: .asList(((InspectableSource) m_delegate)
090: .getSourceProperties()));
091: }
092: if (m_descriptor != null) {
093: properties.addAll(Arrays.asList(m_descriptor
094: .getSourceProperties(m_delegate)));
095: }
096: return (SourceProperty[]) properties
097: .toArray(new SourceProperty[properties.size()]);
098: }
099:
100: /**
101: * Get the source property on the wrapped source. If the wrapped source implements
102: * InspectableSource the implementation will first try to get it from there.
103: * If it doesn't exist on the delegate it will try to find it using the source descriptor.
104: */
105: public SourceProperty getSourceProperty(String uri, String name)
106: throws SourceException {
107: SourceProperty property = null;
108: if (m_delegate instanceof InspectableSource) {
109: property = ((InspectableSource) m_delegate)
110: .getSourceProperty(uri, name);
111: }
112: if (property == null && m_descriptor != null) {
113: property = m_descriptor.getSourceProperty(m_delegate, uri,
114: name);
115: }
116: return property;
117: }
118:
119: /**
120: * Remove the source property on the wrapped source. If the wrapped source implements
121: * InspectableSource the implementation will try to remove the property on both
122: * the wrapped source directly and on the source descriptor.
123: */
124: public void removeSourceProperty(String uri, String name)
125: throws SourceException {
126: if (m_delegate instanceof InspectableSource) {
127: ((InspectableSource) m_delegate).removeSourceProperty(uri,
128: name);
129: }
130: if (m_descriptor != null) {
131: m_descriptor.removeSourceProperty(m_delegate, uri, name);
132: }
133: }
134:
135: /**
136: * Set the source property on the wrapped source. If the wrapped source implements
137: * InspectableSource set the property directly on the wrapped source. Otherwise
138: * set it on the SourceDescriptor.
139: */
140: public void setSourceProperty(SourceProperty property)
141: throws SourceException {
142: if (m_delegate instanceof InspectableSource) {
143: ((InspectableSource) m_delegate)
144: .setSourceProperty(property);
145: } else if (m_descriptor != null) {
146: m_descriptor.setSourceProperty(m_delegate, property);
147: }
148: }
149:
150: // ---------------------------------------------------- Source implementation
151:
152: public boolean exists() {
153: return m_delegate.exists();
154: }
155:
156: public long getContentLength() {
157: return m_delegate.getContentLength();
158: }
159:
160: public InputStream getInputStream() throws IOException,
161: SourceNotFoundException {
162: return m_delegate.getInputStream();
163: }
164:
165: public long getLastModified() {
166: return m_delegate.getLastModified();
167: }
168:
169: public String getMimeType() {
170: return m_delegate.getMimeType();
171: }
172:
173: public String getScheme() {
174: return m_prefix;
175: }
176:
177: public String getURI() {
178: return m_prefix + ":" + m_delegate.getURI();
179: }
180:
181: /**
182: * Return a SourceValidity object describing
183: * the validity of this Source.
184: * <p>
185: * If the SourceDescriptor service is present, the resulting
186: * validity is an aggregated validity object containing both
187: * the validity describing the source itself _and_ one describing
188: * the validity of the SourceProperties managed by the SourceDescriptor.
189: * </p>
190: */
191: public SourceValidity getValidity() {
192: SourceValidity val1;
193: val1 = m_delegate.getValidity();
194: if (val1 != null && m_descriptor != null) {
195: SourceValidity val2 = m_descriptor.getValidity(m_delegate);
196: if (val2 != null) {
197: AggregatedValidity result = new AggregatedValidity();
198: result.add(val1);
199: result.add(val2);
200: return result;
201: }
202: }
203: return val1;
204: }
205:
206: public void refresh() {
207: m_delegate.refresh();
208: }
209:
210: // ---------------------------------------------------- ModifiableTraversableSource
211:
212: public Source getChild(String name) throws SourceException {
213: if (!m_delegate.isCollection())
214: return null;
215: ModifiableTraversableSource child = (ModifiableTraversableSource) m_delegate
216: .getChild(name);
217: if (child == null)
218: return null;
219:
220: return new RepositorySource(m_prefix, child, m_descriptor,
221: getLogger());
222: }
223:
224: public Collection getChildren() throws SourceException {
225: if (!m_delegate.isCollection())
226: return null;
227: Collection result = new ArrayList();
228: Iterator iter = m_delegate.getChildren().iterator();
229: while (iter.hasNext()) {
230: ModifiableTraversableSource child = (ModifiableTraversableSource) iter
231: .next();
232:
233: result.add(new RepositorySource(m_prefix, child,
234: m_descriptor, getLogger()));
235: }
236: return result;
237: }
238:
239: public String getName() {
240: return m_delegate.getName();
241: }
242:
243: public Source getParent() throws SourceException {
244: return new RepositorySource(m_prefix,
245: (ModifiableTraversableSource) m_delegate.getParent(),
246: m_descriptor, getLogger());
247: }
248:
249: public boolean isCollection() {
250: return m_delegate.isCollection();
251: }
252:
253: public void makeCollection() throws SourceException {
254: m_delegate.makeCollection();
255: }
256:
257: public boolean canCancel(OutputStream out) {
258: return m_delegate.canCancel(out);
259: }
260:
261: public void cancel(OutputStream out) throws IOException {
262: m_delegate.cancel(out);
263: }
264:
265: public void delete() throws SourceException {
266: m_delegate.delete();
267: }
268:
269: public OutputStream getOutputStream() throws IOException {
270: return m_delegate.getOutputStream();
271: }
272:
273: }
|