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: */
018: package org.apache.lenya.cms.cocoon.source;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.net.MalformedURLException;
023: import java.util.StringTokenizer;
024:
025: import org.apache.avalon.framework.container.ContainerUtil;
026: import org.apache.avalon.framework.logger.AbstractLogEnabled;
027: import org.apache.avalon.framework.logger.Logger;
028: import org.apache.avalon.framework.service.ServiceException;
029: import org.apache.avalon.framework.service.ServiceManager;
030: import org.apache.cocoon.environment.Request;
031: import org.apache.excalibur.source.Source;
032: import org.apache.excalibur.source.SourceNotFoundException;
033: import org.apache.excalibur.source.SourceResolver;
034: import org.apache.excalibur.source.SourceValidity;
035: import org.apache.excalibur.source.impl.validity.TimeStampValidity;
036: import org.apache.lenya.cms.publication.Document;
037: import org.apache.lenya.cms.publication.DocumentException;
038: import org.apache.lenya.cms.publication.DocumentFactory;
039: import org.apache.lenya.cms.publication.DocumentUtil;
040: import org.apache.lenya.cms.publication.Publication;
041: import org.apache.lenya.cms.publication.URLInformation;
042: import org.apache.lenya.cms.repository.RepositoryUtil;
043: import org.apache.lenya.cms.repository.Session;
044: import org.apache.lenya.cms.site.SiteStructure;
045: import org.apache.lenya.util.Query;
046: import org.apache.lenya.util.ServletHelper;
047:
048: /**
049: * Source for the site:/ protocol.
050: */
051: public class SiteSource extends AbstractLogEnabled implements Source {
052:
053: private ServiceManager manager;
054: private Source delegate;
055: private String scheme;
056: private String uri;
057:
058: /**
059: * @param manager The service manager.
060: * @param request The cocoon request.
061: * @param location The source URI.
062: * @param logger The logger.
063: */
064: public SiteSource(ServiceManager manager, Request request,
065: String location, Logger logger) {
066: ContainerUtil.enableLogging(this , logger);
067:
068: this .manager = manager;
069: this .uri = location;
070:
071: String areaName = null;
072: String pubId;
073:
074: StringTokenizer locationSteps = new StringTokenizer(location,
075: "?");
076: String completePath = locationSteps.nextToken();
077:
078: String relativePath;
079: try {
080:
081: this .scheme = completePath.substring(0, completePath
082: .indexOf(":") + 1);
083: final String absolutePath = completePath.substring(scheme
084: .length());
085: if (absolutePath.startsWith("//")) {
086: final String fullPath = absolutePath.substring(2);
087: StringTokenizer steps = new StringTokenizer(fullPath,
088: "/");
089: pubId = steps.nextToken();
090: areaName = steps.nextToken();
091: String prefix = pubId + "/" + areaName;
092: relativePath = fullPath.substring(prefix.length());
093: } else if (absolutePath.startsWith("/")) {
094: String webappUrl = ServletHelper.getWebappURI(request);
095: URLInformation info = new URLInformation(webappUrl);
096: pubId = info.getPublicationId();
097: areaName = info.getArea();
098: relativePath = absolutePath;
099: } else {
100: throw new MalformedURLException("The path ["
101: + absolutePath
102: + "] must start with at least one slash.");
103: }
104:
105: DocumentFactory factory = DocumentUtil.getDocumentFactory(
106: this .manager, request);
107: Publication pub = factory.getPublication(pubId);
108: SiteStructure site = pub.getArea(areaName).getSite();
109:
110: String[] steps = relativePath.substring(1).split("/");
111:
112: String language = steps[0];
113: String prefix = "/" + language;
114: String path = relativePath.substring(prefix.length());
115:
116: if (site.contains(path, language)) {
117: Document doc = site.getNode(path).getLink(language)
118: .getDocument();
119: if (locationSteps.hasMoreTokens()) {
120: Query query = new Query(locationSteps.nextToken());
121: String format = query.getValue("format");
122: if (format != null) {
123: this .delegate = getFormatSource(doc, format);
124: }
125: }
126: if (this .delegate == null) {
127: String lenyaURL = doc.getSourceURI();
128: Session session = RepositoryUtil.getSession(
129: this .manager, request);
130: this .delegate = new RepositorySource(manager,
131: lenyaURL, session, getLogger());
132: }
133: }
134:
135: } catch (Exception e) {
136: throw new RuntimeException(e);
137: }
138: }
139:
140: public boolean exists() {
141: return this .delegate != null;
142: }
143:
144: public long getContentLength() {
145: return this .delegate == null ? 0 : this .delegate
146: .getContentLength();
147: }
148:
149: public InputStream getInputStream() throws IOException,
150: SourceNotFoundException {
151: return this .delegate.getInputStream();
152: }
153:
154: public long getLastModified() {
155: return this .delegate == null ? 0 : this .delegate
156: .getLastModified();
157: }
158:
159: public String getMimeType() {
160: return this .delegate == null ? "" : this .delegate.getMimeType();
161: }
162:
163: public String getScheme() {
164: return this .scheme;
165: }
166:
167: public String getURI() {
168: return this .uri;
169: }
170:
171: public SourceValidity getValidity() {
172: return this .delegate.getValidity();
173: }
174:
175: public void refresh() {
176: if (this .delegate != null) {
177: this .delegate.refresh();
178: }
179: }
180:
181: protected Source getFormatSource(Document doc, String format)
182: throws DocumentException, ServiceException,
183: MalformedURLException, IOException {
184: String formatBaseUri = doc.getResourceType().getFormatURI(
185: format);
186: String formatUri = formatBaseUri + "/"
187: + doc.getPublication().getId() + "/" + doc.getArea()
188: + "/" + doc.getUUID() + "/" + doc.getLanguage();
189:
190: SourceResolver resolver = null;
191: try {
192: resolver = (SourceResolver) this.manager
193: .lookup(SourceResolver.ROLE);
194: return resolver.resolveURI(formatUri);
195: } finally {
196: if (resolver != null) {
197: this.manager.release(resolver);
198: }
199: }
200: }
201:
202: }
|