/**
   * Constructs a new {@code DirectoryScanner}.
   *
   * <p>This constructor is package protected, and this MBean cannot be created by a remote client,
   * because it needs a reference to the {@link ResultLogManager}, which cannot be provided from
   * remote.
   *
   * <p>This is a conscious design choice: {@code DirectoryScanner} MBeans are expected to be
   * completely managed (created, registered, unregistered) by the {@link ScanManager} which does
   * provide this reference.
   *
   * @param config This {@code DirectoryScanner} configuration.
   * @param logManager The info log manager with which to log the info records.
   * @throws IllegalArgumentException if one of the parameter is null, or if the provided {@code
   *     config} doesn't have its {@code name} set, or if the {@link
   *     DirectoryScannerConfig#getRootDirectory root directory} provided in the {@code config} is
   *     not acceptable (not provided or not found or not readable, etc...).
   */
  public DirectoryScanner(DirectoryScannerConfig config, ResultLogManager logManager)
      throws IllegalArgumentException {
    if (logManager == null) throw new IllegalArgumentException("log=null");
    if (config == null) throw new IllegalArgumentException("config=null");
    if (config.getName() == null) throw new IllegalArgumentException("config.name=null");

    broadcaster = new NotificationBroadcasterSupport();

    // Clone the config: ensure data encapsulation.
    //
    this.config = XmlConfigUtils.xmlClone(config);

    // Checks that the provided root directory is valid.
    // Throws IllegalArgumentException if it isn't.
    //
    rootFile = validateRoot(config.getRootDirectory());

    // Initialize the Set<Action> for which this DirectoryScanner
    // is configured.
    //
    if (config.getActions() == null) actions = Collections.emptySet();
    else actions = EnumSet.copyOf(Arrays.asList(config.getActions()));
    this.logManager = logManager;
  }