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.util.Collection;
021: import java.util.Collections;
022: import java.util.HashMap;
023: import java.util.Map;
024:
025: import org.apache.excalibur.source.Source;
026: import org.apache.excalibur.source.SourceException;
027: import org.apache.excalibur.source.TraversableSource;
028:
029: import org.apache.cocoon.components.source.InspectableSource;
030: import org.apache.cocoon.components.source.helpers.SourceProperty;
031:
032: /**
033: * TraversableCachingSource that adds support for SourceProperty caching.
034: */
035: public class InspectableTraversableCachingSource extends
036: TraversableCachingSource implements InspectableSource {
037:
038: public InspectableTraversableCachingSource(
039: final CachingSourceFactory factory, final String protocol,
040: final String uri, final String sourceUri,
041: InspectableSource source, int expires, String cacheName,
042: boolean async, boolean eventAware) {
043: super (factory, protocol, uri, sourceUri,
044: (TraversableSource) source, expires, cacheName, async,
045: eventAware);
046: }
047:
048: private InspectableSource getInspectableSource() {
049: return (InspectableSource) super .source;
050: }
051:
052: private InspectableSourceMeta getInspectableResponseMeta()
053: throws IOException {
054: return (InspectableSourceMeta) getResponseMeta();
055: }
056:
057: public SourceProperty getSourceProperty(String namespace,
058: String name) throws SourceException {
059: final InspectableSourceMeta meta;
060: try {
061: meta = getInspectableResponseMeta();
062: } catch (IOException e) {
063: if (getLogger().isDebugEnabled()) {
064: getLogger().debug(
065: "Failure initializing inspectable response", e);
066: }
067: return null;
068: }
069:
070: SourceProperty property = meta.getSourceProperty(namespace,
071: name);
072: if (property == null) {
073: // In the case of webdav the source cannot
074: // determine all available properties beforehand.
075: // Therefore, although we initialized the cached
076: // response by calling getSourceProperties(),
077: // this does not mean this particular property
078: // was returned and cached. Hence we try to
079: // get it here still and remember if it was null.
080: property = getInspectableSource().getSourceProperty(
081: namespace, name);
082: if (property == null) {
083: // remember that this property is null
084: property = InspectableSourceMeta.NULL_PROPERTY;
085: }
086: meta.setSourceProperty(property);
087: }
088:
089: if (InspectableSourceMeta.NULL_PROPERTY.equals(property)) {
090: return null;
091: }
092:
093: return property;
094: }
095:
096: public void setSourceProperty(SourceProperty property)
097: throws SourceException {
098: getInspectableSource().setSourceProperty(property);
099: try {
100: getInspectableResponseMeta().setSourceProperty(property);
101: } catch (IOException e) {
102: if (getLogger().isDebugEnabled()) {
103: getLogger().debug(
104: "Failure initializing inspectable response", e);
105: }
106: }
107: }
108:
109: public SourceProperty[] getSourceProperties()
110: throws SourceException {
111: try {
112: return getInspectableResponseMeta().getSourceProperties();
113: } catch (IOException e) {
114: if (getLogger().isDebugEnabled()) {
115: getLogger().debug(
116: "Failure initializing inspectable response", e);
117: }
118: return null;
119: }
120: }
121:
122: public void removeSourceProperty(String namespace, String name)
123: throws SourceException {
124: getInspectableSource().removeSourceProperty(namespace, name);
125: try {
126: getInspectableResponseMeta().removeSourceProperty(
127: namespace, name);
128: } catch (IOException e) {
129: if (getLogger().isDebugEnabled()) {
130: getLogger().debug(
131: "Failure initializing inspectable response", e);
132: }
133: }
134: }
135:
136: protected SourceMeta readMeta(Source source) throws SourceException {
137: return new InspectableSourceMeta(source);
138: }
139:
140: protected static class InspectableSourceMeta extends
141: TraversableSourceMeta {
142: protected static final SourceProperty NULL_PROPERTY = new SourceProperty(
143: "cocoon", "isnull");
144:
145: private Map properties;
146:
147: public InspectableSourceMeta() {
148: }
149:
150: public InspectableSourceMeta(Source source)
151: throws SourceException {
152: super (source);
153: setSourceProperties(((InspectableSource) source)
154: .getSourceProperties());
155: }
156:
157: protected SourceProperty getSourceProperty(String namespace,
158: String name) {
159: if (properties == null) {
160: return null;
161: }
162: final String key = namespace + "#" + name;
163: return (SourceProperty) properties.get(key);
164: }
165:
166: protected void setSourceProperty(SourceProperty property) {
167: if (this .properties == null) {
168: this .properties = Collections
169: .synchronizedMap(new HashMap(11));
170: }
171: final String key = property.getNamespace() + "#"
172: + property.getName();
173: properties.put(key, property);
174: }
175:
176: protected SourceProperty[] getSourceProperties() {
177: if (this .properties == null) {
178: return null;
179: }
180: final Collection values = this .properties.values();
181: return (SourceProperty[]) values
182: .toArray(new SourceProperty[values.size()]);
183: }
184:
185: protected void setSourceProperties(SourceProperty[] props) {
186: if (this .properties == null) {
187: this .properties = Collections
188: .synchronizedMap(new HashMap(props.length));
189: }
190: for (int i = 0; i < props.length; i++) {
191: setSourceProperty(props[i]);
192: }
193: }
194:
195: protected void removeSourceProperty(String namespace,
196: String name) {
197: if (this .properties != null) {
198: final String key = namespace + "#" + name;
199: properties.remove(key);
200: }
201: }
202: }
203: }
|