protected void setStagesToSkip(
      CommandLine commandLine, FederatedTransitDataBundleCreator creator) {

    if (commandLine.hasOption(ARG_SKIP_TO)) {
      String value = commandLine.getOptionValue(ARG_SKIP_TO);
      creator.setSkipToTask(value);
    }

    if (commandLine.hasOption(ARG_ONLY)) {
      String[] values = commandLine.getOptionValues(ARG_ONLY);
      for (String value : values) creator.addTaskToOnlyRun(value);
    }

    if (commandLine.hasOption(ARG_SKIP)) {
      String[] values = commandLine.getOptionValues(ARG_SKIP);
      for (String value : values) creator.addTaskToSkip(value);
    }

    if (commandLine.hasOption(ARG_INCLUDE)) {
      String[] values = commandLine.getOptionValues(ARG_INCLUDE);
      for (String value : values) creator.addTaskToInclude(value);
    }
  }
  public void run(String[] args) throws Exception {

    try {
      Parser parser = new GnuParser();

      Options options = new Options();
      buildOptions(options);

      CommandLine commandLine = parser.parse(options, args);

      String[] remainingArgs = commandLine.getArgs();

      if (remainingArgs.length < 2) {
        printUsage();
        System.exit(-1);
      }

      FederatedTransitDataBundleCreator creator = new FederatedTransitDataBundleCreator();

      Map<String, BeanDefinition> beans = new HashMap<String, BeanDefinition>();
      creator.setContextBeans(beans);

      List<GtfsBundle> gtfsBundles = new ArrayList<GtfsBundle>();
      List<String> contextPaths = new ArrayList<String>();

      for (int i = 0; i < remainingArgs.length - 1; i++) {
        File path = new File(remainingArgs[i]);
        if (path.isDirectory() || path.getName().endsWith(".zip")) {
          GtfsBundle gtfsBundle = new GtfsBundle();
          gtfsBundle.setPath(path);
          gtfsBundles.add(gtfsBundle);
        } else {
          contextPaths.add("file:" + path);
        }
      }

      if (!gtfsBundles.isEmpty()) {
        BeanDefinitionBuilder bean = BeanDefinitionBuilder.genericBeanDefinition(GtfsBundles.class);
        bean.addPropertyValue("bundles", gtfsBundles);
        beans.put("gtfs-bundles", bean.getBeanDefinition());
      }

      if (commandLine.hasOption(ARG_USE_DATABASE_FOR_GTFS)) {
        contextPaths.add("classpath:org/onebusaway/gtfs/application-context.xml");
      } else {
        BeanDefinitionBuilder bean =
            BeanDefinitionBuilder.genericBeanDefinition(GtfsRelationalDaoImpl.class);
        beans.put("gtfsRelationalDaoImpl", bean.getBeanDefinition());
      }

      if (commandLine.hasOption(ARG_DATASOURCE_URL)) {
        String dataSourceUrl = commandLine.getOptionValue(ARG_DATASOURCE_URL);
        BeanDefinitionBuilder bean =
            BeanDefinitionBuilder.genericBeanDefinition(DriverManagerDataSource.class);
        bean.addPropertyValue("url", dataSourceUrl);
        if (commandLine.hasOption(ARG_DATASOURCE_DRIVER_CLASS_NAME))
          bean.addPropertyValue(
              "driverClassName", commandLine.getOptionValue(ARG_DATASOURCE_DRIVER_CLASS_NAME));
        if (commandLine.hasOption(ARG_DATASOURCE_USERNAME))
          bean.addPropertyValue("username", commandLine.getOptionValue(ARG_DATASOURCE_USERNAME));
        if (commandLine.hasOption(ARG_DATASOURCE_PASSWORD))
          bean.addPropertyValue("password", commandLine.getOptionValue(ARG_DATASOURCE_PASSWORD));
        beans.put("dataSource", bean.getBeanDefinition());
      }

      if (commandLine.hasOption(ARG_OSM)) {
        File osmPath = new File(commandLine.getOptionValue(ARG_OSM));
        BeanDefinitionBuilder bean =
            BeanDefinitionBuilder.genericBeanDefinition(FileBasedOpenStreetMapProviderImpl.class);
        bean.addPropertyValue("path", osmPath);
        beans.put("osmProvider", bean.getBeanDefinition());
      }

      File outputPath = new File(remainingArgs[remainingArgs.length - 1]);

      if (commandLine.hasOption(ARG_ONLY_IF_DNE) && outputPath.exists()) {
        System.err.println("Bundle path already exists.  Exiting...");
        System.exit(0);
      }

      if (commandLine.hasOption(ARG_RANDOMIZE_CACHE_DIR)) creator.setRandomizeCacheDir(true);

      if (commandLine.hasOption(ARG_BUNDLE_KEY)) {
        String key = commandLine.getOptionValue(ARG_BUNDLE_KEY);
        creator.setBundleKey(key);
      }

      /**
       * Optionally override any system properties (ok this duplicates existing functionality, yes,
       * but it allows for -D arguments after the main class)
       */
      if (commandLine.hasOption("D")) {
        Properties props = commandLine.getOptionProperties("D");
        for (Object key : props.keySet()) {
          String propName = (String) key;
          String propValue = props.getProperty(propName);
          System.setProperty(propName, propValue);
        }
      }

      /**
       * Optionally override any system properties (ok this duplicates existing functionality, yes,
       * but it allows for -D arguments after the main class)
       */
      if (commandLine.hasOption("P")) {
        Properties props = commandLine.getOptionProperties("P");
        creator.setAdditionalBeanPropertyOverrides(props);
      }

      setStagesToSkip(commandLine, creator);

      creator.setOutputPath(outputPath);
      creator.setContextPaths(contextPaths);

      try {

        if (commandLine.hasOption(ARG_ADDITIONAL_RESOURCES_DIRECTORY)) {
          File additionalResourceDirectory =
              new File(commandLine.getOptionValue(ARG_ADDITIONAL_RESOURCES_DIRECTORY));
          copyFiles(additionalResourceDirectory, outputPath);
        }

        creator.run();
      } catch (Exception ex) {
        _log.error("error building transit data bundle", ex);
        System.exit(-1);
      }
    } catch (ParseException ex) {
      System.err.println(ex.getLocalizedMessage());
      printUsage();
      System.exit(-1);
    }

    System.exit(0);
  }