1 package org.daisy.pipeline.file.calabash.impl;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.net.URI;
9 import java.util.Map;
10
11 import net.sf.saxon.s9api.QName;
12 import net.sf.saxon.s9api.SaxonApiException;
13
14 import org.daisy.common.file.URLs;
15 import org.daisy.common.xproc.calabash.XProcStep;
16 import org.daisy.common.xproc.calabash.XProcStepProvider;
17 import org.daisy.common.xproc.XProcMonitor;
18
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 import com.google.common.io.ByteStreams;
23
24 import com.xmlcalabash.core.XProcConstants;
25 import com.xmlcalabash.core.XProcException;
26 import com.xmlcalabash.core.XProcRuntime;
27 import com.xmlcalabash.io.WritablePipe;
28 import com.xmlcalabash.library.DefaultStep;
29 import com.xmlcalabash.model.RuntimeValue;
30 import com.xmlcalabash.runtime.XAtomicStep;
31 import com.xmlcalabash.util.TreeWriter;
32
33 import org.osgi.service.component.annotations.Component;
34
35
36
37
38 @Component(
39 name = "pxi:copy-resource",
40 service = { XProcStepProvider.class },
41 property = { "type:String={http://www.daisy.org/ns/pipeline/xproc/internal}copy-resource" }
42 )
43 public class CopyResourceProvider implements XProcStepProvider {
44
45
46 Logger logger = LoggerFactory.getLogger(this.getClass());
47
48
49
50
51 @Override
52 public XProcStep newStep(XProcRuntime runtime, XAtomicStep step, XProcMonitor monitor, Map<String,String> properties) {
53 return new CopyResource(runtime, step);
54 }
55
56
57
58
59 public void activate() {
60 logger.trace("Activating px:copy-resource provider");
61 }
62
63
64
65
66
67
68 public static class CopyResource extends DefaultStep implements XProcStep {
69 private static final QName _href = new QName("href");
70 private static final QName _target = new QName("target");
71 private static final QName _fail_on_error = new QName("fail-on-error");
72 private static final int bufsize = 8192;
73
74 private WritablePipe result = null;
75
76
77
78
79 public CopyResource(XProcRuntime runtime, XAtomicStep step) {
80 super(runtime,step);
81 }
82
83 public void setOutput(String port, WritablePipe pipe) {
84 result = pipe;
85 }
86
87 public void reset() {
88 result.resetWriter();
89 }
90
91 public void run() throws SaxonApiException {
92 super.run();
93
94 if (runtime.getSafeMode()) {
95 throw XProcException.dynamicError(21);
96 }
97
98 boolean failOnError = getOption(_fail_on_error, true);
99
100
101 RuntimeValue href = getOption(_href);
102 URI sourceUri= URLs.resolve(href.getBaseURI(), URLs.asURI(href.getString()));
103
104 href = getOption(_target);
105 URI destUri = URLs.resolve(href.getBaseURI(), URLs.asURI(href.getString()));
106
107 File target=this.getFile(destUri,sourceUri);
108
109 TreeWriter tree = new TreeWriter(runtime);
110 tree.startDocument(step.getNode().getBaseURI());
111 tree.addStartElement(XProcConstants.c_result);
112 tree.startContent();
113
114 tree.addText(target.toURI().toASCIIString());
115
116 this.copy(sourceUri,target);
117
118 tree.addEndElement();
119 tree.endDocument();
120
121 result.write(tree.getResult());
122 }
123
124 File getFile(URI destUri,URI sourceUri){
125 File target=null;
126 if (!"file".equals(destUri.getScheme())) {
127 throw new XProcException(step, "Only file: scheme URIs are supported by taget.");
128 } else {
129 target = new File(destUri.getPath());
130 }
131
132 if (target.isDirectory()) {
133 int idx=sourceUri.getPath().lastIndexOf('/');
134 if(idx>-1){
135 target = new File(target, sourceUri.getPath().substring(idx));
136 }else{
137 target = new File(target, sourceUri.getPath());
138 }
139 if (target.isDirectory()) {
140 throw new XProcException(step, "Cannot copy: target is a directory: " + target.getAbsolutePath());
141 }
142 }
143 return target;
144
145 }
146
147 void copy(URI sourceUri,File target){
148
149 try {
150 InputStream src = sourceUri.toURL().openStream();
151 FileOutputStream dst = new FileOutputStream(target);
152 ByteStreams.copy(src,dst);
153 src.close();
154 dst.close();
155 } catch (FileNotFoundException fnfe) {
156 throw new XProcException(step, fnfe);
157 } catch (IOException ioe) {
158 throw new XProcException(step, ioe);
159 }
160 }
161 }
162
163 }
164