// Path: api/src/main/java/org/alfresco/extension/bulkimport/source/BulkImportSource.java
// public interface BulkImportSource
// {
//     /**
//      * @return The human readable name of this bulk import source <i>(must not be null, empty or blank)</i>.
//      */
//     String getName();
//     
//     
//     /**
//      * @return A description of this bulk import source - may contain HTML tags <i>(may be null, empty or blank)</i>.
//      */
//     String getDescription();
//     
//     
//     /**
//      * @return The parameters used to initialise this import source, as human-readable text <i>(may be null or empty)</i>.
//      */
//     Map<String, String> getParameters();
// 
//     
//     /**
//      * @return The URI of the Web Script to display in the initiation form, when this source is selected <i>(may be null)</i>.
//      */
//     String getConfigWebScriptURI();
//     
//     
//     /**
//      * Called before anything else, so that the source can validate and parse its parameters.  If the parameters are invalid,
//      * sources should throw an <code>IllegalArgumentException</code> with details on which parameters were missing / invalid.
//      * 
//      * @param status     The status object to use to pre-register any source-side statistics <i>(will not be null)</li>.
//      * @param parameters The parameters (if any) provided by the initiator of the import <i>(will not be null, but may be empty)</i>.
//      */
//     void init(BulkImportSourceStatus status, Map<String, List<String>> parameters);
//     
//     
//     /**
//      * Query to determine whether an "in-place" import is possible, given the provided parameters.  Note that this doesn't imply
//      * that all content in the source must be imported in-place - that can be decided by a source implementation on a file-by-file
//      * basis.  Instead this is indicative of whether any amount of in-place import is possible or not.
//      * 
//      * @return True if an in-place import is possible with the given parameters, or false otherwise.
//      */
//     boolean inPlaceImportPossible();
//     
//     
//     /**
//      * Called when the folder scanning phase of a bulk import is commenced.  Importable items should be submitted via the callback,
//      * and status may (optionally) be provided via the status object.
//      * 
//      * Notes:
//      * <ol>
//      * <li>Items must be submitted in dependency order i.e. parents before children.
//      * Failure to do so will have a <b>severe</b> impact on performance (due to
//      * transactional rollbacks, followed by retries).</li>
//      * <li>This code <u>must not</u> use any Alfresco repository services whatsoever,
//      * as this method is executed on a background thread that runs outside of both
//      * an Alfresco authentication context and an Alfresco transaction.</li>
//      * </ol>
//      * 
//      * @param status     The status object to use to report source-side statistics <i>(will not be null)</li>.
//      * @param callback   The callback into the bulk import engine with which to enqueue items discovered <i>(will not be null)</li>.
//      * @throws InterruptedException Should be thrown if the thread running the scan is interrupted.
//      */
//     void scanFolders(BulkImportSourceStatus status, BulkImportCallback callback)
//         throws InterruptedException;
// 
//     
//     /**
//      * Called when the file scanning phase of a bulk import is commenced.  Importable items should be submitted via the callback,
//      * and status may (optionally) be provided via the status object.
//      * 
//      * Notes:
//      * <ol>
//      * <li>This code must <u>not</u> use any Alfresco repository services whatsoever,
//      * as this method is executed on a background thread that runs outside of both
//      * an Alfresco authentication context and an Alfresco transaction.</li>
//      * </ol>
//      * 
//      * @param status     The status object to use to report source-side statistics <i>(will not be null)</li>.
//      * @param callback   The callback into the bulk import engine with which to enqueue items discovered <i>(will not be null)</li>.
//      * @throws InterruptedException Should be thrown if the thread running the scan is interrupted.
//      */
//     void scanFiles(BulkImportSourceStatus status, BulkImportCallback callback)
//         throws InterruptedException;
//     
// }


import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.alfresco.extension.bulkimport.util.ThreadPauser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.extension.bulkimport.BulkImportCompletionHandler;
import org.alfresco.extension.bulkimport.BulkImportStatus;
import org.alfresco.extension.bulkimport.BulkImporter;
import org.alfresco.extension.bulkimport.source.BulkImportSource;
import static org.alfresco.extension.bulkimport.util.LogUtils.*;
        this.authenticationService = serviceRegistry.getAuthenticationService();
        
        this.importStatus  = importStatus;
        this.pauser        = pauser;
        this.batchImporter = batchImporter;
        this.batchWeight   = batchWeight <= 0 ? DEFAULT_BATCH_WEIGHT : batchWeight;
        
        this.completionHandlers = completionHandlers;
    }
    
    
    /**
     * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
     */
    @Override
    public void setApplicationContext(final ApplicationContext appContext)
        throws BeansException
    {
        // PRECONDITIONS
        assert appContext != null : "appContext must not be null.";
        
        // Body
        this.appContext = appContext;
    }
    
    
    /**
     * @see org.alfresco.extension.bulkimport.BulkImporter#getBulkImportSources()
     */
    @Override
