1 package org.collectionspace.services.imports.nuxeo;
3 import java.io.BufferedInputStream;
5 import java.io.FileFilter;
6 import java.io.FileInputStream;
7 import java.io.IOException;
8 import java.util.ArrayList;
11 import org.dom4j.Document;
12 import org.dom4j.DocumentException;
13 import org.dom4j.io.SAXReader;
15 import org.nuxeo.common.utils.FileTreeIterator;
16 import org.nuxeo.common.utils.FileUtils;
17 import org.nuxeo.common.utils.Path;
18 import org.nuxeo.ecm.core.api.impl.blob.StreamingBlob;
19 import org.nuxeo.ecm.core.io.ExportConstants;
20 import org.nuxeo.ecm.core.io.ExportedDocument;
21 import org.nuxeo.ecm.core.io.impl.AbstractDocumentReader;
22 import org.nuxeo.ecm.core.io.impl.ExportedDocumentImpl;
23 import org.nuxeo.runtime.services.streaming.FileSource;
24 import org.nuxeo.runtime.transaction.TransactionHelper;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
29 public class LoggedXMLDirectoryReader extends AbstractDocumentReader {
31 private static final int TIMEOUT_NEVER = 0;
32 private final Logger logger = LoggerFactory.getLogger(LoggedXMLDirectoryReader.class);
33 protected long timeoutMillis = TIMEOUT_NEVER;
34 protected int totalTimeLimitSecs = 0; // the number of seconds before we timeout
36 protected Document loadXML(File file) throws IOException {
37 String filename = file.getCanonicalPath();
39 if (logger.isTraceEnabled()) {
40 logger.trace("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename);
42 BufferedInputStream in = null;
44 in = new BufferedInputStream(new FileInputStream(file));
45 if (logger.isTraceEnabled()) {
46 logger.trace("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename+" :: DONE");
48 reportList.add("READ: "+filename);
49 return new SAXReader().read(in);
50 } catch (DocumentException e) {
51 IOException ioe = new IOException("Failed to read file document "
52 + file + ": " + e.getMessage());
53 ioe.setStackTrace(e.getStackTrace());
54 logger.error("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename+" :: ERROR");
55 reportList.add("ERROR: "+filename);
66 private FileTreeIterator iterator;
68 public LoggedXMLDirectoryReader(String sourcePath) {
69 this(new File(sourcePath), TIMEOUT_NEVER);
72 public LoggedXMLDirectoryReader(File source, int timeout) {
74 this.totalTimeLimitSecs = timeout;
75 this.timeoutMillis = System.currentTimeMillis() + (timeout * 1000); // set the timeout milliseconds time
78 iterator = new FileTreeIterator(source);
79 iterator.setFilter(new FileFilter() {
80 public boolean accept(File pathname) {
81 return pathname.isDirectory();
86 public Object getSource() {
90 public void setSource(File source) {
99 private List<String> reportList = new ArrayList<String>();
100 public String report(){
101 StringBuffer result = new StringBuffer();
102 for (String s: reportList){
103 result.append(s).append("\r\n");
105 return result.toString();
109 * Returns 'true' if we've timed out.
111 protected boolean hasTimedOut() {
112 boolean result = false;
114 if (totalTimeLimitSecs > 0 && System.currentTimeMillis() > timeoutMillis) {
123 public ExportedDocument read() throws IOException {
124 if (iterator.hasNext()) {
125 File dir = iterator.next();
129 // read document files
130 ExportedDocument xdoc = new ExportedDocumentImpl();
131 for (File file : dir.listFiles()) {
133 if (hasTimedOut() == true) { // Check to see if the current transaction has already timed out.
134 TransactionHelper.setTransactionRollbackOnly();
135 String errMsg = String.format("Import transaction timed out by exceeding %d seconds.", this.totalTimeLimitSecs);
136 throw new IOException(errMsg);
138 String name = file.getName();
139 if (ExportConstants.DOCUMENT_FILE.equals(name)) {
140 Document doc = loadXML(file);
141 xdoc.setDocument(doc);
142 Path relPath = computeRelativePath(dir);
143 xdoc.setPath(relPath);
144 reportList.add(relPath.toString());
145 } else if (name.endsWith(".xml")) {
147 FileUtils.getFileNameNoExt(file.getName()),
149 } else { // presume a blob
150 xdoc.putBlob(file.getName(), new StreamingBlob(
151 new FileSource(file)));
160 /*NXP-1688 Rux: the path was somehow left over when migrated from
161 core 1.3.4 to 1.4.0. Pull back.*/
162 private Path computeRelativePath(File file) {
163 /*NXP-2507 Rux: preserve directory structure with slashes instead OS name separator*/
165 file.getAbsolutePath().substring(source.getAbsolutePath().length());
166 subPathS = subPathS.replace(File.separatorChar, '/');
167 return new Path(subPathS);