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.component.validator; 018 019 import java.io.IOException; 020 import java.io.InputStream; 021 import java.io.Reader; 022 import java.util.HashMap; 023 import java.util.Map; 024 025 import org.w3c.dom.ls.LSInput; 026 import org.w3c.dom.ls.LSResourceResolver; 027 028 import org.apache.camel.CamelContext; 029 import org.apache.camel.util.FileUtil; 030 import org.apache.camel.util.ObjectHelper; 031 import org.apache.camel.util.ResourceHelper; 032 033 /** 034 * Default {@link LSResourceResolver} which can included schema resources. 035 */ 036 public class DefaultLSResourceResolver implements LSResourceResolver { 037 038 private final CamelContext camelContext; 039 private final String resourceUri; 040 private final String resourcePath; 041 private String relatedURI; 042 private Map<String, String> relatedURIMap = new HashMap<String, String>(); 043 044 public DefaultLSResourceResolver(CamelContext camelContext, String resourceUri) { 045 this.camelContext = camelContext; 046 this.resourceUri = resourceUri; 047 this.resourcePath = FileUtil.onlyPath(resourceUri); 048 } 049 050 private String getUri(String systemId) { 051 if (resourcePath != null) { 052 return FileUtil.onlyPath(resourceUri) + "/" + systemId; 053 } else { 054 return systemId; 055 } 056 } 057 058 @Override 059 public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { 060 // systemId should be mandatory 061 if (systemId == null) { 062 throw new IllegalArgumentException(String.format("Resource: %s refers an invalid resource without SystemId." 063 + " Invalid resource has type: %s, namespaceURI: %s, publicId: %s, systemId: %s, baseURI: %s", resourceUri, type, namespaceURI, publicId, systemId, baseURI)); 064 } 065 String resourceURI = null; 066 // Build up the relative path for using relatedURI and baseURI 067 if (baseURI == null) { 068 relatedURI = FileUtil.compactPath(getUri(systemId), '/'); 069 resourceURI = relatedURI; 070 } else { 071 String relatedPath = relatedURIMap.get(baseURI); 072 if (relatedPath == null) { 073 relatedPath = FileUtil.onlyPath(relatedURI); 074 if (relatedPath == null) { 075 relatedPath = ""; 076 } 077 relatedURI = FileUtil.compactPath(FileUtil.onlyPath(relatedURI) + "/" + systemId, '/'); 078 resourceURI = relatedURI; 079 relatedURIMap.put(baseURI, relatedPath); 080 } else { 081 resourceURI = FileUtil.compactPath(relatedPath + "/" + systemId, '/'); 082 relatedURI = resourceURI; 083 } 084 } 085 return new DefaultLSInput(publicId, systemId, baseURI, resourceURI); 086 } 087 088 private final class DefaultLSInput implements LSInput { 089 090 private final String publicId; 091 private final String systemId; 092 private final String baseURI; 093 private final String relatedURI; 094 private final String uri; 095 096 private DefaultLSInput(String publicId, String systemId, String basedURI, String relatedURI) { 097 this.publicId = publicId; 098 this.systemId = systemId; 099 this.baseURI = basedURI; 100 this.relatedURI = relatedURI; 101 this.uri = getInputUri(); 102 } 103 104 private String getInputUri() { 105 // find the xsd with relative path 106 if (ObjectHelper.isNotEmpty(relatedURI)) { 107 try { 108 ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext.getClassResolver(), relatedURI); 109 return relatedURI; 110 } catch (IOException e) { 111 // ignore the exception 112 } 113 } 114 // don't use the relative path 115 return getUri(systemId); 116 } 117 118 @Override 119 public Reader getCharacterStream() { 120 InputStream is = getByteStream(); 121 return camelContext.getTypeConverter().convertTo(Reader.class, is); 122 } 123 124 @Override 125 public void setCharacterStream(Reader reader) { 126 // noop 127 } 128 129 @Override 130 public InputStream getByteStream() { 131 try { 132 return ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext.getClassResolver(), uri); 133 } catch (IOException e) { 134 throw ObjectHelper.wrapRuntimeCamelException(e); 135 } 136 } 137 138 @Override 139 public void setByteStream(InputStream inputStream) { 140 // noop 141 } 142 143 @Override 144 public String getStringData() { 145 InputStream is = getByteStream(); 146 return camelContext.getTypeConverter().convertTo(String.class, is); 147 } 148 149 @Override 150 public void setStringData(String stringData) { 151 // noop 152 } 153 154 @Override 155 public String getSystemId() { 156 return systemId; 157 } 158 159 @Override 160 public void setSystemId(String systemId) { 161 // noop 162 } 163 164 @Override 165 public String getPublicId() { 166 return publicId; 167 } 168 169 @Override 170 public void setPublicId(String publicId) { 171 // noop 172 } 173 174 @Override 175 public String getBaseURI() { 176 return baseURI; 177 } 178 179 @Override 180 public void setBaseURI(String baseURI) { 181 // noop 182 } 183 184 @Override 185 public String getEncoding() { 186 return null; 187 } 188 189 @Override 190 public void setEncoding(String encoding) { 191 // noop 192 } 193 194 @Override 195 public boolean getCertifiedText() { 196 return false; 197 } 198 199 @Override 200 public void setCertifiedText(boolean certifiedText) { 201 // noop 202 } 203 204 @Override 205 public String toString() { 206 return "DefaultLSInput[" + uri + "]"; 207 } 208 } 209 210 }