1 package net.sf.saxon.functions; 2 3 import net.sf.saxon.*; 4 import net.sf.saxon.event.Builder; 5 import net.sf.saxon.event.Stripper; 6 import net.sf.saxon.expr.MappingFunction; 7 import net.sf.saxon.expr.MappingIterator; 8 import net.sf.saxon.expr.XPathContext; 9 import net.sf.saxon.om.*; 10 import net.sf.saxon.pattern.NodeKindTest; 11 import net.sf.saxon.trans.DynamicError; 12 import net.sf.saxon.trans.XPathException; 13 import net.sf.saxon.value.ObjectValue; 14 import org.xml.sax.XMLReader ; 15 16 import javax.xml.transform.Source ; 17 import javax.xml.transform.TransformerException ; 18 import javax.xml.transform.stream.StreamSource ; 19 import java.io.File ; 20 import java.io.FilenameFilter ; 21 import java.net.URI ; 22 import java.net.URISyntaxException ; 23 24 48 49 public class StandardCollectionURIResolver implements CollectionURIResolver, MappingFunction { 50 51 69 70 public SequenceIterator resolve(String href, String base, XPathContext context) throws XPathException { 71 72 if (href == null) { 73 return null; 75 } 76 77 if (base == null) { 78 base = StandardURIResolver.tryToExpand(base); 79 if (base == null) { 80 DynamicError err = new DynamicError( 81 "Cannot resolve relative URI: no base URI available"); 82 err.setXPathContext(context); 83 throw err; 84 } 85 } 86 87 URI resolvedURI; 88 URIQueryParameters params = null; 89 try { 90 URI relative = new URI (href); 91 String query = relative.getQuery(); 92 if (query != null) { 93 params = new URIQueryParameters(query, context.getController().getConfiguration()); 94 int q = href.indexOf('?'); 95 href = href.substring(0, q); 96 } 97 resolvedURI = new URI (base).resolve(href); 98 } catch (URISyntaxException e) { 99 DynamicError err = new DynamicError( 100 "Invalid URI " + Err.wrap(href) + " passed to collection() function"); 101 err.setXPathContext(context); 102 throw err; 103 } 104 105 if ("file".equals(resolvedURI.getScheme())) { 106 File file = new File (resolvedURI); 107 if (!file.exists()) { 108 DynamicError err = new DynamicError( 109 "The file or directory " + resolvedURI + " does not exist"); 110 err.setXPathContext(context); 111 throw err; 112 } 113 if (file.isDirectory()) { 114 return directoryContents(file, params, context); 115 } 116 } 117 return catalogContents(resolvedURI, params, context); 118 119 } 120 121 private SequenceIterator directoryContents(File directory, URIQueryParameters params, XPathContext context) { 122 123 FilenameFilter filter = null; 124 125 if (params != null) { 126 FilenameFilter f = params.getFilenameFilter(); 127 if (f != null) { 128 filter = f; 129 } 130 } 131 132 File [] files; 133 if (filter == null) { 134 files = directory.listFiles(); 135 } else { 136 files = directory.listFiles(filter); 137 } 138 139 ObjectValue[] fileValues = new ObjectValue[files.length]; 140 for (int f=0; f<files.length; f++) { 141 fileValues[f] = new ObjectValue(files[f]); 142 } 143 144 FileExpander expander = new FileExpander(params); 145 return new MappingIterator(new ArrayIterator(fileValues), expander, context); 146 } 147 148 private SequenceIterator catalogContents(URI catalogFile, URIQueryParameters params, XPathContext context) 149 throws XPathException { 150 151 DocumentInfo catalog = 152 (DocumentInfo) Document.makeDoc(catalogFile.toString(), null, context, null); 153 if (catalog==null) { 154 DynamicError err = new DynamicError("Failed to load collection catalogue " + catalogFile); 156 err.setXPathContext(context); 157 throw err; 158 } 159 160 162 SequenceIterator iter = 163 catalog.iterateAxis(Axis.CHILD, NodeKindTest.ELEMENT); 164 NodeInfo top; 165 while (true) { 166 top = (NodeInfo)iter.next(); 167 if (top == null) break; 168 if (!("collection".equals(top.getLocalPart()) && 169 top.getURI().equals("") )) { 170 DynamicError err = new DynamicError("collection catalogue must contain top-level element <collection>"); 171 err.setXPathContext(context); 172 throw err; 173 } 174 break; 175 } 176 177 SequenceIterator documents = 178 top.iterateAxis(Axis.CHILD, NodeKindTest.ELEMENT); 179 180 return new MappingIterator(documents, this, context); 181 } 182 183 184 185 195 196 public Object map(Item item, XPathContext context) throws XPathException { 197 NodeInfo element = (NodeInfo)item; 198 if (!("doc".equals(element.getLocalPart()) && 199 element.getURI().equals("") )) { 200 DynamicError err = new DynamicError( 201 "children of <collection> element must be <doc> elements"); 202 err.setXPathContext(context); 203 throw err; 204 } 205 String href = Navigator.getAttributeValue(element, "", "href"); 206 if (href==null) { 207 DynamicError err = new DynamicError( 208 "\"<doc> element in catalogue has no @href attribute\""); 209 err.setXPathContext(context); 210 throw err; 211 } 212 213 NodeInfo target = Document.makeDoc(href, element.getBaseURI(), context, null); 214 return target; 215 } 216 217 private static class FileExpander implements MappingFunction { 218 219 private URIQueryParameters params; 220 boolean recurse = false; 221 boolean strip = false; 222 int validation = Validation.STRIP; 223 XMLReader parser = null; 224 int onError = URIQueryParameters.ON_ERROR_FAIL; 225 FilenameFilter filter = null; 226 227 public FileExpander(URIQueryParameters params) { 228 this.params = params; 229 if (params != null) { 230 FilenameFilter f = params.getFilenameFilter(); 231 if (f != null) { 232 filter = f; 233 } 234 Boolean r = params.getRecurse(); 235 if (r != null) { 236 recurse = r.booleanValue(); 237 } 238 Integer v = params.getValidationMode(); 239 if (v != null) { 240 validation = v.intValue(); 241 } 242 Boolean s = params.getStripSpace(); 243 if (s != null) { 244 strip = s.booleanValue(); 245 } 246 Integer e = params.getOnError(); 247 if (e != null) { 248 onError = e.intValue(); 249 } 250 XMLReader p = params.getXMLReader(); 251 if (p != null) { 252 parser = p; 253 } 254 } 255 256 } 257 258 270 271 public Object map(Item item, XPathContext context) throws XPathException { 272 File file = (File )((ObjectValue)item).getObject(); 273 if (file.isDirectory()) { 274 if (recurse) { 275 File [] files; 276 if (filter == null) { 277 files = file.listFiles(); 278 } else { 279 files = file.listFiles(filter); 280 } 281 282 ObjectValue[] fileValues = new ObjectValue[files.length]; 283 for (int f=0; f<files.length; f++) { 284 fileValues[f] = new ObjectValue(files[f]); 285 } 286 287 FileExpander expander = new FileExpander(params); 288 return new MappingIterator(new ArrayIterator(fileValues), expander, context); 289 } else { 290 return null; 291 } 292 } else { 293 try { 294 Source source = new StreamSource (file.toURI().toString()); 295 if (validation != Validation.STRIP && validation != Validation.PRESERVE) { 296 source = AugmentedSource.makeAugmentedSource(source); 297 ((AugmentedSource)source).setSchemaValidationMode(validation); 298 } 299 if (parser != null) { 300 source = AugmentedSource.makeAugmentedSource(source); 301 ((AugmentedSource)source).setXMLReader(parser); 302 } 303 Stripper stripper = null; 304 305 if (strip) { 306 stripper = AllElementStripper.getInstance(); 307 stripper.setStripAll(); 308 } 309 Configuration config = context.getController().getConfiguration(); 310 NodeInfo contextNode = Builder.build(source, stripper, config); 311 return contextNode.getDocumentRoot(); 312 } catch (XPathException err) { 313 if (onError == URIQueryParameters.ON_ERROR_IGNORE) { 314 return null; 315 } else if (onError == URIQueryParameters.ON_ERROR_WARNING) { 316 try { 317 context.getController().getErrorListener().warning(err); 318 } catch (TransformerException err2) { 319 } 321 return null; 322 } else { 323 throw err; 324 } 325 } 326 } 327 } 328 } 329 330 331 332 333 } 334 335 353 | Popular Tags |