blob: ea9c3574333210d0c4bffca13432d89f61a2220b [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.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceException;
import org.apache.excalibur.source.TraversableSource;
import org.apache.cocoon.components.source.InspectableSource;
import org.apache.cocoon.components.source.helpers.SourceProperty;
/**
* TraversableCachingSource that adds support for SourceProperty caching.
*/
public class InspectableTraversableCachingSource extends TraversableCachingSource
implements InspectableSource {
public InspectableTraversableCachingSource(final CachingSourceFactory factory,
final String protocol,
final String uri,
final String sourceUri,
InspectableSource source,
int expires,
String cacheName,
boolean async,
boolean eventAware) {
super(factory, protocol, uri, sourceUri, (TraversableSource) source, expires, cacheName, async, eventAware);
}
private InspectableSource getInspectableSource() {
return (InspectableSource) super.source;
}
private InspectableSourceMeta getInspectableResponseMeta() throws IOException {
return (InspectableSourceMeta) getResponseMeta();
}
public SourceProperty getSourceProperty(String namespace, String name) throws SourceException {
final InspectableSourceMeta meta;
try {
meta = getInspectableResponseMeta();
} catch (IOException e) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Failure initializing inspectable response", e);
}
return null;
}
SourceProperty property = meta.getSourceProperty(namespace, name);
if (property == null) {
// In the case of webdav the source cannot
// determine all available properties beforehand.
// Therefore, although we initialized the cached
// response by calling getSourceProperties(),
// this does not mean this particular property
// was returned and cached. Hence we try to
// get it here still and remember if it was null.
property = getInspectableSource().getSourceProperty(namespace, name);
if (property == null) {
// remember that this property is null
property = InspectableSourceMeta.NULL_PROPERTY;
}
meta.setSourceProperty(property);
}
if (InspectableSourceMeta.NULL_PROPERTY.equals(property)) {
return null;
}
return property;
}
public void setSourceProperty(SourceProperty property) throws SourceException {
getInspectableSource().setSourceProperty(property);
try {
getInspectableResponseMeta().setSourceProperty(property);
} catch (IOException e) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Failure initializing inspectable response", e);
}
}
}
public SourceProperty[] getSourceProperties() throws SourceException {
try {
return getInspectableResponseMeta().getSourceProperties();
} catch (IOException e) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Failure initializing inspectable response", e);
}
return null;
}
}
public void removeSourceProperty(String namespace, String name) throws SourceException {
getInspectableSource().removeSourceProperty(namespace, name);
try {
getInspectableResponseMeta().removeSourceProperty(namespace, name);
} catch (IOException e) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Failure initializing inspectable response", e);
}
}
}
protected SourceMeta readMeta(Source source) throws SourceException {
return new InspectableSourceMeta(source);
}
protected static class InspectableSourceMeta extends TraversableSourceMeta {
protected static final SourceProperty NULL_PROPERTY = new SourceProperty("cocoon", "isnull");
private Map properties;
public InspectableSourceMeta() {
}
public InspectableSourceMeta(Source source) throws SourceException {
super(source);
setSourceProperties(((InspectableSource) source).getSourceProperties());
}
protected SourceProperty getSourceProperty(String namespace, String name) {
if (properties == null) {
return null;
}
final String key = namespace + "#" + name;
return (SourceProperty) properties.get(key);
}
protected void setSourceProperty(SourceProperty property) {
if (this.properties == null) {
this.properties = Collections.synchronizedMap(new HashMap(11));
}
final String key = property.getNamespace() + "#" + property.getName();
properties.put(key, property);
}
protected SourceProperty[] getSourceProperties() {
if (this.properties == null) {
return null;
}
final Collection values = this.properties.values();
return (SourceProperty[]) values.toArray(new SourceProperty[values.size()]);
}
protected void setSourceProperties(SourceProperty[] props) {
if (this.properties == null) {
this.properties = Collections.synchronizedMap(new HashMap(props.length));
}
for (int i = 0; i < props.length; i++) {
setSourceProperty(props[i]);
}
}
protected void removeSourceProperty(String namespace, String name) {
if (this.properties != null) {
final String key = namespace + "#" + name;
properties.remove(key);
}
}
}
}