// Path: api/src/main/java/org/alfresco/extension/bulkimport/source/BulkImportSource.java
// public interface BulkImportSource
// {
//     /**
//      * @return The human readable name of this bulk import source <i>(must not be null, empty or blank)</i>.
//      */
//     String getName();
//     
//     
//     /**
//      * @return A description of this bulk import source - may contain HTML tags <i>(may be null, empty or blank)</i>.
//      */
//     String getDescription();
//     
//     
//     /**
//      * @return The parameters used to initialise this import source, as human-readable text <i>(may be null or empty)</i>.
//      */
//     Map<String, String> getParameters();
// 
//     
//     /**
//      * @return The URI of the Web Script to display in the initiation form, when this source is selected <i>(may be null)</i>.
//      */
//     String getConfigWebScriptURI();
//     
//     
//     /**
//      * Called before anything else, so that the source can validate and parse its parameters.  If the parameters are invalid,
//      * sources should throw an <code>IllegalArgumentException</code> with details on which parameters were missing / invalid.
//      * 
//      * @param status     The status object to use to pre-register any source-side statistics <i>(will not be null)</li>.
//      * @param parameters The parameters (if any) provided by the initiator of the import <i>(will not be null, but may be empty)</i>.
//      */
//     void init(BulkImportSourceStatus status, Map<String, List<String>> parameters);
//     
//     
//     /**
//      * Query to determine whether an "in-place" import is possible, given the provided parameters.  Note that this doesn't imply
//      * that all content in the source must be imported in-place - that can be decided by a source implementation on a file-by-file
//      * basis.  Instead this is indicative of whether any amount of in-place import is possible or not.
//      * 
//      * @return True if an in-place import is possible with the given parameters, or false otherwise.
//      */
//     boolean inPlaceImportPossible();
//     
//     
//     /**
//      * Called when the folder scanning phase of a bulk import is commenced.  Importable items should be submitted via the callback,
//      * and status may (optionally) be provided via the status object.
//      * 
//      * Notes:
//      * <ol>
//      * <li>Items must be submitted in dependency order i.e. parents before children.
//      * Failure to do so will have a <b>severe</b> impact on performance (due to
//      * transactional rollbacks, followed by retries).</li>
//      * <li>This code <u>must not</u> use any Alfresco repository services whatsoever,
//      * as this method is executed on a background thread that runs outside of both
//      * an Alfresco authentication context and an Alfresco transaction.</li>
//      * </ol>
//      * 
//      * @param status     The status object to use to report source-side statistics <i>(will not be null)</li>.
//      * @param callback   The callback into the bulk import engine with which to enqueue items discovered <i>(will not be null)</li>.
//      * @throws InterruptedException Should be thrown if the thread running the scan is interrupted.
//      */
//     void scanFolders(BulkImportSourceStatus status, BulkImportCallback callback)
//         throws InterruptedException;
// 
//     
//     /**
//      * Called when the file scanning phase of a bulk import is commenced.  Importable items should be submitted via the callback,
//      * and status may (optionally) be provided via the status object.
//      * 
//      * Notes:
//      * <ol>
//      * <li>This code must <u>not</u> use any Alfresco repository services whatsoever,
//      * as this method is executed on a background thread that runs outside of both
//      * an Alfresco authentication context and an Alfresco transaction.</li>
//      * </ol>
//      * 
//      * @param status     The status object to use to report source-side statistics <i>(will not be null)</li>.
//      * @param callback   The callback into the bulk import engine with which to enqueue items discovered <i>(will not be null)</li>.
//      * @throws InterruptedException Should be thrown if the thread running the scan is interrupted.
//      */
//     void scanFiles(BulkImportSourceStatus status, BulkImportCallback callback)
//         throws InterruptedException;
//     
// }


// Path: amp/src/main/java/org/alfresco/extension/bulkimport/impl/BulkImporterImpl.java
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.alfresco.extension.bulkimport.util.ThreadPauser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.extension.bulkimport.BulkImportCompletionHandler;
import org.alfresco.extension.bulkimport.BulkImportStatus;
import org.alfresco.extension.bulkimport.BulkImporter;
import org.alfresco.extension.bulkimport.source.BulkImportSource;
import static org.alfresco.extension.bulkimport.util.LogUtils.*;

        this.authenticationService = serviceRegistry.getAuthenticationService();
        
        this.importStatus  = importStatus;
        this.pauser        = pauser;
        this.batchImporter = batchImporter;
        this.batchWeight   = batchWeight <= 0 ? DEFAULT_BATCH_WEIGHT : batchWeight;
        
        this.completionHandlers = completionHandlers;
    }
    
    
    /**
     * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
     */
    @Override
    public void setApplicationContext(final ApplicationContext appContext)
        throws BeansException
    {
        // PRECONDITIONS
        assert appContext != null : "appContext must not be null.";
        
        // Body
        this.appContext = appContext;
    }
    
    
    /**
     * @see org.alfresco.extension.bulkimport.BulkImporter#getBulkImportSources()
     */
    @Override
    public Map<String, BulkImportSource> getBulkImportSources()