Ejemplo n.º 1
0
  @Override
  public void setEmbargo(Context context, Item item) throws SQLException, AuthorizeException {
    // if lift is null, we might be restoring an item from an AIP
    DCDate myLift = getEmbargoTermsAsDate(context, item);
    if (myLift == null) {
      if ((myLift = recoverEmbargoDate(item)) == null) {
        return;
      }
    }
    String slift = myLift.toString();
    boolean ignoreAuth = context.ignoreAuthorization();
    try {
      context.setIgnoreAuthorization(true);
      itemService.clearMetadata(context, item, lift_schema, lift_element, lift_qualifier, Item.ANY);
      itemService.addMetadata(
          context, item, lift_schema, lift_element, lift_qualifier, null, slift);
      log.info("Set embargo on Item " + item.getHandle() + ", expires on: " + slift);

      setter.setEmbargo(context, item);

      itemService.update(context, item);
    } finally {
      context.setIgnoreAuthorization(ignoreAuth);
    }
  }
Ejemplo n.º 2
0
  /**
   * Save a registry to a filepath
   *
   * @param file filepath
   * @param schema schema definition to save
   * @throws SQLException if database error
   * @throws IOException if IO error
   * @throws SAXException if XML error
   * @throws RegistryExportException if export error
   */
  public static void saveRegistry(String file, String schema)
      throws SQLException, IOException, SAXException, RegistryExportException {
    // create a context
    Context context = new Context();
    context.setIgnoreAuthorization(true);

    OutputFormat xmlFormat = new OutputFormat(Method.XML, "UTF-8", true);
    xmlFormat.setLineWidth(120);
    xmlFormat.setIndent(4);

    XMLSerializer xmlSerializer =
        new XMLSerializer(new BufferedWriter(new FileWriter(file)), xmlFormat);
    //        XMLSerializer xmlSerializer = new XMLSerializer(System.out, xmlFormat);
    xmlSerializer.startDocument();
    xmlSerializer.startElement("dspace-dc-types", null);

    // Save the schema definition(s)
    saveSchema(context, xmlSerializer, schema);

    List<MetadataField> mdFields = null;

    // If a single schema has been specified
    if (schema != null && !"".equals(schema)) {
      // Get the id of that schema
      MetadataSchema mdSchema = metadataSchemaService.find(context, schema);
      if (mdSchema == null) {
        throw new RegistryExportException("no schema to export");
      }

      // Get the metadata fields only for the specified schema
      mdFields = metadataFieldService.findAllInSchema(context, mdSchema);
    } else {
      // Get the metadata fields for all the schemas
      mdFields = metadataFieldService.findAll(context);
    }

    // Output the metadata fields
    for (MetadataField mdField : mdFields) {
      saveType(context, xmlSerializer, mdField);
    }

    xmlSerializer.endElement("dspace-dc-types");
    xmlSerializer.endDocument();

    // abort the context, as we shouldn't have changed it!!
    context.abort();
  }
  /**
   * @param args
   * @throws SQLException
   * @throws IOException
   * @throws AuthorizeException
   */
  public static void main(String[] args) throws SQLException, AuthorizeException, IOException {

    Context ctx = new Context();
    ctx.setIgnoreAuthorization(true);
    ItemIterator iter = Item.findAll(ctx);

    Properties props = new Properties();

    File processed = new File("license.processed");

    if (processed.exists()) props.load(new FileInputStream(processed));

    int i = 0;

    try {
      while (iter.hasNext()) {
        if (i == 100) {
          props.store(
              new FileOutputStream(processed),
              "processed license files, remove to restart processing from scratch");
          i = 0;
        }

        Item item = (Item) iter.next();
        log.info("checking: " + item.getID());
        if (!props.containsKey("I" + item.getID())) {
          handleItem(item);
          log.info("processed: " + item.getID());
        }

        item.decache();
        props.put("I" + item.getID(), "done");
        i++;
      }

    } finally {
      props.store(
          new FileOutputStream(processed),
          "processed license files, remove to restart processing from scratch");
    }
  }
