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 */ 017package org.apache.camel.builder.xml; 018 019import java.io.IOException; 020import java.io.InputStream; 021 022import javax.xml.transform.Source; 023import javax.xml.transform.TransformerException; 024import javax.xml.transform.URIResolver; 025import javax.xml.transform.stream.StreamSource; 026 027import org.apache.camel.CamelContext; 028import org.apache.camel.util.FileUtil; 029import org.apache.camel.util.ObjectHelper; 030import org.apache.camel.util.ResourceHelper; 031import org.apache.camel.util.StringHelper; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034 035/** 036 * Camel specific {@link javax.xml.transform.URIResolver} which is capable of loading files 037 * from classpath, file system and more. 038 * <p/> 039 * You can prefix with: classpath, file, http, ref, or bean. 040 * classpath, file and http loads the resource using these protocols (classpath is default). 041 * ref will lookup the resource in the registry. 042 * bean will call a method on a bean to be used as the resource. 043 * For bean you can specify the method name after dot, eg bean:myBean.myMethod 044 * 045 * @version 046 */ 047public class XsltUriResolver implements URIResolver { 048 049 private static final Logger LOG = LoggerFactory.getLogger(XsltUriResolver.class); 050 051 private final CamelContext context; 052 private final String location; 053 private final String baseScheme; 054 055 public XsltUriResolver(CamelContext context, String location) { 056 this.context = context; 057 this.location = location; 058 if (ResourceHelper.hasScheme(location)) { 059 baseScheme = ResourceHelper.getScheme(location); 060 } else { 061 // default to use classpath 062 baseScheme = "classpath:"; 063 } 064 } 065 066 @Override 067 public Source resolve(String href, String base) throws TransformerException { 068 // supports the empty href 069 if (ObjectHelper.isEmpty(href)) { 070 href = location; 071 } 072 if (ObjectHelper.isEmpty(href)) { 073 throw new TransformerException("include href is empty"); 074 } 075 076 LOG.trace("Resolving URI with href: {} and base: {}", href, base); 077 078 String scheme = ResourceHelper.getScheme(href); 079 080 if (scheme != null) { 081 // need to compact paths for file/classpath as it can be relative paths using .. to go backwards 082 String hrefPath = StringHelper.after(href, scheme); 083 if ("file:".equals(scheme)) { 084 // compact path use file OS separator 085 href = scheme + FileUtil.compactPath(hrefPath); 086 } else if ("classpath:".equals(scheme)) { 087 // for classpath always use / 088 href = scheme + FileUtil.compactPath(hrefPath, '/'); 089 } 090 LOG.debug("Resolving URI from {}: {}", scheme, href); 091 092 InputStream is; 093 try { 094 is = ResourceHelper.resolveMandatoryResourceAsInputStream(context, href); 095 } catch (IOException e) { 096 throw new TransformerException(e); 097 } 098 return new StreamSource(is, href); 099 } 100 101 // if href and location is the same, then its the initial resolve 102 if (href.equals(location)) { 103 String path = baseScheme + href; 104 return resolve(path, base); 105 } 106 107 // okay then its relative to the starting location from the XSLT importing this one 108 String path = FileUtil.onlyPath(base); 109 if (ObjectHelper.isEmpty(path)) { 110 path = baseScheme + href; 111 return resolve(path, base); 112 } else { 113 if (ResourceHelper.hasScheme(path)) { 114 path = path + "/" + href; 115 } else { 116 path = baseScheme + path + "/" + href; 117 } 118 return resolve(path, base); 119 } 120 } 121 122}