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.File;
020: import java.io.IOException;
021: import java.net.MalformedURLException;
022: import java.net.URL;
023: import java.util.Map;
024:
025: import org.apache.avalon.framework.context.ContextException;
026: import org.apache.avalon.framework.context.Contextualizable;
027: import org.apache.avalon.framework.logger.AbstractLogEnabled;
028: import org.apache.avalon.framework.service.ServiceException;
029: import org.apache.avalon.framework.service.ServiceManager;
030: import org.apache.avalon.framework.service.Serviceable;
031: import org.apache.avalon.framework.thread.ThreadSafe;
032: import org.apache.cocoon.Constants;
033: import org.apache.cocoon.environment.Context;
034: import org.apache.excalibur.source.Source;
035: import org.apache.excalibur.source.SourceException;
036: import org.apache.excalibur.source.SourceFactory;
037: import org.apache.excalibur.source.SourceResolver;
038: import org.apache.excalibur.source.SourceUtil;
039: import org.apache.excalibur.source.URIAbsolutizer;
040:
041: /**
042: * A factory for the context protocol using the context of the servlet api.
043: * It builds the source by asking the environment context for the real URL
044: * (see {@link org.apache.cocoon.environment.Context#getResource(String)})
045: * and then resolving this real URL.
046: *
047: * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
048: * @author <a href="http://www.apache.org/~sylvain">Sylvain Wallez</a>
049: * @version CVS $Id: ContextSourceFactory.java 433543 2006-08-22 06:22:54Z crossley $
050: */
051: public class ContextSourceFactory extends AbstractLogEnabled implements
052: SourceFactory, Serviceable, Contextualizable, ThreadSafe,
053: URIAbsolutizer {
054:
055: /** The context */
056: protected Context envContext;
057:
058: /** The ServiceManager */
059: protected ServiceManager manager;
060:
061: /* (non-Javadoc)
062: * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
063: */
064: public void service(ServiceManager manager) throws ServiceException {
065: this .manager = manager;
066: }
067:
068: /* (non-Javadoc)
069: * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
070: */
071: public void contextualize(
072: org.apache.avalon.framework.context.Context context)
073: throws ContextException {
074: this .envContext = (Context) context
075: .get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
076: }
077:
078: /* (non-Javadoc)
079: * @see org.apache.excalibur.source.SourceFactory#getSource(java.lang.String, java.util.Map)
080: */
081: public Source getSource(String location, Map parameters)
082: throws SourceException, MalformedURLException, IOException {
083: if (this .getLogger().isDebugEnabled()) {
084: this .getLogger().debug(
085: "Creating source object for " + location);
086: }
087:
088: // Lookup resolver
089: SourceResolver resolver = null;
090: try {
091: resolver = (SourceResolver) this .manager
092: .lookup(SourceResolver.ROLE);
093:
094: // Remove the protocol and the first '/'
095: final int pos = location.indexOf(":/");
096: final String path = location.substring(pos + 1);
097:
098: // fix for #24093, we don't give access to files outside the context:
099: if (path.indexOf("../") != -1) {
100: throw new MalformedURLException(
101: "Invalid path ('../' is not allowed) : " + path);
102: }
103:
104: URL u;
105:
106: // Try to get a file first and fall back to a resource URL
107: String actualPath = envContext.getRealPath(path);
108: if (actualPath != null) {
109: u = new File(actualPath).toURL();
110: } else {
111: u = envContext.getResource(path);
112: }
113:
114: if (u != null) {
115: return resolver.resolveURI(u.toExternalForm());
116:
117: } else {
118: String message = location
119: + " could not be found. (possible context problem)";
120: getLogger().info(message);
121: throw new MalformedURLException(message);
122: }
123: } catch (ServiceException se) {
124: throw new SourceException(
125: "Unable to lookup source resolver.", se);
126: } finally {
127: this .manager.release(resolver);
128: }
129:
130: }
131:
132: /* (non-Javadoc)
133: * @see org.apache.excalibur.source.SourceFactory#release(org.apache.excalibur.source.Source)
134: */
135: public void release(Source source) {
136: // In fact, this method should never be called as this factory
137: // returns a source object from a different factory. So that
138: // factory should release the source
139: if (null != source) {
140: if (this .getLogger().isDebugEnabled()) {
141: this .getLogger().debug(
142: "Releasing source " + source.getURI());
143: }
144: SourceResolver resolver = null;
145: try {
146: resolver = (SourceResolver) this .manager
147: .lookup(SourceResolver.ROLE);
148: resolver.release(source);
149: } catch (ServiceException ingore) {
150: } finally {
151: this .manager.release(resolver);
152: }
153: }
154: }
155:
156: /* (non-Javadoc)
157: * @see org.apache.excalibur.source.URIAbsolutizer#absolutize(java.lang.String, java.lang.String)
158: */
159: public String absolutize(String baseURI, String location) {
160: return SourceUtil.absolutize(baseURI, location, true);
161: }
162: }
|