Ejemplo n.º 4
0
  /**
   * Perform a deposit, using the supplied SWORD Deposit object.
   *
   * @param deposit
   * @throws SWORDErrorException
   * @throws DSpaceSWORDException
   */
  public DepositResult doDeposit(Deposit deposit) throws SWORDErrorException, DSpaceSWORDException {
    // get the things out of the service that we need
    Context context = swordService.getContext();
    SWORDConfiguration swordConfig = swordService.getSwordConfig();
    SWORDUrlManager urlManager = swordService.getUrlManager();

    // FIXME: the spec is unclear what to do in this situation.  I'm going
    // the throw a 415 (ERROR_CONTENT) until further notice
    //
    // determine if this is an acceptable file format
    if (!swordConfig.isAcceptableContentType(context, deposit.getContentType(), collection)) {
      log.error(
          "Unacceptable content type detected: "
              + deposit.getContentType()
              + " for collection "
              + collection.getID());
      throw new SWORDErrorException(
          ErrorCodes.ERROR_CONTENT,
          "Unacceptable content type in deposit request: " + deposit.getContentType());
    }

    // determine if this is an acceptable packaging type for the deposit
    // if not, we throw a 415 HTTP error (Unsupported Media Type, ERROR_CONTENT)
    if (!swordConfig.isSupportedMediaType(deposit.getPackaging(), this.collection)) {
      log.error(
          "Unacceptable packaging type detected: "
              + deposit.getPackaging()
              + "for collection"
              + collection.getID());
      throw new SWORDErrorException(
          ErrorCodes.ERROR_CONTENT,
          "Unacceptable packaging type in deposit request: " + deposit.getPackaging());
    }

    // Obtain the relevant ingester from the factory
    SWORDIngester si = SWORDIngesterFactory.getInstance(context, deposit, collection);
    swordService.message("Loaded ingester: " + si.getClass().getName());

    // do the deposit
    DepositResult result = si.ingest(swordService, deposit, collection);
    swordService.message("Archive ingest completed successfully");

    // if there's an item availalble, and we want to keep the original
    // then do that
    try {
      if (swordConfig.isKeepOriginal()) {
        swordService.message(
            "DSpace will store an original copy of the deposit, "
                + "as well as ingesting the item into the archive");

        // in order to be allowed to add the file back to the item, we need to ignore authorisations
        // for a moment
        boolean ignoreAuth = context.ignoreAuthorization();
        context.setIgnoreAuthorization(true);

        String bundleName = ConfigurationManager.getProperty("sword-server", "bundle.name");
        if (bundleName == null || "".equals(bundleName)) {
          bundleName = "SWORD";
        }
        Item item = result.getItem();
        Bundle[] bundles = item.getBundles(bundleName);
        Bundle swordBundle = null;
        if (bundles.length > 0) {
          swordBundle = bundles[0];
        }
        if (swordBundle == null) {
          swordBundle = item.createBundle(bundleName);
        }

        String fn = swordService.getFilename(context, deposit, true);

        Bitstream bitstream;
        FileInputStream fis = null;
        try {
          fis = new FileInputStream(deposit.getFile());
          bitstream = swordBundle.createBitstream(fis);
        } finally {
          if (fis != null) {
            fis.close();
          }
        }

        bitstream.setName(fn);
        bitstream.setDescription("SWORD deposit package");

        BitstreamFormat bf = BitstreamFormat.findByMIMEType(context, deposit.getContentType());
        if (bf != null) {
          bitstream.setFormat(bf);
        }

        bitstream.update();

        swordBundle.update();
        item.update();

        swordService.message(
            "Original package stored as " + fn + ", in item bundle " + swordBundle);

        // now reset the context ignore authorisation
        context.setIgnoreAuthorization(ignoreAuth);

        // set the media link for the created item
        result.setMediaLink(urlManager.getMediaLink(bitstream));
      } else {
        // set the vanilla media link, which doesn't resolve to anything
        result.setMediaLink(urlManager.getBaseMediaLinkUrl());
      }
    } catch (SQLException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSWORDException(e);
    } catch (AuthorizeException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSWORDException(e);
    } catch (FileNotFoundException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSWORDException(e);
    } catch (IOException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSWORDException(e);
    }

    return result;
  }
  public static void main(String[] argv) throws Exception {
    // set headless for non-gui workstations
    System.setProperty("java.awt.headless", "true");

    // create an options object and populate it
    CommandLineParser parser = new PosixParser();

    Options options = new Options();

    options.addOption(
        "v", "verbose", false, "print all extracted text and other details to STDOUT");
    options.addOption("f", "force", false, "force all bitstreams to be processed");
    options.addOption(
        "n", "noindex", false, "do NOT update the search index after filtering bitstreams");
    options.addOption("i", "identifier", true, "ONLY process bitstreams belonging to identifier");
    options.addOption("m", "maximum", true, "process no more than maximum items");
    options.addOption("h", "help", false, "help");

    CommandLine line = parser.parse(options, argv);

    if (line.hasOption('h')) {
      HelpFormatter myhelp = new HelpFormatter();
      myhelp.printHelp("MediaFilter\n", options);

      System.exit(0);
    }

    if (line.hasOption('v')) {
      isVerbose = true;
    }

    if (line.hasOption('n')) {
      updateIndex = false;
    }

    if (line.hasOption('f')) {
      isForce = true;
    }

    if (line.hasOption('i')) {
      identifier = line.getOptionValue('i');
    }

    if (line.hasOption('m')) {
      max2Process = Integer.parseInt(line.getOptionValue('m'));
      if (max2Process <= 1) {
        System.out.println("Invalid maximum value '" + line.getOptionValue('m') + "' - ignoring");
        max2Process = Integer.MAX_VALUE;
      }
    }

    // set up filters
    filterClasses = (MediaFilter[]) PluginManager.getPluginSequence(MediaFilter.class);
    for (int i = 0; i < filterClasses.length; i++) {
      String filterName = filterClasses[i].getClass().getName();
      String formats = ConfigurationManager.getProperty("filter." + filterName + ".inputFormats");
      if (formats != null) {
        filterFormats.put(filterName, Arrays.asList(formats.split(",[\\s]*")));
      }
    }

    Context c = null;

    try {
      c = new Context();

      // have to be super-user to do the filtering
      c.setIgnoreAuthorization(true);

      // now apply the filters
      if (identifier == null) {
        applyFiltersAllItems(c);
      } else // restrict application scope to identifier
      {
        DSpaceObject dso = HandleManager.resolveToObject(c, identifier);
        if (dso == null) {
          throw new IllegalArgumentException(
              "Cannot resolve " + identifier + " to a DSpace object");
        }

        switch (dso.getType()) {
          case Constants.COMMUNITY:
            applyFiltersCommunity(c, (Community) dso);
            break;
          case Constants.COLLECTION:
            applyFiltersCollection(c, (Collection) dso);
            break;
          case Constants.ITEM:
            applyFiltersItem(c, (Item) dso);
            break;
        }
      }

      // update search index?
      if (updateIndex) {
        System.out.println("Updating search index:");
        DSIndexer.updateIndex(c);
      }

      c.complete();
      c = null;
    } finally {
      if (c != null) {
        c.abort();
      }
    }
  }
