001/*
002 * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 * $Id$
020 */
021package org.nuxeo.ecm.platform.scanimporter.processor;
022
023import java.io.File;
024import java.io.IOException;
025import java.lang.reflect.Constructor;
026import java.nio.file.Files;
027import java.nio.file.Path;
028import java.util.ArrayList;
029import java.util.List;
030import java.util.concurrent.locks.ReentrantReadWriteLock;
031
032import org.apache.commons.logging.Log;
033import org.apache.commons.logging.LogFactory;
034import org.nuxeo.ecm.core.api.NuxeoException;
035import org.nuxeo.ecm.platform.importer.base.GenericMultiThreadedImporter;
036import org.nuxeo.ecm.platform.importer.factories.ImporterDocumentModelFactory;
037import org.nuxeo.ecm.platform.importer.log.BasicLogger;
038import org.nuxeo.ecm.platform.importer.service.DefaultImporterService;
039import org.nuxeo.ecm.platform.importer.source.FileSourceNode;
040import org.nuxeo.ecm.platform.importer.source.SourceNode;
041import org.nuxeo.ecm.platform.scanimporter.service.ImporterConfig;
042import org.nuxeo.ecm.platform.scanimporter.service.ScannedFileMapperService;
043import org.nuxeo.runtime.api.Framework;
044
045/**
046 * Setup the importer with the rights factories
047 *
048 * @author Thierry Delprat
049 */
050public class ScannedFileImporter {
051
052    private static final Log log = LogFactory.getLog(ScannedFileImporter.class);
053
054    protected static List<String> processedDescriptors;
055
056    protected static ReentrantReadWriteLock processedLock = new ReentrantReadWriteLock();
057
058    public ScannedFileImporter() {
059        processedDescriptors = new ArrayList<String>();
060    }
061
062    public static void addProcessedDescriptor(String fileDesc) {
063        processedLock.writeLock().lock();
064        try {
065            processedDescriptors.add(fileDesc);
066            if (processedDescriptors.size() % 100 == 0) {
067                doCleanUp();
068            }
069        } finally {
070            processedLock.writeLock().unlock();
071        }
072    }
073
074    protected static void doCleanUp() {
075
076        ScannedFileMapperService sfms = Framework.getService(ScannedFileMapperService.class);
077        ImporterConfig config = sfms.getImporterConfig();
078        File outDir = null;
079
080        if (config != null) {
081            String outPath = config.getProcessedPath();
082            if (outPath != null) {
083                outDir = new File(outPath);
084                if (!outDir.exists()) {
085                    outDir = null;
086                }
087            }
088        }
089        for (String fileDesc : processedDescriptors) {
090            File file = new File(fileDesc);
091            if (file.exists()) {
092                if (outDir == null) {
093                    file.delete();
094                } else {
095                    Path source = file.toPath();
096                    Path target = outDir.toPath().resolve(file.getName());
097                    try {
098                        Files.move(source, target);
099                    } catch (IOException e) {
100                        log.error("An exception occured while moving " + source.getFileName(), e);
101                    }
102                }
103            }
104        }
105        processedDescriptors = new ArrayList<String>();
106    }
107
108    public void doImport() {
109
110        ScannedFileMapperService sfms = Framework.getService(ScannedFileMapperService.class);
111
112        ImporterConfig config = sfms.getImporterConfig();
113        if (config == null) {
114            log.error("No configuration can be found, exit importer");
115            return;
116        }
117        File folder = new File(config.getSourcePath());
118
119        doImport(folder, config);
120    }
121
122    public void doImport(File folder, ImporterConfig config) {
123
124        if (folder == null || !folder.exists()) {
125            throw new NuxeoException("Unable to access source folder " + folder);
126        }
127        if (config.getTargetPath() == null) {
128            throw new NuxeoException("target path must be set");
129        }
130
131        if (folder.listFiles().length == 0) {
132            log.info("Nothing to import exiting");
133            return;
134        }
135
136        log.info("Starting import process on path " + config.getTargetPath() + " from source "
137                + folder.getAbsolutePath());
138        SourceNode src = initSourceNode(folder);
139
140        ScanedFileSourceNode.useXMLMapping = config.useXMLMapping();
141        GenericMultiThreadedImporter importer = new GenericMultiThreadedImporter(src, config.getTargetPath(),
142                !config.isCreateInitialFolder(), config.getBatchSize(), config.getNbThreads(), new BasicLogger(log));
143
144        ImporterDocumentModelFactory factory = initDocumentModelFactory(config);
145        importer.setEnablePerfLogging(Framework.getService(
146                DefaultImporterService.class).getEnablePerfLogging());
147        importer.setFactory(factory);
148        importer.setTransactionTimeout(config.getTransactionTimeout());
149        importer.run();
150
151        log.info("Fininish moving files");
152        doCleanUp();
153
154        log.info("Ending import process");
155    }
156
157    /**
158     * @since 5.7.3
159     */
160    private ImporterDocumentModelFactory initDocumentModelFactory(ImporterConfig config) {
161        Class<? extends ImporterDocumentModelFactory> factoryClass = Framework.getService(
162                DefaultImporterService.class).getDocModelFactoryClass();
163        // Class<? extends DefaultDocumentModelFactory> factoryClass = ScanedFileFactory.class;
164        Constructor<? extends ImporterDocumentModelFactory> cst = null;
165
166        try {
167            try {
168                cst = factoryClass.getConstructor(ImporterConfig.class);
169                return cst.newInstance(config);
170            } catch (NoSuchMethodException e) {
171                return factoryClass.newInstance();
172            }
173        } catch (ReflectiveOperationException e) {
174            throw new NuxeoException(e);
175        }
176    }
177
178    /**
179     * @throws Exception
180     * @since 5.7.3
181     */
182    private SourceNode initSourceNode(File file) {
183        Class<? extends SourceNode> srcClass = Framework.getService(DefaultImporterService.class).getSourceNodeClass();
184        // Class<? extends SourceNode> srcClass = ScanedFileSourceNode.class;
185        if (!FileSourceNode.class.isAssignableFrom(srcClass)) {
186            throw new NuxeoException("Waiting source node extending FileSourceNode for Scan Importer");
187        }
188        try {
189            return srcClass.getConstructor(File.class).newInstance(file);
190        } catch (ReflectiveOperationException e) {
191            throw new NuxeoException(e);
192        }
193    }
194
195}