1   package org.daisy.pipeline.file.saxon.impl;
2   
3   import java.net.URI;
4   import java.net.URISyntaxException;
5   import java.nio.file.Files;
6   
7   import net.sf.saxon.expr.XPathContext;
8   import net.sf.saxon.lib.ExtensionFunctionCall;
9   import net.sf.saxon.lib.ExtensionFunctionDefinition;
10  import net.sf.saxon.om.Sequence;
11  import net.sf.saxon.om.StructuredQName;
12  import net.sf.saxon.trans.XPathException;
13  import net.sf.saxon.type.BuiltInAtomicType;
14  import net.sf.saxon.value.BooleanValue;
15  import net.sf.saxon.value.SequenceType;
16  
17  import org.daisy.common.file.URLs;
18  import org.daisy.pipeline.file.FileUtils;
19  
20  import org.osgi.service.component.annotations.Component;
21  
22  @Component(
23  	name = "pf:file-exists",
24  	service = { ExtensionFunctionDefinition.class }
25  )
26  @SuppressWarnings("serial")
27  public class FileExists extends ExtensionFunctionDefinition {
28  
29  	private static final StructuredQName funcname = new StructuredQName(
30  		"pf",
31  		"http://www.daisy.org/ns/pipeline/functions",
32  		"file-exists");
33  
34  	@Override
35  	public SequenceType[] getArgumentTypes() {
36  		return new SequenceType[] { SequenceType.SINGLE_STRING };
37  	}
38  
39  	@Override
40  	public StructuredQName getFunctionQName() {
41  		return funcname;
42  	}
43  
44  	@Override
45  	public SequenceType getResultType(SequenceType[] arg0) {
46  		return SequenceType.SINGLE_BOOLEAN;
47  	}
48  
49  	@Override
50  	public ExtensionFunctionCall makeCallExpression() {
51  		return new ExtensionFunctionCall() {
52  
53  			@SuppressWarnings({ "unchecked", "rawtypes" })
54  			public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
55  				try {
56  					String uri = arguments[0].head().getStringValue();
57  					return new BooleanValue(exists(URLs.asURI(uri)), BuiltInAtomicType.BOOLEAN);
58  				} catch (Throwable e) {
59  					throw new XPathException("Unexpected error in pf:file-exists", e);
60  				}
61  			}
62  		};
63  	}
64  
65  	/**
66  	 * Whether the file or ZIP entry denoted by this absolute URI exists.
67  	 */
68  	private static boolean exists(URI uri) throws URISyntaxException {
69  		try {
70  			return Files.exists(FileUtils.asPath(uri));
71  		} catch (IllegalArgumentException e) {
72  			return false;
73  		}
74  	}
75  }