Ejemplo n.º 6
0
  /**
   * perform the ingest using the given deposit object onto the specified target dspace object,
   * using the sword service implementation
   *
   * @param service
   * @param deposit
   * @param target
   * @return
   * @throws DSpaceSWORDException
   * @throws SWORDErrorException
   */
  public DepositResult ingest(SWORDService service, Deposit deposit, DSpaceObject target)
      throws DSpaceSWORDException, SWORDErrorException {
    try {
      if (!(target instanceof Item)) {
        throw new DSpaceSWORDException(
            "SimpleFileIngester can only be loaded for deposit onto DSpace Items");
      }
      Item item = (Item) target;

      // now set the sword service
      SWORDService swordService = service;

      // get the things out of the service that we need
      Context context = swordService.getContext();
      SWORDUrlManager urlManager = swordService.getUrlManager();

      Bundle[] bundles = item.getBundles("ORIGINAL");
      Bundle original;
      if (bundles.length > 0) {
        original = bundles[0];
      } else {
        original = item.createBundle("ORIGINAL");
      }

      Bitstream bs;
      FileInputStream fis = null;

      try {
        fis = new FileInputStream(deposit.getFile());
        bs = original.createBitstream(fis);
      } finally {
        if (fis != null) {
          fis.close();
        }
      }

      String fn = swordService.getFilename(context, deposit, false);
      bs.setName(fn);

      swordService.message("File created in item with filename " + fn);

      BitstreamFormat bf = BitstreamFormat.findByMIMEType(context, deposit.getContentType());
      if (bf != null) {
        bs.setFormat(bf);
      }

      // to do the updates, we need to ignore authorisation in the context
      boolean ignoreAuth = context.ignoreAuthorization();
      context.setIgnoreAuthorization(true);

      bs.update();
      original.update();
      item.update();

      // reset the ignore authorisation
      context.setIgnoreAuthorization(ignoreAuth);

      DepositResult result = new DepositResult();
      result.setHandle(urlManager.getBitstreamUrl(bs));
      result.setTreatment(this.getTreatment());
      result.setBitstream(bs);

      return result;
    } catch (SQLException e) {
      throw new DSpaceSWORDException(e);
    } catch (AuthorizeException e) {
      throw new DSpaceSWORDException(e);
    } catch (IOException e) {
      throw new DSpaceSWORDException(e);
    }
  }
