/** * Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org> * Copyright (C) 2011 Google, Inc. * * 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 org.onebusaway.transit_data_federation.bundle; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.Parser; import org.onebusaway.gtfs.impl.GtfsRelationalDaoImpl; import org.onebusaway.transit_data_federation.bundle.model.GtfsBundle; import org.onebusaway.transit_data_federation.bundle.model.GtfsBundles; import org.opentripplanner.graph_builder.impl.osm.FileBasedOpenStreetMapProviderImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.jdbc.datasource.DriverManagerDataSource; /** * Command line tool for federated transit data bundle creator. Allows * {@link FederatedTransitDataBundleCreator} to configured and run from the * command line. * * @author bdferris * @see FederatedTransitDataBundleCreator */ public class FederatedTransitDataBundleCreatorMain { private static final Logger _log = LoggerFactory.getLogger(FederatedTransitDataBundleCreatorMain.class); private static final String ARG_SKIP_TO = "skipTo"; private static final String ARG_ONLY = "only"; private static final String ARG_SKIP = "skip"; private static final String ARG_INCLUDE = "include"; private static final String ARG_ONLY_IF_DNE = "onlyIfDoesNotExist"; private static final String ARG_USE_DATABASE_FOR_GTFS = "useDatabaseForGtfs"; private static final String ARG_DATASOURCE_DRIVER_CLASS_NAME = "dataSourceDriverClassName"; private static final String ARG_DATASOURCE_URL = "dataSourceUrl"; private static final String ARG_DATASOURCE_USERNAME = "dataSourceUsername"; private static final String ARG_DATASOURCE_PASSWORD = "dataSourcePassword"; private static final String ARG_BUNDLE_KEY = "bundleKey"; private static final String ARG_RANDOMIZE_CACHE_DIR = "randomizeCacheDir"; private static final String ARG_ADDITIONAL_RESOURCES_DIRECTORY = "additionalResourcesDirectory"; private static final String ARG_OSM = "osm"; public static void main(String[] args) throws Exception { System.out.println(System.getProperties()); FederatedTransitDataBundleCreatorMain main = new FederatedTransitDataBundleCreatorMain(); main.run(args); } 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); } protected void buildOptions(Options options) { options.addOption(ARG_USE_DATABASE_FOR_GTFS, false, ""); options.addOption(ARG_SKIP_TO, true, ""); options.addOption(ARG_ONLY, true, ""); options.addOption(ARG_SKIP, true, ""); options.addOption(ARG_INCLUDE, true, ""); options.addOption(ARG_ONLY_IF_DNE, false, ""); options.addOption(ARG_DATASOURCE_DRIVER_CLASS_NAME, true, ""); options.addOption(ARG_DATASOURCE_URL, true, ""); options.addOption(ARG_DATASOURCE_USERNAME, true, ""); options.addOption(ARG_DATASOURCE_PASSWORD, true, ""); options.addOption(ARG_BUNDLE_KEY, true, ""); options.addOption(ARG_RANDOMIZE_CACHE_DIR, false, ""); options.addOption(ARG_ADDITIONAL_RESOURCES_DIRECTORY, true, ""); options.addOption(ARG_OSM, true, ""); Option dOption = new Option("D", "use value for given property"); dOption.setArgName("property=value"); dOption.setArgs(2); dOption.setValueSeparator('='); options.addOption(dOption); Option pOption = new Option("P", "use value for given property"); pOption.setArgName("beanName.beanProperty=value"); pOption.setArgs(2); pOption.setValueSeparator('='); options.addOption(pOption); } protected void printUsage() { InputStream is = getClass().getResourceAsStream("usage.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line = null; try { while ((line = reader.readLine()) != null) { System.err.println(line); } } catch (IOException ex) { } finally { if (reader != null) { try { reader.close(); } catch (IOException ex) { } } } } 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); } } protected void copyFiles(File from, File to) throws IOException { if (!from.exists()) return; if (from.isDirectory()) { to.mkdirs(); for (File fromChild : from.listFiles()) { File toChild = new File(to, fromChild.getName()); copyFiles(fromChild, toChild); } } else { FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream(from); out = new FileOutputStream(to); int byteCount = 0; byte[] buffer = new byte[1024]; while ((byteCount = in.read(buffer)) >= 0) out.write(buffer, 0, byteCount); } finally { if (in != null) in.close(); if (out != null) out.close(); } } } }