1 package pl.psnc.dl.ege;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.OutputStream;
9 import java.net.URI;
10 import java.net.URL;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.UUID;
15 import java.util.regex.Pattern;
16 import java.util.zip.ZipException;
17
18 import javax.xml.transform.stream.StreamSource;
19
20 import net.sf.saxon.s9api.DocumentBuilder;
21 import net.sf.saxon.s9api.Processor;
22 import net.sf.saxon.s9api.SaxonApiException;
23 import net.sf.saxon.s9api.Serializer;
24 import net.sf.saxon.s9api.XsltCompiler;
25 import net.sf.saxon.s9api.XsltExecutable;
26 import net.sf.saxon.s9api.XsltTransformer;
27
28 import org.xml.sax.SAXNotRecognizedException;
29 import org.xml.sax.SAXNotSupportedException;
30
31 import pl.psnc.dl.ege.utils.EGEIOUtils;
32 import pl.psnc.dl.ege.MultiXslOutputResolver;
33 import pl.psnc.dl.ege.component.ConfigurableConverter;
34 import pl.psnc.dl.ege.configuration.EGEConfigurationManager;
35 import pl.psnc.dl.ege.configuration.EGEConstants;
36 import pl.psnc.dl.ege.exception.ConverterException;
37 import pl.psnc.dl.ege.exception.EGEException;
38 import pl.psnc.dl.ege.types.ConversionActionArguments;
39 import pl.psnc.dl.ege.types.DataType;
40 import pl.psnc.dl.ege.utils.IOResolver;
41
42
43
44
45
46
47
48
49
50
51
52
53 public class MultiXslConverter implements ConfigurableConverter {
54
55 private static final String EAD = "EAD";
56
57 private static final String MASTER = "MASTER";
58
59
60
61
62 private URI xslUri;
63
64 private URI defaultUri = null;
65
66 private final IOResolver ior = EGEConfigurationManager.getInstance()
67 .getStandardIOResolver();
68
69
70
71
72 private List<ConversionActionArguments> possibleConversions = new ArrayList<ConversionActionArguments>();
73
74 public void convert(InputStream inputStream, OutputStream outputStream,
75 ConversionActionArguments conversionDataTypes)
76 throws ConverterException, IOException {
77 if (!isSupported(conversionDataTypes)) {
78 throw new ConverterException(
79 ConverterException.UNSUPPORTED_CONVERSION_TYPES);
80 }
81 File inTempDir = prepareTempDir();
82 File outTempDir = null;
83 try {
84 if (conversionDataTypes.getInputType().getFormat().equals(EAD)) {
85 outTempDir = performEADTransformation(prepareInputData(
86 inputStream, inTempDir));
87 } else {
88 outTempDir = performStandardTransformation(prepareInputData(
89 inputStream, inTempDir));
90 }
91 ior.compressData(outTempDir, outputStream);
92 } catch (ZipException ex) {
93 throw new ConverterException(
94 "Error during EAD conversion : probably wrong input data.");
95 } catch (SaxonApiException ex) {
96 ex.printStackTrace();
97 throw new ConverterException(ex.getMessage());
98 } catch (Exception ex) {
99 ex.printStackTrace();
100 throw new ConverterException(ex.getMessage());
101 } finally {
102 if (inTempDir != null && inTempDir.exists())
103 EGEIOUtils.deleteDirectory(inTempDir);
104 if (outTempDir != null && outTempDir.exists())
105 EGEIOUtils.deleteDirectory(outTempDir);
106 }
107 }
108
109
110
111
112 private File prepareTempDir() {
113 File inTempDir = null;
114 String uid = UUID.randomUUID().toString();
115 inTempDir = new File(EGEConstants.TEMP_PATH + File.separator + uid
116 + File.separator);
117 inTempDir.mkdir();
118 return inTempDir;
119 }
120
121
122
123
124 private InputStream prepareInputData(InputStream inputStream, File inTempDir)
125 throws IOException, ConverterException {
126 ior.decompressStream(inputStream, inTempDir);
127
128 File sFile = searchForData(inTempDir, "^.*\\.((?i)xml)$");
129 if (sFile == null) {
130
131 sFile = searchForData(inTempDir, "^.*");
132 if (sFile == null) {
133 throw new ConverterException(
134 "No file data was found for conversion!");
135 }
136 }
137 FileInputStream fis = new FileInputStream(sFile);
138 return fis;
139 }
140
141 private File searchForData(File dir, String regex) {
142 for (File f : dir.listFiles()) {
143 if (!f.isDirectory() && Pattern.matches(regex, f.getName())) {
144 return f;
145 } else if (f.isDirectory()) {
146 File sf = searchForData(f, regex);
147 if (sf != null) {
148 return sf;
149 }
150 }
151 }
152 return null;
153 }
154
155
156
157
158
159 private File performEADTransformation(InputStream inputStream)
160 throws SaxonApiException, IOException, ConverterException {
161 InputStream is = null;
162 try {
163 Processor proc = new Processor(false);
164 XsltCompiler comp = proc.newXsltCompiler();
165 URL xslURL = xslUri.toURL();
166 try{
167 is = xslURL.openStream();
168 }catch(IOException ex){
169 if(defaultUri != null){
170 xslURL = defaultUri.toURL();
171 is = xslURL.openStream();
172 }else{
173 throw ex;
174 }
175 }
176
177 String uid = UUID.randomUUID().toString();
178 File tempDir = new File(System.getProperty("java.io.tmpdir")
179 + File.separator + uid + File.separator);
180 tempDir.mkdir();
181
182
183 proc.getUnderlyingConfiguration().setOutputURIResolver(
184 new MultiXslOutputResolver(uid));
185 XsltExecutable exec = comp.compile(new StreamSource(is));
186 XsltTransformer transformer = exec.load();
187 transformer.setInitialContextNode(proc.newDocumentBuilder().build(
188 new StreamSource(inputStream)));
189 Serializer result = new Serializer();
190
191
192 File dummyResult = new File(tempDir.getPath() + ".xml");
193 FileOutputStream dummyOs = new FileOutputStream(dummyResult);
194
195 result.setOutputStream(dummyOs);
196 transformer.setDestination(result);
197 transformer.transform();
198 dummyOs.close();
199 dummyResult.delete();
200
201 return tempDir;
202
203 } finally {
204 if (is != null) {
205 try {
206 is.close();
207 } catch (Exception ex) {
208
209 }
210 }
211 try {
212 inputStream.close();
213 } catch (Exception ex) {
214
215 }
216 }
217 }
218
219
220
221
222 private File performStandardTransformation(InputStream inputStream)
223 throws IOException, SaxonApiException, SAXNotRecognizedException,
224 SAXNotSupportedException {
225 InputStream is = null;
226 File tempDir = null;
227 FileOutputStream fos = null;
228 try {
229 String uid = UUID.randomUUID().toString();
230 tempDir = new File(EGEConstants.TEMP_PATH + File.separator + uid
231 + File.separator);
232 tempDir.mkdir();
233 fos = new FileOutputStream(new File(tempDir + File.separator
234 + "stand.xml"));
235 Processor proc = new Processor(false);
236 proc.getUnderlyingConfiguration().setValidation(false);
237 proc.getUnderlyingConfiguration().getSourceParser()
238 .setErrorHandler(null);
239 XsltCompiler comp = proc.newXsltCompiler();
240 URL xslURL = xslUri.toURL();
241 try{
242 is = xslURL.openStream();
243 }catch(IOException ex){
244 if(defaultUri != null){
245 xslURL = defaultUri.toURL();
246 is = xslURL.openStream();
247 }else{
248 throw ex;
249 }
250 }
251 XsltExecutable exec = comp.compile(new StreamSource(is));
252 XsltTransformer transformer = exec.load();
253 DocumentBuilder documentBuilder = proc.newDocumentBuilder();
254 documentBuilder.setDTDValidation(false);
255 transformer.setInitialContextNode(documentBuilder
256 .build(new StreamSource(inputStream)));
257 Serializer result = new Serializer();
258 result.setOutputStream(fos);
259 transformer.setDestination(result);
260 transformer.transform();
261 return tempDir;
262 } finally {
263 if (fos != null) {
264 fos.close();
265 }
266 if (is != null) {
267 is.close();
268 }
269 inputStream.close();
270 }
271 }
272
273 public List<ConversionActionArguments> getPossibleConversions() {
274 return possibleConversions;
275 }
276
277 private boolean isSupported(ConversionActionArguments cadtCheck) {
278 for (ConversionActionArguments cadt : possibleConversions) {
279 if (cadt.equals(cadtCheck)) {
280 return true;
281 }
282 }
283 return false;
284 }
285
286 public void configure(Map<String, String> params) throws EGEException {
287 try {
288 xslUri = new URI(params.get("xsluri"));
289 String iFormat = params.get("iFormat");
290 StringBuffer sb = new StringBuffer();
291 sb.append("jar:file:");
292 sb.append(getClass().getProtectionDomain().getCodeSource()
293 .getLocation().getFile());
294
295 if (EAD.equals(iFormat)) {
296 sb.append("!/ead2enrich/ead2enrich.xsl");
297 defaultUri = new URI(sb.toString());
298 } else if (MASTER.equals(iFormat)) {
299 sb.append("!/master2enrich/master2enrich.xsl");
300 defaultUri = new URI(sb.toString());
301 }
302 String iMIME = params.get("iMimeType");
303 String oFormat = params.get("oFormat");
304 String oMIME = params.get("oMimeType");
305 ConversionActionArguments cadt = new ConversionActionArguments(
306 new DataType(iFormat, iMIME), new DataType(oFormat, oMIME));
307 possibleConversions.add(cadt);
308 } catch (NullPointerException ex) {
309 throw new EGEException(EGEException.WRONG_CONFIGURATION
310 + " 'null' value of parameter.");
311 } catch (Exception ex) {
312 throw new EGEException(EGEException.WRONG_CONFIGURATION + " "
313 + ex.getMessage());
314 }
315 }
316
317 }