Ejemplo n.º 7
0
  /** @param argv */
  public static void main(String[] argv) {
    // create an options object and populate it
    CommandLineParser parser = new PosixParser();

    Options options = new Options();

    // processing basis for determining items
    // item-specific changes with metadata in source directory with dublin_core.xml files
    options.addOption("s", "source", true, "root directory of source dspace archive ");

    // actions  on items
    options.addOption(
        "a",
        "addmetadata",
        true,
        "add metadata specified for each item; multiples separated by semicolon ';'");
    options.addOption("d", "deletemetadata", true, "delete metadata specified for each item");

    options.addOption("A", "addbitstreams", false, "add bitstreams as specified for each item");

    // extra work to get optional argument
    Option delBitstreamOption =
        new Option("D", "deletebitstreams", true, "delete bitstreams as specified for each item");
    delBitstreamOption.setOptionalArg(true);
    delBitstreamOption.setArgName("BitstreamFilter");
    options.addOption(delBitstreamOption);

    // other params
    options.addOption("e", "eperson", true, "email of eperson doing the update");
    options.addOption(
        "i",
        "itemfield",
        true,
        "optional metadata field that containing item identifier; default is dc.identifier.uri");
    options.addOption(
        "F", "filter-properties", true, "filter class name; only for deleting bitstream");
    options.addOption("v", "verbose", false, "verbose logging");

    // special run states
    options.addOption("t", "test", false, "test run - do not actually import items");
    options.addOption(
        "P", "provenance", false, "suppress altering provenance field for bitstream changes");
    options.addOption("h", "help", false, "help");

    int status = 0;
    boolean isTest = false;
    boolean alterProvenance = true;
    String itemField = null;
    String metadataIndexName = null;

    Context context = null;
    ItemUpdate iu = new ItemUpdate();

    try {
      CommandLine line = parser.parse(options, argv);

      if (line.hasOption('h')) {
        HelpFormatter myhelp = new HelpFormatter();
        myhelp.printHelp("ItemUpdate", options);
        pr("");
        pr("Examples:");
        pr(
            "  adding metadata:     ItemUpdate -e [email protected] -s sourcedir -a dc.contributor -a dc.subject ");
        pr(
            "  deleting metadata:   ItemUpdate -e [email protected] -s sourcedir -d dc.description.other");
        pr("  adding bitstreams:   ItemUpdate -e [email protected] -s sourcedir -A -i dc.identifier");
        pr("  deleting bitstreams: ItemUpdate -e [email protected] -s sourcedir -D ORIGINAL ");
        pr("");

        System.exit(0);
      }

      if (line.hasOption('v')) {
        verbose = true;
      }

      if (line.hasOption('P')) {
        alterProvenance = false;
        pr("Suppressing changes to Provenance field option");
      }

      iu.eperson = line.getOptionValue('e'); // db ID or email

      if (!line.hasOption('s')) // item specific changes from archive dir
      {
        pr("Missing source archive option");
        System.exit(1);
      }
      String sourcedir = line.getOptionValue('s');

      if (line.hasOption('t')) // test
      {
        isTest = true;
        pr("**Test Run** - not actually updating items.");
      }

      if (line.hasOption('i')) {
        itemField = line.getOptionValue('i');
      }

      if (line.hasOption('d')) {
        String[] targetFields = line.getOptionValues('d');

        DeleteMetadataAction delMetadataAction =
            (DeleteMetadataAction) iu.actionMgr.getUpdateAction(DeleteMetadataAction.class);
        delMetadataAction.addTargetFields(targetFields);

        // undo is an add
        for (String field : targetFields) {
          iu.undoActionList.add(" -a " + field + " ");
        }

        pr("Delete metadata for fields: ");
        for (String s : targetFields) {
          pr("    " + s);
        }
      }

      if (line.hasOption('a')) {
        String[] targetFields = line.getOptionValues('a');

        AddMetadataAction addMetadataAction =
            (AddMetadataAction) iu.actionMgr.getUpdateAction(AddMetadataAction.class);
        addMetadataAction.addTargetFields(targetFields);

        // undo is a delete followed by an add of a replace record for target fields
        for (String field : targetFields) {
          iu.undoActionList.add(" -d " + field + " ");
        }

        for (String field : targetFields) {
          iu.undoActionList.add(" -a " + field + " ");
        }

        pr("Add metadata for fields: ");
        for (String s : targetFields) {
          pr("    " + s);
        }
      }

      if (line.hasOption('D')) // undo not supported
      {
        pr("Delete bitstreams ");

        String[] filterNames = line.getOptionValues('D');
        if ((filterNames != null) && (filterNames.length > 1)) {
          pr("Error: Only one filter can be a used at a time.");
          System.exit(1);
        }

        String filterName = line.getOptionValue('D');
        pr("Filter argument: " + filterName);

        if (filterName == null) // indicates using delete_contents files
        {
          DeleteBitstreamsAction delAction =
              (DeleteBitstreamsAction) iu.actionMgr.getUpdateAction(DeleteBitstreamsAction.class);
          delAction.setAlterProvenance(alterProvenance);
        } else {
          // check if param is on ALIAS list
          String filterClassname = filterAliases.get(filterName);

          if (filterClassname == null) {
            filterClassname = filterName;
          }

          BitstreamFilter filter = null;

          try {
            Class<?> cfilter = Class.forName(filterClassname);
            pr("BitstreamFilter class to instantiate: " + cfilter.toString());

            filter =
                (BitstreamFilter) cfilter.newInstance(); // unfortunate cast, an erasure consequence
          } catch (Exception e) {
            pr("Error:  Failure instantiating bitstream filter class: " + filterClassname);
            System.exit(1);
          }

          String filterPropertiesName = line.getOptionValue('F');
          if (filterPropertiesName != null) // not always required
          {
            try {
              // TODO try multiple relative locations, e.g. source dir
              if (!filterPropertiesName.startsWith("/")) {
                filterPropertiesName = sourcedir + File.separator + filterPropertiesName;
              }

              filter.initProperties(filterPropertiesName);
            } catch (Exception e) {
              pr(
                  "Error:  Failure finding properties file for bitstream filter class: "
                      + filterPropertiesName);
              System.exit(1);
            }
          }

          DeleteBitstreamsByFilterAction delAction =
              (DeleteBitstreamsByFilterAction)
                  iu.actionMgr.getUpdateAction(DeleteBitstreamsByFilterAction.class);
          delAction.setAlterProvenance(alterProvenance);
          delAction.setBitstreamFilter(filter);
          // undo not supported
        }
      }

      if (line.hasOption('A')) {
        pr("Add bitstreams ");
        AddBitstreamsAction addAction =
            (AddBitstreamsAction) iu.actionMgr.getUpdateAction(AddBitstreamsAction.class);
        addAction.setAlterProvenance(alterProvenance);

        iu.undoActionList.add(" -D "); // delete_contents file will be written, no arg required
      }

      if (!iu.actionMgr.hasActions()) {
        pr("Error - an action must be specified");
        System.exit(1);
      } else {
        pr("Actions to be performed: ");

        for (UpdateAction ua : iu.actionMgr) {
          pr("    " + ua.getClass().getName());
        }
      }

      pr("ItemUpdate - initializing run on " + (new Date()).toString());

      context = new Context();
      iu.setEPerson(context, iu.eperson);
      context.setIgnoreAuthorization(true);

      HANDLE_PREFIX = ConfigurationManager.getProperty("handle.canonical.prefix");
      if (HANDLE_PREFIX == null || HANDLE_PREFIX.length() == 0) {
        HANDLE_PREFIX = "http://hdl.handle.net/";
      }

      iu.processArchive(context, sourcedir, itemField, metadataIndexName, alterProvenance, isTest);

      context.complete(); // complete all transactions
      context.setIgnoreAuthorization(false);
    } catch (Exception e) {
      if (context != null && context.isValid()) {
        context.abort();
        context.setIgnoreAuthorization(false);
      }
      e.printStackTrace();
      pr(e.toString());
      status = 1;
    }

    if (isTest) {
      pr("***End of Test Run***");
    } else {
      pr("End.");
    }
    System.exit(status);
  }
