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.component.validator; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.io.Reader; 022import java.util.HashMap; 023import java.util.Map; 024 025import org.w3c.dom.ls.LSInput; 026import org.w3c.dom.ls.LSResourceResolver; 027 028import org.apache.camel.CamelContext; 029import org.apache.camel.util.FileUtil; 030import org.apache.camel.util.ObjectHelper; 031import org.apache.camel.util.ResourceHelper; 032 033/** 034 * Default {@link LSResourceResolver} which can included schema resources. 035 */ 036public 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 return null; 121 } 122 123 @Override 124 public void setCharacterStream(Reader reader) { 125 // noop 126 } 127 128 @Override 129 public InputStream getByteStream() { 130 try { 131 return ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext.getClassResolver(), uri); 132 } catch (IOException e) { 133 throw ObjectHelper.wrapRuntimeCamelException(e); 134 } 135 } 136 137 @Override 138 public void setByteStream(InputStream inputStream) { 139 // noop 140 } 141 142 @Override 143 public String getStringData() { 144 InputStream is = getByteStream(); 145 return camelContext.getTypeConverter().convertTo(String.class, is); 146 } 147 148 @Override 149 public void setStringData(String stringData) { 150 // noop 151 } 152 153 @Override 154 public String getSystemId() { 155 return systemId; 156 } 157 158 @Override 159 public void setSystemId(String systemId) { 160 // noop 161 } 162 163 @Override 164 public String getPublicId() { 165 return publicId; 166 } 167 168 @Override 169 public void setPublicId(String publicId) { 170 // noop 171 } 172 173 @Override 174 public String getBaseURI() { 175 return baseURI; 176 } 177 178 @Override 179 public void setBaseURI(String baseURI) { 180 // noop 181 } 182 183 @Override 184 public String getEncoding() { 185 return null; 186 } 187 188 @Override 189 public void setEncoding(String encoding) { 190 // noop 191 } 192 193 @Override 194 public boolean getCertifiedText() { 195 return false; 196 } 197 198 @Override 199 public void setCertifiedText(boolean certifiedText) { 200 // noop 201 } 202 203 @Override 204 public String toString() { 205 return "DefaultLSInput[" + uri + "]"; 206 } 207 } 208 209}