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.components.modules.input;
019:
020: import java.util.Arrays;
021: import java.util.Map;
022: import java.util.Date;
023: import java.text.SimpleDateFormat;
024:
025: import org.apache.avalon.framework.configuration.Configuration;
026: import org.apache.avalon.framework.configuration.ConfigurationException;
027: import org.apache.avalon.framework.service.ServiceException;
028: import org.apache.avalon.framework.service.ServiceManager;
029: import org.apache.avalon.framework.service.ServiceSelector;
030: import org.apache.avalon.framework.service.Serviceable;
031: import org.apache.cocoon.components.modules.input.AbstractInputModule;
032: import org.apache.cocoon.environment.ObjectModelHelper;
033: import org.apache.cocoon.environment.Request;
034: import org.apache.commons.lang.StringUtils;
035: import org.apache.lenya.cms.publication.DocumentUtil;
036: import org.apache.lenya.cms.publication.Publication;
037: import org.apache.lenya.cms.publication.Document;
038: import org.apache.lenya.cms.publication.DocumentFactory;
039: import org.apache.lenya.cms.publication.ResourceType;
040: import org.apache.lenya.cms.repository.RepositoryUtil;
041: import org.apache.lenya.cms.repository.Session;
042: import org.apache.lenya.util.ServletHelper;
043:
044: /**
045: * <p>
046: * Resource type module.
047: * </p>
048: * <p>
049: * The syntax is either <code>{resource-type:<attribute>}</code> (which uses the resource
050: * type of the currenlty requested document) or
051: * <code>{resource-type:<name>:<attribute>}</code> (which allows to access an
052: * arbitrary resource type).
053: * </p>
054: * <p>
055: * Attributes:
056: * </p>
057: * <ul>
058: * <li><strong><code>expires</code></strong> - the expiration date in RFC 822/1123 format, see
059: * {@link org.apache.lenya.cms.publication.ResourceType#getExpires()}</li>
060: * <li><strong><code>schemaUri</code></strong> - see
061: * {@link org.apache.lenya.xml.Schema#getURI()}</li>
062: * <li><strong><code>httpSchemaUri</code></strong> - the URI to request the schema over HTTP, without Proxy and context (use {proxy:} around it).</li>
063: * <li><strong><code>supportsFormat:{format}</code></strong> - true if the resource type
064: * supports this format, false otherwise</li>
065: * </ul>
066: */
067: public class ResourceTypeModule extends AbstractInputModule implements
068: Serviceable {
069:
070: protected static final String SCHEMA_URI = "schemaUri";
071: protected static final String HTTP_SCHEMA_URI = "httpSchemaUri";
072: protected static final String EXPIRES = "expires";
073: protected static final String SUPPORTS_FORMAT = "supportsFormat";
074:
075: public Object getAttribute(String name, Configuration modeConf,
076: Map objectModel) throws ConfigurationException {
077: Object value = null;
078:
079: try {
080: Request request = ObjectModelHelper.getRequest(objectModel);
081: Session session = RepositoryUtil.getSession(this .manager,
082: request);
083:
084: ResourceType resourceType;
085: Publication pub = null;
086: String attribute;
087:
088: String[] steps = name.split(":");
089: if (steps.length == 1) {
090: DocumentFactory docFactory = DocumentUtil
091: .createDocumentFactory(this .manager, session);
092: String webappUrl = ServletHelper.getWebappURI(request);
093: Document document = docFactory.getFromURL(webappUrl);
094: pub = document.getPublication();
095:
096: attribute = name;
097: resourceType = document.getResourceType();
098: } else {
099: attribute = steps[1];
100: String resourceTypeName = steps[0];
101:
102: ServiceSelector selector = null;
103: try {
104: selector = (ServiceSelector) this .manager
105: .lookup(ResourceType.ROLE + "Selector");
106: resourceType = (ResourceType) selector
107: .select(resourceTypeName);
108: } finally {
109: this .manager.release(selector);
110: }
111: }
112:
113: if (attribute.startsWith("format-")) {
114: String[] formatSteps = name.split("-");
115: String format = formatSteps[1];
116: value = resourceType.getFormatURI(format);
117: } else if (attribute.equals(SCHEMA_URI)) {
118: value = resourceType.getSchema().getURI();
119: } else if (attribute.equals(HTTP_SCHEMA_URI)) {
120: String uri = resourceType.getSchema().getURI();
121: value = transformFallbackUriToHttp(pub.getId(), uri);
122: } else if (attribute.equals(EXPIRES)) {
123: Date expires = resourceType.getExpires();
124: SimpleDateFormat sdf = new SimpleDateFormat(
125: "EEE, dd MMM yyyy kk:mm:ss zzz");
126: value = sdf.format(expires);
127: } else if (attribute.equals(SUPPORTS_FORMAT)) {
128: String format = steps[steps.length - 1];
129: String[] formats = resourceType.getFormats();
130: return Boolean.toString(Arrays.asList(formats)
131: .contains(format));
132: } else {
133: throw new ConfigurationException("Attribute [" + name
134: + "] not supported!");
135: }
136:
137: } catch (Exception e) {
138: throw new ConfigurationException("Resolving attribute ["
139: + name + "] failed: ", e);
140: }
141:
142: return value;
143: }
144:
145: /**
146: * Transforms a fallback URI for resources into a HTTP URL.
147: *
148: * Currently only supports module urls:
149: *
150: * fallback://lenya/modules/foo/resources/schemas/bar.rng ->
151: * prefix/pubid/modules/foo/schemas/bar.rng
152: *
153: * FIXME: allow other kind of fallback URIs
154: *
155: * @param pubid publication id of the current document
156: * @param prefix prefix which will be prepended to the resulting URL
157: * @param uri fallback uri, must start with fallback://
158: * @return A string.
159: * @throws ConfigurationException
160: */
161: protected String transformFallbackUriToHttp(String pubid, String uri)
162: throws ConfigurationException {
163: if (uri.startsWith("fallback://lenya/modules/")) {
164: String path = StringUtils.substringAfter(uri,
165: "fallback://lenya/modules/");
166: String module = StringUtils.substringBefore(path, "/");
167: path = StringUtils.substringAfter(path, module
168: + "/resources");
169: return "/" + pubid + "/modules/" + module + path;
170: } else {
171: throw new ConfigurationException(
172: "Don't know how to create HTTP URL from : " + uri);
173: }
174: }
175:
176: protected ServiceManager manager;
177:
178: public void service(ServiceManager manager) throws ServiceException {
179: this.manager = manager;
180: }
181:
182: }
|