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