Java tutorial
// Copyright 2007 Hitachi Data Systems // All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. package com.archivas.clienttools.arcmover.cli; import com.archivas.clienttools.arcutils.api.JobException; import com.archivas.clienttools.arcutils.api.JobId; import com.archivas.clienttools.arcutils.api.ManagedJobStats; import com.archivas.clienttools.arcutils.api.jobs.ManagedJob; import com.archivas.clienttools.arcutils.api.jobs.SetMetadataJob; import com.archivas.clienttools.arcutils.config.HCPMoverProperties; import com.archivas.clienttools.arcutils.model.ACLMetadata; import com.archivas.clienttools.arcutils.model.CustomMetadata; import com.archivas.clienttools.arcutils.model.FileMetadata; import com.archivas.clienttools.arcutils.model.LoadSchedule; import com.archivas.clienttools.arcutils.model.Owner; import com.archivas.clienttools.arcutils.model.Retention; import com.archivas.clienttools.arcutils.profile.AbstractProfileBase; import com.archivas.clienttools.arcutils.profile.ProfileManager; import com.archivas.clienttools.arcutils.utils.FileListParser; import com.archivas.clienttools.arcutils.utils.FileListParserException; import com.archivas.clienttools.arcutils.utils.database.DatabaseException; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; public class ArcMetadata extends ManagedCLIJob { private static String PROFILE_OPTION = "profile"; private static String PATH_OPTION = "path"; private static String HOLD_OPTION = "hold"; private static String INDEX_OPTION = "index"; private static String SHRED_OPTION = "shred"; private static String RETENTION_OPTION = "retention"; private static String CUSTOM_METADATA_OPTION = "custom-metadata"; private static String ACL_OPTION = "acl"; private static String OWNER_OPTION = "owner"; private static String DOMAIN_OPTION = "domain"; /** * Command Line Options * */ private static Options cliOptions; private static int cliOptionsCount = 0; static { addNextCLIOption(HELP_OPTION); addNextCLIOption(PROFILE_OPTION); addNextCLIOption(PATH_OPTION); addNextCLIOption(JOB_NAME); addNextCLIOption(HOLD_OPTION); addNextCLIOption(INDEX_OPTION); addNextCLIOption(SHRED_OPTION); addNextCLIOption(RETENTION_OPTION); addNextCLIOption(CUSTOM_METADATA_OPTION); addNextCLIOption(ACL_OPTION); addNextCLIOption(OWNER_OPTION); addNextCLIOption(DOMAIN_OPTION); addNextCLIOption(MAX_CONNECTIONS); addNextCLIOption(MAX_NODE_CONNECTIONS); addNextCLIOption(REDUCED_MAX_CONNECTIONS); addNextCLIOption(REDUCED_MAX_NODE_CONNECTIONS); addNextCLIOption(REDUCED_START); addNextCLIOption(REDUCED_END); addNextCLIOption(IGNORE_CONFLICTS); addNextCLIOption(EXPORT_RESULTS_TYPE); addNextCLIOption(EXPORT_RESULTS_PATH); addNextCLIOption(EXPORT_RESULTS_PREFIX); addNextCLIOption(RESUME); addNextCLIOption(RERUN); addNextCLIOption(INSECURE_OPTION); } private static void addNextCLIOption(String option) { cliOrder.put(option, cliOptionsCount++); } public ArcMetadata(String args[], int numCmdLineArgs) { super(args, numCmdLineArgs); HELP_USAGE_LINE = commandName + " metadata --profile <profile_name> [options] [list_file]"; HELP_HEADER = "Sets metadata on items from the specified location. Items to update are listed in the list_file.\n"; } @SuppressWarnings({ "static-access", "AccessStaticViaInstance" }) public Options getOptions() { if (cliOptions == null) { Options options = new Options(); // *** Adding a new option needs to be added to the cliOrder list // Note, you cannot do required options with this library and help so we have to add all // as non-required // and deal with it when parsing options.addOption(OptionBuilder.withDescription("Displays this help text (the default behavior).") .withLongOpt(HELP_OPTION).create("h")); // Required options.addOption(OptionBuilder.withArgName("profile_name").hasArg() .withDescription("Target location for the set metadata operation: a namespace profile name.") .withLongOpt(PROFILE_OPTION).create("p")); options.addOption(OptionBuilder.withArgName("path").hasArg() .withDescription("Directory in which to perform the set metadata operation.") .withLongOpt(PATH_OPTION).create()); // Optional options.addOption(OptionBuilder.withArgName("path").hasArg() .withDescription("Custom metadata path. Can be relative or absolute.") .withLongOpt(CUSTOM_METADATA_OPTION).create()); options.addOption(OptionBuilder.withArgName("path").hasArg().withDescription( "ACL path. Can be relative or absolute. This option only applies when updating a HCP 5.0 or later namespace.") .withLongOpt(ACL_OPTION).create()); options.addOption(OptionBuilder.withArgName("path").hasArg() .withDescription( "Owner's name. This option applies only when updating a HCP 5.0 or later namespace.") .withLongOpt(OWNER_OPTION).create()); options.addOption(OptionBuilder.withArgName("path").hasArg() .withDescription( "Owner's domain. This option applies only when updating a HCP 5.0 or later namespace.") .withLongOpt(DOMAIN_OPTION).create()); options.addOption(OptionBuilder.withArgName("true|false").hasArg() .withDescription("Specifies whether copied objects should be marked for indexing.") .withLongOpt(INDEX_OPTION).create()); options.addOption(OptionBuilder.withArgName("true|false").hasArg() .withDescription("Specifies whether copied objects should be marked for shredding.") .withLongOpt(SHRED_OPTION).create()); options.addOption(OptionBuilder.withArgName("true|false").hasArg() .withDescription("Specifies whether objects should be placed on hold.").withLongOpt(HOLD_OPTION) .create()); options.addOption(OptionBuilder.withArgName("retention_setting").hasArg() .withDescription("Retention setting for copied objects.").withLongOpt(RETENTION_OPTION) .create()); options.addOption(OptionBuilder.withArgName("job_name").hasOptionalArg().withDescription( "Reruns the metadata job with the given job name if provided; if no name is provided it reruns the last metadata job run. When rerunning you can change the load and export settings. Any changes to profiles, paths or metadata values will not change what is set in the job.") .withLongOpt(RERUN).create()); options.addOption(OptionBuilder.withArgName("job_name").hasOptionalArg().withDescription( "Resumes the metadata job from where it left off, if no name is provided it resumes the last metadata job run. When rerunning you can change the load and export settings. Any changes to profiles, paths or metadata values will not change what is set in the job.") .withLongOpt(RESUME).create()); options.addOption(OptionBuilder.withArgName("results_types").hasArg().withDescription( "Types of results lists to export: either ALL or a comma-separated list that includes one or more of SUCCESS, FAILURE, and JOBLIST. If omitted no results lists are exported.") .withLongOpt(EXPORT_RESULTS_TYPE).create()); getSharedOptions(options); cliOptions = options; } return cliOptions; } protected void parseArgs() throws ParseException { // create the command cmdLine parser CommandLineParser parser = new PosixParser(); CommandLine cmdLine; // parse the command cmdLine arguments cmdLine = parser.parse(getOptions(), getArgs()); // Help printHelp = cmdLine.hasOption("h"); if (printHelp) { return; } initializeProfiles(cmdLine.hasOption("insecure")); // See how we are getting the input list: file or from stdin @SuppressWarnings({ "unchecked" }) List<String> argList = cmdLine.getArgList(); // Handle the load schedule and export lists LoadSchedule schedule = LoadSchedule.getDefaultLoadSchedule(); getLoadSchedule(cmdLine, schedule); setUpExportListThread(cmdLine); // See if we are rerunning, set up the job if we are boolean rerunning = handleRerunAndResume(cmdLine, schedule); if (rerunning) { List<String> extraOptions = new ArrayList<String>(); if (cmdLine.hasOption(PROFILE_OPTION)) { extraOptions.add(PROFILE_OPTION); } if (cmdLine.hasOption(PATH_OPTION)) { extraOptions.add(PATH_OPTION); } if (cmdLine.hasOption(JOB_NAME)) { extraOptions.add(JOB_NAME); } if (cmdLine.hasOption(HOLD_OPTION)) { extraOptions.add(HOLD_OPTION); } if (cmdLine.hasOption(INDEX_OPTION)) { extraOptions.add(INDEX_OPTION); } if (cmdLine.hasOption(SHRED_OPTION)) { extraOptions.add(SHRED_OPTION); } if (cmdLine.hasOption(RETENTION_OPTION)) { extraOptions.add(RETENTION_OPTION); } if (cmdLine.hasOption(CUSTOM_METADATA_OPTION)) { extraOptions.add(CUSTOM_METADATA_OPTION); } if (cmdLine.hasOption(ACL_OPTION)) { extraOptions.add(ACL_OPTION); } if (cmdLine.hasOption(OWNER_OPTION)) { extraOptions.add(OWNER_OPTION); } if (cmdLine.hasOption(DOMAIN_OPTION)) { extraOptions.add(DOMAIN_OPTION); } if (!extraOptions.isEmpty()) { throw new ParseException("The following supplied options are not allowed with --" + RESUME + " or --" + RERUN + ": " + extraOptions); } // The list_file is not allowed for rerun/resume if (argList.size() > numCmdLineArgs - 1) { throw new ParseException( "The list_file argument is not allowed with --" + RESUME + " or --" + RERUN); } } else { if (argList.size() != numCmdLineArgs) { throw new ParseException("Missing argument list_file."); } String listFileName = argList.get(numCmdLineArgs - 1); // Required fields // Parse require options String profileName = getProfileNameFromCmdLineAndValidateExistance(cmdLine, PROFILE_OPTION); AbstractProfileBase profile = ProfileManager.getProfileByName(profileName); if (!profile.isAuthNamespace()) { throw new ParseException("Metadata may only be set on HCP namespaces."); } String path = validatePath(cmdLine); // Optional fields String jobName = null; if (cmdLine.hasOption(JOB_NAME)) { jobName = cmdLine.getOptionValue(JOB_NAME); } FileMetadata metadata = new FileMetadata(); if (cmdLine.hasOption(INDEX_OPTION)) { metadata.setSearchIndex(new Boolean(cmdLine.getOptionValue(INDEX_OPTION))); } if (cmdLine.hasOption(HOLD_OPTION)) { metadata.setRetentionHold(new Boolean(cmdLine.getOptionValue(HOLD_OPTION))); } if (cmdLine.hasOption(SHRED_OPTION)) { metadata.setShred(new Boolean(cmdLine.getOptionValue(SHRED_OPTION))); } if (cmdLine.hasOption(RETENTION_OPTION)) { String cmdLineRetentionValue = cmdLine.getOptionValue(RETENTION_OPTION); Retention retention = Retention.fromHcapValue(cmdLineRetentionValue); metadata.setRetention(retention); } if (cmdLine.hasOption(CUSTOM_METADATA_OPTION)) { CustomMetadata customMetadata = new CustomMetadata(CustomMetadata.Form.FILE, cmdLine.getOptionValue(CUSTOM_METADATA_OPTION)); metadata.setCustomMetadata(customMetadata); } if (cmdLine.hasOption(ACL_OPTION)) { if (profile.supportsACLs()) { ACLMetadata acl = new ACLMetadata(CustomMetadata.Form.FILE, cmdLine.getOptionValue(ACL_OPTION)); metadata.setACL(acl); } else { throw new ParseException("The " + ACL_OPTION + " may only be specified when updating a HCP 5.0 or later namespace."); } } // throw an exception if anonymous user tries to set owner for objects if (profile.isAnonymousAccess()) { if (cmdLine.hasOption(OWNER_OPTION)) { throw new ParseException("Cannot use owner option with an anonymous namespace profile."); } } if (profile.supportsOwner()) { if (cmdLine.hasOption(OWNER_OPTION)) { Owner owner; if (cmdLine.hasOption(DOMAIN_OPTION)) { owner = new Owner(cmdLine.getOptionValue(OWNER_OPTION), cmdLine.getOptionValue(DOMAIN_OPTION)); } else { String ownerName = cmdLine.getOptionValue(OWNER_OPTION); if (ownerName.length() == 0) { owner = new Owner(Owner.OwnerType.PUBLIC); } else { owner = new Owner(ownerName); } } metadata.setOwner(owner); } } else { List<String> extraOptions = new ArrayList<String>(); if (cmdLine.hasOption(OWNER_OPTION)) { extraOptions.add(OWNER_OPTION); } if (cmdLine.hasOption(DOMAIN_OPTION)) { extraOptions.add(DOMAIN_OPTION); } if (!extraOptions.isEmpty()) { throw new ParseException( "The following supplied options are only allowed when copying from the local file system to an HCP 5.0 or later namespace: " + extraOptions); } } // Validate the input file if one was provided try { FileListParser.validateFile(new File(listFileName), profile, path, ""); } catch (IOException e) { throw new ParseException("Error parsing input file. Msg: " + e.getMessage()); } catch (FileListParserException e) { throw new ParseException("Error parsing input file. Msg: " + e.getMessage()); } // Setup the job with the arguments try { setupMetadataJob(listFileName, profile, path, jobName, metadata, schedule); managedJobImpl = arcMover.createManagedJob(managedJob); } catch (Exception e) { LOG.log(Level.SEVERE, "An error occurred preparing a metadata job", e); throw new ParseException( "Error writing to database during file list parsing. Msg: " + e.getMessage()); } } } private String validatePath(CommandLine cmdLine) throws ParseException { if (!cmdLine.hasOption(PATH_OPTION)) { throw new ParseException("Missing Option: " + PATH_OPTION); } String value = cmdLine.getOptionValue(PATH_OPTION); String retval = null; if (value != null) { retval = value; } if (retval == null) { throw new ParseException("Invalid " + PATH_OPTION + " : " + value); } return retval; } protected void appendAdditionalOutput(ManagedJobStats jobStats, StringBuilder sb, String padding) { // no-op } @Override protected String getFormattedJobStats(ManagedJobStats jobStats) { return String.format("%3$,d objects found, %1$,d/%2$,d objects updated", jobStats.getCompletedObjectCount(), jobStats.getTotalObjectCount(), jobStats.getDiscoveredObjectCount()); } protected String getErrorMessage() { return " failed to update metadata because: "; } protected ManagedJob.Type getJobType() { return ManagedJob.Type.SET_METADATA; } protected JobId getLastJobID() throws NumberFormatException { return new JobId(Long.parseLong(HCPMoverProperties.LAST_METADATA_JOB_RUN.get())); } private void setupMetadataJob(String listFileName, AbstractProfileBase profile, String path, String jobName, FileMetadata metadata, LoadSchedule schedule) throws DatabaseException { SetMetadataJob job = new SetMetadataJob(profile, new File(listFileName)); managedJob = job; managedJob.setSourcePath(profile.encode(path)); if (jobName != null) { managedJob.setUserDefinedJobName(jobName); } managedJob.setLoadSchedule(schedule); ((SetMetadataJob) managedJob).setIngestionMetadata(metadata); } public boolean supportsConflictReports() { return false; } }