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 = getUri(systemId); 069 resourceURI = relatedURI.intern(); 070 } else { 071 String relatedPath = relatedURIMap.get(baseURI); 072 if (relatedPath == null) { 073 relatedPath = FileUtil.onlyPath(relatedURI).intern(); 074 relatedURI = FileUtil.onlyPath(relatedURI) + "/" + systemId; 075 resourceURI = relatedURI.intern(); 076 relatedURIMap.put(baseURI, relatedPath); 077 } else { 078 resourceURI = relatedPath + "/" + systemId; 079 } 080 } 081 return new DefaultLSInput(publicId, systemId, baseURI, resourceURI); 082 } 083 084 private final class DefaultLSInput implements LSInput { 085 086 private final String publicId; 087 private final String systemId; 088 private final String baseURI; 089 private final String relatedURI; 090 private final String uri; 091 092 093 private DefaultLSInput(String publicId, String systemId, String basedURI, String relatedURI) { 094 this.publicId = publicId; 095 this.systemId = systemId; 096 this.baseURI = basedURI; 097 this.relatedURI = relatedURI; 098 this.uri = getInputUri(); 099 } 100 101 102 private String getInputUri() { 103 // find the xsd with relative path 104 if (ObjectHelper.isNotEmpty(relatedURI)) { 105 try { 106 ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext.getClassResolver(), relatedURI); 107 return relatedURI; 108 } catch (IOException e) { 109 // ignore the exception 110 } 111 } 112 // don't use the relative path 113 return getUri(systemId); 114 } 115 116 @Override 117 public Reader getCharacterStream() { 118 InputStream is = getByteStream(); 119 return camelContext.getTypeConverter().convertTo(Reader.class, is); 120 } 121 122 @Override 123 public void setCharacterStream(Reader reader) { 124 // noop 125 } 126 127 @Override 128 public InputStream getByteStream() { 129 try { 130 return ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext.getClassResolver(), uri); 131 } catch (IOException e) { 132 throw ObjectHelper.wrapRuntimeCamelException(e); 133 } 134 } 135 136 @Override 137 public void setByteStream(InputStream inputStream) { 138 // noop 139 } 140 141 @Override 142 public String getStringData() { 143 InputStream is = getByteStream(); 144 return camelContext.getTypeConverter().convertTo(String.class, is); 145 } 146 147 @Override 148 public void setStringData(String stringData) { 149 // noop 150 } 151 152 @Override 153 public String getSystemId() { 154 return systemId; 155 } 156 157 @Override 158 public void setSystemId(String systemId) { 159 // noop 160 } 161 162 @Override 163 public String getPublicId() { 164 return publicId; 165 } 166 167 @Override 168 public void setPublicId(String publicId) { 169 // noop 170 } 171 172 @Override 173 public String getBaseURI() { 174 return baseURI; 175 } 176 177 @Override 178 public void setBaseURI(String baseURI) { 179 // noop 180 } 181 182 @Override 183 public String getEncoding() { 184 return null; 185 } 186 187 @Override 188 public void setEncoding(String encoding) { 189 // noop 190 } 191 192 @Override 193 public boolean getCertifiedText() { 194 return false; 195 } 196 197 @Override 198 public void setCertifiedText(boolean certifiedText) { 199 // noop 200 } 201 202 @Override 203 public String toString() { 204 return "DefaultLSInput[" + uri + "]"; 205 } 206 } 207 208 209 210 }