Java tutorial
/** * Copyright 2011-2017 Asakusa Framework Team. * * 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.asakusafw.testdriver.tools.runner; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.TreeMap; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.asakusafw.testdriver.TestDriverContext; import com.asakusafw.vocabulary.batch.BatchDescription; import com.asakusafw.vocabulary.batch.JobFlowWorkDescription; import com.asakusafw.vocabulary.batch.Work; import com.asakusafw.vocabulary.batch.WorkDescription; import com.asakusafw.vocabulary.external.ExporterDescription; import com.asakusafw.vocabulary.external.ImporterDescription; import com.asakusafw.vocabulary.flow.Export; import com.asakusafw.vocabulary.flow.FlowDescription; import com.asakusafw.vocabulary.flow.Import; /** * Truncates batch execution inputs/outputs. * @see BatchTestRunner * @since 0.7.3 */ public class BatchTestTruncator extends BatchTestTool { static final Logger LOG = LoggerFactory.getLogger(BatchTestTruncator.class); static final Option OPT_DESCRIPTION; static final Option OPT_ARGUMENT; static final Option OPT_PROPERTY; private static final Options OPTIONS; static { OPT_DESCRIPTION = new Option(null, "description", true, //$NON-NLS-1$ Messages.getString("BatchTestTruncator.optDescription")); //$NON-NLS-1$ OPT_DESCRIPTION.setArgName("description class name"); //$NON-NLS-1$ OPT_DESCRIPTION.setRequired(true); OPT_ARGUMENT = new Option("A", "argument", true, //$NON-NLS-1$ //$NON-NLS-2$ Messages.getString("BatchTestTruncator.optArgument")); //$NON-NLS-1$ OPT_ARGUMENT.setArgs(2); OPT_ARGUMENT.setValueSeparator('='); OPT_ARGUMENT.setArgName("name=value"); //$NON-NLS-1$ OPT_ARGUMENT.setRequired(false); OPT_PROPERTY = new Option("D", "property", true, //$NON-NLS-1$ //$NON-NLS-2$ Messages.getString("BatchTestTruncator.optProperty")); //$NON-NLS-1$ OPT_PROPERTY.setArgs(2); OPT_PROPERTY.setValueSeparator('='); OPT_PROPERTY.setArgName("name=value"); //$NON-NLS-1$ OPT_PROPERTY.setRequired(false); OPTIONS = new Options(); OPTIONS.addOption(OPT_DESCRIPTION); OPTIONS.addOption(OPT_ARGUMENT); OPTIONS.addOption(OPT_PROPERTY); } /** * Creates a new instance. * @param context the current context */ public BatchTestTruncator(TestDriverContext context) { super(context); } /** * Program entry. * @param args program arguments */ public static void main(String[] args) { int exitCode = execute(args); if (exitCode != 0) { System.exit(exitCode); } } /** * Program entry. * @param args program arguments * @return the exit code */ public static int execute(String[] args) { Conf conf; try { conf = parseArguments(args); } catch (Exception e) { HelpFormatter formatter = new HelpFormatter(); formatter.setWidth(Integer.MAX_VALUE); formatter.printHelp(MessageFormat.format("java -classpath ... {0}", //$NON-NLS-1$ BatchTestRunner.class.getName()), OPTIONS, true); LOG.error(MessageFormat.format(Messages.getString("BatchTestTruncator.errorInvalidArgument"), //$NON-NLS-1$ Arrays.toString(args)), e); return 1; } try { BatchTestTruncator truncator = new BatchTestTruncator(conf.context); for (ImporterDescription desc : conf.importers) { truncator.truncate(desc); } for (ExporterDescription desc : conf.exporters) { truncator.truncate(desc); } return 0; } catch (Exception e) { LOG.error(MessageFormat.format(Messages.getString("BatchTestTruncator.errorFailedToTruncate"), //$NON-NLS-1$ Arrays.toString(args)), e); return 1; } } static Conf parseArguments(String[] args) throws ParseException { assert args != null; CommandLineParser parser = new BasicParser(); CommandLine cmd = parser.parse(OPTIONS, args); Conf conf = new Conf(); String descriptionClass = cmd.getOptionValue(OPT_DESCRIPTION.getLongOpt()); Class<?> description; try { description = Class.forName(descriptionClass); } catch (Exception e) { throw new IllegalArgumentException( MessageFormat.format(Messages.getString("BatchTestTruncator.errorFailedToAnalyze"), //$NON-NLS-1$ descriptionClass), e); } conf.context = new TestDriverContext(description); resolveDescription(conf, description); Properties arguments = cmd.getOptionProperties(OPT_ARGUMENT.getOpt()); conf.context.getBatchArgs().putAll(toMap(arguments)); Properties properties = cmd.getOptionProperties(OPT_PROPERTY.getOpt()); conf.context.getExtraConfigurations().putAll(toMap(properties)); return conf; } private static void resolveDescription(Conf conf, Class<?> description) { if (BatchDescription.class.isAssignableFrom(description)) { resolveBatch(conf, description.asSubclass(BatchDescription.class)); } else if (FlowDescription.class.isAssignableFrom(description)) { resolveFlow(conf, description.asSubclass(FlowDescription.class)); } else if (ImporterDescription.class.isAssignableFrom(description)) { resolveImporter(conf, description.asSubclass(ImporterDescription.class)); } else if (ExporterDescription.class.isAssignableFrom(description)) { resolveExporter(conf, description.asSubclass(ExporterDescription.class)); } else { throw new IllegalArgumentException( MessageFormat.format(Messages.getString("BatchTestTruncator.errorInvalidTarget"), //$NON-NLS-1$ description.getName())); } } private static void resolveBatch(Conf conf, Class<? extends BatchDescription> aClass) { LOG.debug("analyzing batch: {}", aClass.getName()); //$NON-NLS-1$ List<Class<? extends FlowDescription>> flows = new ArrayList<>(); try { BatchDescription batch = aClass.newInstance(); batch.start(); for (Work work : batch.getWorks()) { WorkDescription desc = work.getDescription(); if (desc instanceof JobFlowWorkDescription) { Class<? extends FlowDescription> flow = ((JobFlowWorkDescription) desc).getFlowClass(); flows.add(flow); } } } catch (ReflectiveOperationException e) { throw new IllegalArgumentException( MessageFormat.format(Messages.getString("BatchTestTruncator.errorInvalidBatchClass"), //$NON-NLS-1$ aClass.getName())); } for (Class<? extends FlowDescription> flow : flows) { resolveFlow(conf, flow); } } private static void resolveFlow(Conf conf, Class<? extends FlowDescription> aClass) { LOG.debug("analyzing jobflow: {}", aClass.getName()); //$NON-NLS-1$ Constructor<?>[] ctors = aClass.getConstructors(); if (FlowDescription.isJobFlow(aClass) == false || ctors.length != 1) { throw new IllegalArgumentException( MessageFormat.format(Messages.getString("BatchTestTruncator.errorInvalidJobflowClass"), //$NON-NLS-1$ aClass.getName())); } for (Annotation[] as : ctors[0].getParameterAnnotations()) { for (Annotation a : as) { if (a.annotationType() == Import.class) { resolveImporter(conf, ((Import) a).description()); } else if (a.annotationType() == Export.class) { resolveExporter(conf, ((Export) a).description()); } } } } private static void resolveImporter(Conf conf, Class<? extends ImporterDescription> aClass) { try { conf.importers.add(aClass.newInstance()); } catch (Exception e) { throw new IllegalArgumentException( MessageFormat.format(Messages.getString("BatchTestTruncator.errorInvalidImporterClass"), //$NON-NLS-1$ aClass.getName()), e); } } private static void resolveExporter(Conf conf, Class<? extends ExporterDescription> aClass) { try { conf.exporters.add(aClass.newInstance()); } catch (Exception e) { throw new IllegalArgumentException( MessageFormat.format(Messages.getString("BatchTestTruncator.errorInvalidExporterClass"), //$NON-NLS-1$ aClass.getName()), e); } } private static Map<String, String> toMap(Properties p) { assert p != null; Map<String, String> results = new TreeMap<>(); for (Map.Entry<Object, Object> entry : p.entrySet()) { results.put((String) entry.getKey(), (String) entry.getValue()); } return results; } private static final class Conf { final List<ImporterDescription> importers = new ArrayList<>(); final List<ExporterDescription> exporters = new ArrayList<>(); TestDriverContext context; Conf() { return; } } }