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.transformation.helpers;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.io.ObjectInputStream;
022: import java.io.ObjectOutputStream;
023: import java.io.OutputStream;
024: import java.io.Serializable;
025:
026: import org.apache.avalon.framework.logger.Logger;
027: import org.apache.cocoon.CascadingIOException;
028: import org.apache.cocoon.util.HashUtil;
029: import org.apache.excalibur.source.ModifiableSource;
030: import org.apache.excalibur.source.Source;
031: import org.apache.excalibur.source.SourceResolver;
032:
033: /**
034: * This is the interface between the {@link IncludeCacheManager} and a
035: * {@link Source} object that stores the cached content in a directory
036: * manner.
037: *
038: * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
039: * @version CVS $Id: ModifiableSourceIncludeCacheStorageProxy.java 433543 2006-08-22 06:22:54Z crossley $
040: * @since 2.1
041: */
042: public final class ModifiableSourceIncludeCacheStorageProxy implements
043: IncludeCacheStorageProxy {
044:
045: private SourceResolver resolver;
046: private String parentURI;
047: private Logger logger;
048:
049: /**
050: * Constructor
051: * @param resolver For source resolving
052: * @param parentURI The "directory"
053: * @param logger A logger for debugging
054: */
055: public ModifiableSourceIncludeCacheStorageProxy(
056: SourceResolver resolver, String parentURI, Logger logger) {
057: this .resolver = resolver;
058: this .parentURI = parentURI;
059: this .logger = logger;
060: }
061:
062: /**
063: * Calculate the URI for a child
064: * @param uri Child URI
065: * @return String Absolute URI
066: */
067: private String getURI(String uri) {
068: final long hash = HashUtil.hash(uri);
069: final StringBuffer buffer = new StringBuffer(this .parentURI);
070: buffer.append('/');
071: if (hash < 0) {
072: buffer.append('M').append(hash * -1);
073: } else {
074: buffer.append(hash);
075: }
076: buffer.append(".cxml");
077: return buffer.toString();
078: }
079:
080: /**
081: * @see IncludeCacheStorageProxy#get(java.lang.String)
082: */
083: public Serializable get(String uri) {
084: if (logger.isDebugEnabled()) {
085: logger.debug("WSCProxy: Getting content for " + uri);
086: }
087:
088: Source child = null;
089: Serializable result = null;
090: try {
091: child = this .resolver.resolveURI(this .getURI(uri));
092:
093: if (logger.isDebugEnabled()) {
094: logger.debug("WSCProxy: Resolved to " + child.getURI());
095: }
096:
097: if (child.exists()) {
098: InputStream is = child.getInputStream();
099: ObjectInputStream ois = new ObjectInputStream(is);
100: result = (Serializable) ois.readObject();
101: ois.close();
102: }
103: } catch (Exception ignore) {
104: } finally {
105: this .resolver.release(child);
106: }
107:
108: if (logger.isDebugEnabled()) {
109: logger.debug("WSCProxy: Result for " + uri + " : "
110: + (result == null ? "Not in cache" : "Found"));
111: }
112: return result;
113: }
114:
115: /**
116: * @see IncludeCacheStorageProxy#put(java.lang.String, java.io.Serializable)
117: */
118: public void put(String uri, Serializable object) throws IOException {
119: if (logger.isDebugEnabled()) {
120: logger.debug("WSCProxy: Storing content for " + uri);
121: }
122: Source child = null;
123: try {
124: child = this .resolver.resolveURI(this .getURI(uri));
125:
126: if (logger.isDebugEnabled()) {
127: logger.debug("WSCProxy: Resolved to " + child.getURI());
128: }
129:
130: OutputStream os;
131: if (child instanceof ModifiableSource) {
132: os = ((ModifiableSource) child).getOutputStream();
133: } else {
134: throw new IOException("Source " + uri
135: + " is not writeable.");
136: }
137: ObjectOutputStream oos = new ObjectOutputStream(os);
138: oos.writeObject(object);
139: oos.flush();
140: oos.close();
141: } catch (IOException io) {
142: throw io;
143: } catch (Exception ignore) {
144: throw new CascadingIOException("Exception.", ignore);
145: } finally {
146: this .resolver.release(child);
147: }
148: }
149:
150: /**
151: * @see IncludeCacheStorageProxy#remove(java.lang.String)
152: */
153: public void remove(String uri) {
154: if (logger.isDebugEnabled()) {
155: logger.debug("WSCProxy: Removing content for " + uri);
156: }
157: Source child = null;
158: try {
159: child = this .resolver.resolveURI(this .getURI(uri));
160:
161: if (logger.isDebugEnabled()) {
162: logger.debug("WSCProxy: Resolved to " + child.getURI());
163: }
164:
165: if (child instanceof ModifiableSource) {
166: ((ModifiableSource) child).delete();
167: } else {
168: throw new IOException("Source " + uri
169: + " is not writeable.");
170: }
171: } catch (Exception ignore) {
172: } finally {
173: this .resolver.release(child);
174: }
175: }
176:
177: /**
178: * Compare
179: */
180: public boolean equals(Object object) {
181: if (object instanceof ModifiableSourceIncludeCacheStorageProxy) {
182: return this .parentURI
183: .equals(((ModifiableSourceIncludeCacheStorageProxy) object).parentURI);
184: }
185: return false;
186: }
187:
188: /**
189: * Generate a hash code
190: */
191: public int hashCode() {
192: return this.parentURI.hashCode();
193: }
194:
195: }
|