001: package org.apache.lenya.cms.cocoon.source;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.ByteArrayOutputStream;
005: import java.io.IOException;
006: import java.io.InputStream;
007:
008: import org.apache.avalon.framework.service.ServiceManager;
009: import org.apache.cocoon.components.source.impl.MultiSourceValidity;
010: import org.apache.excalibur.source.Source;
011: import org.apache.excalibur.source.SourceNotFoundException;
012: import org.apache.excalibur.source.SourceResolver;
013: import org.apache.excalibur.source.SourceValidity;
014: import org.apache.lenya.xml.DocumentHelper;
015: import org.apache.lenya.xml.NamespaceHelper;
016: import org.w3c.dom.Document;
017: import org.w3c.dom.Element;
018:
019: /**
020: *
021: */
022: public class AggregatingSource implements Source {
023:
024: private String uri;
025: private String[] sourceUris;
026: private ServiceManager manager;
027:
028: /**
029: * @param uri
030: * @param uris
031: * @param manager
032: */
033: public AggregatingSource(String uri, String[] uris,
034: ServiceManager manager) {
035: this .manager = manager;
036: this .sourceUris = (String[]) uris.clone();
037: this .uri = uri;
038: }
039:
040: public String toString() {
041: return getURI();
042: }
043:
044: protected void loadDom() {
045: try {
046: for (int i = 0; i < sourceUris.length; i++) {
047: Document sourceDom = SourceUtil.readDOM(sourceUris[i],
048: this .manager);
049:
050: if (sourceDom == null) {
051: throw new RuntimeException("The source ["
052: + sourceUris[i] + "] doesn't contain XML.");
053: }
054:
055: Element docElement = sourceDom.getDocumentElement();
056: if (this .dom == null) {
057: String namespaceUri = docElement.getNamespaceURI();
058: String prefix = docElement.getPrefix();
059: String localName = docElement.getLocalName();
060:
061: if (namespaceUri == null) {
062: this .dom = DocumentHelper.createDocument(null,
063: localName, null);
064: } else {
065: NamespaceHelper helper = new NamespaceHelper(
066: namespaceUri, prefix, localName);
067: this .dom = helper.getDocument();
068: }
069: }
070:
071: Element[] elements = DocumentHelper
072: .getChildren(docElement);
073: for (int e = 0; e < elements.length; e++) {
074: Element clone = (Element) this .dom.importNode(
075: elements[e], true);
076: this .dom.getDocumentElement().appendChild(clone);
077: }
078: }
079: } catch (RuntimeException e) {
080: throw e;
081: } catch (Exception e) {
082: throw new RuntimeException(e);
083: }
084: }
085:
086: private Document dom;
087: private byte[] data;
088:
089: protected Document getDom() {
090: if (this .dom == null) {
091: loadDom();
092: }
093: return this .dom;
094: }
095:
096: protected byte[] getData() {
097: if (this .data == null) {
098: Document dom = getDom();
099: if (dom != null) {
100: ByteArrayOutputStream out = new ByteArrayOutputStream();
101: try {
102: DocumentHelper.writeDocument(dom, out);
103: } catch (Exception e) {
104: throw new RuntimeException(e);
105: }
106: this .data = out.toByteArray();
107: }
108: }
109: return this .data;
110: }
111:
112: public boolean exists() {
113: return this .sourceUris.length > 0;
114: }
115:
116: public long getContentLength() {
117: return getData().length;
118: }
119:
120: public InputStream getInputStream() throws IOException,
121: SourceNotFoundException {
122: if (!exists()) {
123: throw new RuntimeException(this + " does not exist!");
124: }
125: return new ByteArrayInputStream(getData());
126: }
127:
128: public long getLastModified() {
129: long lastModified = 0;
130: for (int i = 0; i < this .sourceUris.length; i++) {
131: try {
132: lastModified = Math.max(lastModified, SourceUtil
133: .getLastModified(sourceUris[i], this .manager));
134: } catch (Exception e) {
135: throw new RuntimeException(e);
136: }
137: }
138: return lastModified;
139: }
140:
141: public String getMimeType() {
142: return "application/xml";
143: }
144:
145: public String getScheme() {
146: return "aggregate-template";
147: }
148:
149: public String getURI() {
150: return this .uri;
151: }
152:
153: private SourceValidity validity;
154:
155: public SourceValidity getValidity() {
156: if (this .validity == null) {
157: SourceResolver resolver = null;
158: try {
159: resolver = (SourceResolver) this .manager
160: .lookup(SourceResolver.ROLE);
161: MultiSourceValidity aggregatedValidity = new MultiSourceValidity(
162: resolver, 0);
163: for (int i = 0; i < this .sourceUris.length; i++) {
164: Source source = null;
165: try {
166: source = resolver
167: .resolveURI(this .sourceUris[i]);
168: aggregatedValidity.addSource(source);
169: } finally {
170: if (source != null) {
171: resolver.release(source);
172: }
173: }
174: }
175: aggregatedValidity.close();
176: this .validity = aggregatedValidity;
177: } catch (Exception e) {
178: throw new RuntimeException(e);
179: } finally {
180: if (resolver != null) {
181: this .manager.release(resolver);
182: }
183: }
184: }
185: return this .validity;
186: }
187:
188: public void refresh() {
189: this.dom = null;
190: this.data = null;
191: this.validity = null;
192: }
193:
194: }
|