Ejemplo n.º 8
0
  public static void main(String[] argv) throws Exception {
    // create an options object and populate it
    CommandLineParser parser = new PosixParser();

    Options options = new Options();

    options.addOption("s", "set", false, "set a parent/child relationship");
    options.addOption("r", "remove", false, "remove a parent/child relationship");
    options.addOption("p", "parent", true, "parent community (handle or database ID)");
    options.addOption("c", "child", true, "child community (handle or databaseID)");
    options.addOption("h", "help", false, "help");

    CommandLine line = parser.parse(options, argv);

    String command = null; // set or remove
    String parentID = null;
    String childID = null;

    if (line.hasOption('h')) {
      HelpFormatter myhelp = new HelpFormatter();
      myhelp.printHelp("CommunityFiliator\n", options);
      System.out.println("\nestablish a relationship: CommunityFiliator -s -p parentID -c childID");
      System.out.println("remove a relationship: CommunityFiliator -r -p parentID -c childID");

      System.exit(0);
    }

    if (line.hasOption('s')) {
      command = "set";
    }

    if (line.hasOption('r')) {
      command = "remove";
    }

    if (line.hasOption('p')) // parent
    {
      parentID = line.getOptionValue('p');
    }

    if (line.hasOption('c')) // child
    {
      childID = line.getOptionValue('c');
    }

    // now validate
    // must have a command set
    if (command == null) {
      System.out.println(
          "Error - must run with either set or remove (run with -h flag for details)");
      System.exit(1);
    }

    if (command.equals("set") || command.equals("remove")) {
      if (parentID == null) {
        System.out.println("Error - a parentID must be specified (run with -h flag for details)");
        System.exit(1);
      }

      if (childID == null) {
        System.out.println("Error - a childID must be specified (run with -h flag for details)");
        System.exit(1);
      }
    }

    CommunityFiliator filiator = new CommunityFiliator();
    Context c = new Context();

    // ve are superuser!
    c.setIgnoreAuthorization(true);

    try {
      // validate and resolve the parent and child IDs into commmunities
      Community parent = filiator.resolveCommunity(c, parentID);
      Community child = filiator.resolveCommunity(c, childID);

      if (parent == null) {
        System.out.println("Error, parent community cannot be found: " + parentID);
        System.exit(1);
      }

      if (child == null) {
        System.out.println("Error, child community cannot be found: " + childID);
        System.exit(1);
      }

      if (command.equals("set")) {
        filiator.filiate(c, parent, child);
      } else {
        filiator.defiliate(c, parent, child);
      }
    } catch (SQLException sqlE) {
      System.out.println("Error - SQL exception: " + sqlE.toString());
    } catch (AuthorizeException authE) {
      System.out.println("Error - Authorize exception: " + authE.toString());
    } catch (IOException ioE) {
      System.out.println("Error - IO exception: " + ioE.toString());
    }
  }
  /*
   * Authenticate the given credentials.
   * This is the heart of the authentication method: test the
   * credentials for authenticity, and if accepted, attempt to match
   * (or optionally, create) an <code>EPerson</code>.  If an <code>EPerson</code> is found it is
   * set in the <code>Context</code> that was passed.
   *
   * @param context
   *  DSpace context, will be modified (ePerson set) upon success.
   *
   * @param username
   *  Username (or email address) when method is explicit. Use null for
   *  implicit method.
   *
   * @param password
   *  Password for explicit auth, or null for implicit method.
   *
   * @param realm
   *  Realm is an extra parameter used by some authentication methods, leave null if
   *  not applicable.
   *
   * @param request
   *  The HTTP request that started this operation, or null if not applicable.
   *
   * @return One of:
   *   SUCCESS, BAD_CREDENTIALS, CERT_REQUIRED, NO_SUCH_USER, BAD_ARGS
   * <p>Meaning:
   * <br>SUCCESS         - authenticated OK.
   * <br>BAD_CREDENTIALS - user exists, but credentials (e.g. passwd) don't match
   * <br>CERT_REQUIRED   - not allowed to login this way without X.509 cert.
   * <br>NO_SUCH_USER    - user not found using this method.
   * <br>BAD_ARGS        - user/pw not appropriate for this method
   */
  @Override
  public int authenticate(
      Context context, String netid, String password, String realm, HttpServletRequest request)
      throws SQLException {
    log.info(LogManager.getHeader(context, "auth", "attempting trivial auth of user="******"authentication-ldap", "search.anonymous");
    String adminUser = ConfigurationManager.getProperty("authentication-ldap", "search.user");
    String adminPassword =
        ConfigurationManager.getProperty("authentication-ldap", "search.password");
    String objectContext =
        ConfigurationManager.getProperty("authentication-ldap", "object_context");
    String idField = ConfigurationManager.getProperty("authentication-ldap", "id_field");
    String dn = "";

    // If adminUser is blank and anonymous search is not allowed, then we can't search so construct
    // the DN instead of searching it
    if ((StringUtils.isBlank(adminUser) || StringUtils.isBlank(adminPassword))
        && !anonymousSearch) {
      dn = idField + "=" + netid + "," + objectContext;
    } else {
      dn = ldap.getDNOfUser(adminUser, adminPassword, context, netid);
    }

    // Check a DN was found
    if ((dn == null) || (dn.trim().equals(""))) {
      log.info(LogManager.getHeader(context, "failed_login", "no DN found for user " + netid));
      return BAD_CREDENTIALS;
    }

    // if they entered a netid that matches an eperson
    if (eperson != null) {
      // e-mail address corresponds to active account
      if (eperson.getRequireCertificate()) {
        return CERT_REQUIRED;
      } else if (!eperson.canLogIn()) {
        return BAD_ARGS;
      }

      if (ldap.ldapAuthenticate(dn, password, context)) {
        context.setCurrentUser(eperson);

        // assign user to groups based on ldap dn
        assignGroups(dn, ldap.ldapGroup, context);

        log.info(LogManager.getHeader(context, "authenticate", "type=ldap"));
        return SUCCESS;
      } else {
        return BAD_CREDENTIALS;
      }
    } else {
      // the user does not already exist so try and authenticate them
      // with ldap and create an eperson for them

      if (ldap.ldapAuthenticate(dn, password, context)) {
        // Register the new user automatically
        log.info(LogManager.getHeader(context, "autoregister", "netid=" + netid));

        String email = ldap.ldapEmail;

        // Check if we were able to determine an email address from LDAP
        if (StringUtils.isEmpty(email)) {
          // If no email, check if we have a "netid_email_domain". If so, append it to the netid to
          // create email
          if (StringUtils.isNotEmpty(
              ConfigurationManager.getProperty("authentication-ldap", "netid_email_domain"))) {
            email =
                netid
                    + ConfigurationManager.getProperty("authentication-ldap", "netid_email_domain");
          } else {
            // We don't have a valid email address. We'll default it to 'netid' but log a warning
            log.warn(
                LogManager.getHeader(
                    context,
                    "autoregister",
                    "Unable to locate email address for account '"
                        + netid
                        + "', so it has been set to '"
                        + netid
                        + "'. "
                        + "Please check the LDAP 'email_field' OR consider configuring 'netid_email_domain'."));
            email = netid;
          }
        }

        if (StringUtils.isNotEmpty(email)) {
          try {
            eperson = ePersonService.findByEmail(context, email);
            if (eperson != null) {
              log.info(
                  LogManager.getHeader(context, "type=ldap-login", "type=ldap_but_already_email"));
              context.setIgnoreAuthorization(true);
              eperson.setNetid(netid.toLowerCase());
              ePersonService.update(context, eperson);
              context.dispatchEvents();
              context.setIgnoreAuthorization(false);
              context.setCurrentUser(eperson);

              // assign user to groups based on ldap dn
              assignGroups(dn, ldap.ldapGroup, context);

              return SUCCESS;
            } else {
              if (canSelfRegister(context, request, netid)) {
                // TEMPORARILY turn off authorisation
                try {
                  context.setIgnoreAuthorization(true);
                  eperson = ePersonService.create(context);
                  if (StringUtils.isNotEmpty(email)) {
                    eperson.setEmail(email);
                  }
                  if (StringUtils.isNotEmpty(ldap.ldapGivenName)) {
                    eperson.setFirstName(context, ldap.ldapGivenName);
                  }
                  if (StringUtils.isNotEmpty(ldap.ldapSurname)) {
                    eperson.setLastName(context, ldap.ldapSurname);
                  }
                  if (StringUtils.isNotEmpty(ldap.ldapPhone)) {
                    ePersonService.setMetadata(context, eperson, "phone", ldap.ldapPhone);
                  }
                  eperson.setNetid(netid.toLowerCase());
                  eperson.setCanLogIn(true);
                  authenticationService.initEPerson(context, request, eperson);
                  ePersonService.update(context, eperson);
                  context.dispatchEvents();
                  context.setCurrentUser(eperson);

                  // assign user to groups based on ldap dn
                  assignGroups(dn, ldap.ldapGroup, context);
                } catch (AuthorizeException e) {
                  return NO_SUCH_USER;
                } finally {
                  context.setIgnoreAuthorization(false);
                }

                log.info(
                    LogManager.getHeader(
                        context, "authenticate", "type=ldap-login, created ePerson"));
                return SUCCESS;
              } else {
                // No auto-registration for valid certs
                log.info(LogManager.getHeader(context, "failed_login", "type=ldap_but_no_record"));
                return NO_SUCH_USER;
              }
            }
          } catch (AuthorizeException e) {
            eperson = null;
          } finally {
            context.setIgnoreAuthorization(false);
          }
        }
      }
    }
    return BAD_ARGS;
  }