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.camel.builder.xml;
018
019 import java.io.File;
020 import java.io.InputStream;
021 import javax.xml.transform.Source;
022 import javax.xml.transform.TransformerException;
023 import javax.xml.transform.URIResolver;
024 import javax.xml.transform.stream.StreamSource;
025
026 import org.apache.camel.spi.ClassResolver;
027 import org.apache.camel.util.FileUtil;
028 import org.apache.camel.util.ObjectHelper;
029 import org.slf4j.Logger;
030 import org.slf4j.LoggerFactory;
031
032 /**
033 * Camel specific {@link javax.xml.transform.URIResolver} which is capable of loading files
034 * from the classpath and file system.
035 * <p/>
036 * Use prefix <tt>classpath:</tt> or <tt>file:</tt> to denote either classpath or file system.
037 * If no prefix is provided then the prefix from the <tt>location</tt> parameter is used.
038 * If it neither has a prefix then <tt>classpath:</tt> is used.
039 * <p/>
040 * This implementation <b>cannot</b> load files over http.
041 *
042 * @version
043 */
044 public class XsltUriResolver implements URIResolver {
045
046 private static final transient Logger LOG = LoggerFactory.getLogger(XsltUriResolver.class);
047
048 private final ClassResolver resolver;
049 private final String location;
050
051 public XsltUriResolver(ClassResolver resolver, String location) {
052 this.resolver = resolver;
053 this.location = location;
054 }
055
056 public Source resolve(String href, String base) throws TransformerException {
057 if (ObjectHelper.isEmpty(href)) {
058 throw new TransformerException("include href is empty");
059 }
060
061 LOG.trace("Resolving URI with href: {} and base: {}", href, base);
062
063 if (href.startsWith("classpath:")) {
064 LOG.debug("Resolving URI from classpath: {}", href);
065
066 String name = ObjectHelper.after(href, ":");
067 InputStream is = resolver.loadResourceAsStream(name);
068 if (is == null) {
069 throw new TransformerException("Cannot find " + name + " in classpath");
070 }
071 return new StreamSource(is);
072 }
073
074 if (href.startsWith("file:")) {
075 LOG.debug("Resolving URI from file: {}", href);
076
077 String name = ObjectHelper.after(href, ":");
078 File file = new File(name);
079 if (!file.exists()) {
080 throw new TransformerException("Cannot find " + name + " in the file system");
081 }
082 return new StreamSource(file);
083 }
084
085 // okay then its relative to the starting location from the XSLT component
086 String path = FileUtil.onlyPath(location);
087 if (ObjectHelper.isEmpty(path)) {
088 // default to use classpath: location
089 path = "classpath:" + href;
090 return resolve(path, base);
091 } else {
092 // default to use classpath: location
093 path = "classpath:" + path + "/" + href;
094 return resolve(path, base);
095 }
096 }
097
098 }