package net.sourceforge.gpstools;
/* gpsdings
* Copyright (C) 2006 Moritz Ringler
* $Id: GPSDings.java 447 2011-01-18 22:19:43Z ringler $
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.PrintStream;
import java.io.OutputStream;
import java.io.BufferedOutputStream;
import java.io.OutputStreamWriter;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.util.EnumMap;
import java.util.Map;
import java.util.TimeZone;
import java.util.Properties;
import net.sourceforge.gpstools.kml.GpxKMLWriter;
import net.sourceforge.gpstools.utils.GpxReader;
import net.sourceforge.gpstools.utils.TemplateProcessor;
import net.sourceforge.gpstools.gpx.Gpx;
import net.sourceforge.gpstools.gpx.GpxType;
import org.exolab.castor.xml.handlers.DateFieldHandler;
import org.exolab.castor.xml.Marshaller;
import org.xml.sax.InputSource;
/* Serves as a common entry point for the different tools in gpsdings */
public class GPSDings {
private boolean verbose = true;
private TemplateProcessor templateProcessor;
public static enum Output {
MapJS, CSS, HTML, Text, XML, KML, KMZ
}
public final static String ISO_DATE = "yyyy-MM-dd'T'HH:mm:ss";
public final static TimeZone UTC = TimeZone.getTimeZone("UTC");
protected Map<Output, File> output = new EnumMap<Output, File>(Output.class);
private static String version = "";
private static String jsVersion = "";
static {
try {
Properties p = new Properties();
p.load(GPSDings.class.getResourceAsStream("version.properties"));
version = p.getProperty("version") + " (build "
+ p.getProperty("build") + ")";
jsVersion = p.getProperty("jsversion");
} catch (Exception ex) {
ex.printStackTrace();
}
}
protected GPSDings() {
// make default constructor protected.
}
private static enum Application {
gpxovl(GpxOVL.class, "Converts between GPX and OVL formats."),
gpxkml(GpxKMLWriter.class, "Converts GPX to KML."),
googlemap(GoogleMapMaker.class, "Makes Google maps."),
openlayers(OpenLayersMap.class, "Makes OpenLayers slippy maps."),
exifloc(ExifLocator.class, "Finds the geolocation of digital camera pictures."),
trackanalyzer(TrackAnalyzer.class,"Analyzes GPS tracks (speed, distance, ...)"),
shrink(TrackShrink.class, "Shrinks GPS tracks."),
elevations(Elevations.class, "Adds SRTM elevations to GPX files.");
private final Class<? extends GPSDings> clazz;
private final String desc;
Application(Class<? extends GPSDings> klass, String description) {
clazz = klass;
desc = description;
}
public Class<? extends GPSDings> appClass() {
return clazz;
}
public String description() {
return desc;
}
}
public static void printLicense() {
try {
AbstractCommandLine.cat("gpl", GPSDings.class);
} catch (IOException ex) {
throw new Error(ex);
}
}
public static void main(String[] argv) throws Exception {
if (argv.length == 0 || argv[0].equals("-h")
|| argv[0].equals("--help")) {
GPSDings.printHelp(System.out);
System.exit(0);
} else if (argv[0].equals("--license")) {
GPSDings.printLicense();
System.exit(0);
}
String progname = argv[0];
Application app = null;
try {
app = Enum.valueOf(Application.class, argv[0]);
} catch (IllegalArgumentException ex) {
System.err.println("No such application " + progname);
System.exit(1);
}
Class<? extends GPSDings> prog = app.appClass();
String[] args = new String[argv.length - 1];
System.arraycopy(argv, 1, args, 0, args.length);
prog.getMethod("main", args.getClass()).invoke(null, (Object) args);
}
public static String getApplicationInfo() {
return "gpsdings "
+ version
+ " (c) 2006-2011 Moritz Ringler.\n"
+ "This program comes with ABSOLUTELY NO WARRANTY.\n"
+ "This is free software, and you are welcome to redistribute it\n"
+ "under certain conditions; use the --license option for details.";
}
private static void printHelp(PrintStream out) {
out.println(getApplicationInfo());
out.println("USAGE: gpsdings <application> [arguments]");
out.println("Applications in this gpsdings version are:");
for (Application app : Application.values()) {
out.printf(" %s : %s%n", app, app.description());
}
out.println("For help on a specific application use");
out.println("gpsdings <application>");
}
public static String getVersion() {
return version;
}
static String jsVersion() {
return jsVersion;
}
protected void message(Object s) {
if (verbose) {
System.err.println(s);
}
}
public void enableOutput(Output o, File f) {
output.put(o, f);
}
public void enableOutput(Output o, String file) {
output.put(o, "-".equals(file) ? null : new File(file));
}
public void print() throws IOException {
for (Output out : output.keySet()) {
print(out);
}
}
public static void writeGPX(GpxType gpx, OutputStream out)
throws IOException {
final OutputStream bout = (out instanceof BufferedOutputStream) ? out
: new BufferedOutputStream(out);
// The default time zone for GPX is UTC
synchronized (TimeZone.class) {
DateFieldHandler.setSuppressMillis(true);
// This should do the job but it does not
// see http://jira.codehaus.org/browse/CASTOR-2220
DateFieldHandler.setDefaultTimeZone(UTC);
// workaround:
// temporarily set Default TZ to UTC
// //TimeZone tz = TimeZone.getDefault();
// //TimeZone.setDefault(UTC);
try {
Marshaller marshaller = new Marshaller();
marshaller.setWriter(new OutputStreamWriter(bout, "UTF-8"));
marshaller.marshal(gpx);
} catch (Exception ex) {
IOException ioex = new IOException("Error writing GPX.");
ioex.initCause(ex);
throw ioex;
} finally {
// restore old Default TZ
// //TimeZone.setDefault(tz);
}
}
}
public static Gpx readGPX(InputStream in) throws IOException {
Gpx gpx = null;
final InputStream bin = (in instanceof BufferedInputStream) ? in
: new BufferedInputStream(in);
// Does not have the desired effect.
DateFieldHandler.setDefaultTimeZone(UTC);
try {
GpxReader reader = new GpxReader();
reader.parse(new InputSource(bin));
gpx = reader.getGpx();
} catch (Exception ex) {
IOException ioex = new IOException(
"Error parsing GPX. Make sure that the input is in GPX 1.1 format.");
ioex.initCause(ex);
throw ioex;
}
return gpx;
}
/** Subclasses should override this to create output. */
public void print(Output out) throws IOException {
throw new IOException("print(Output) is not supported by"
+ this.getClass() + ".");
}
protected synchronized TemplateProcessor getTemplateProcessor() {
/* lazily initialize templateProcessor */
if (templateProcessor == null) {
try {
templateProcessor = new TemplateProcessor("UTF-8");
} catch (UnsupportedEncodingException cannothappen) {
throw new Error(cannothappen);
}
}
return templateProcessor;
}
public void setQuiet(boolean b) {
verbose = !b;
}
public void handleException(String opt, Throwable ex) {
if (verbose) {
if (opt != null) {
System.err.println("Error processing the " + opt + " option:");
}
System.err.println(ex);
if (ex.getCause() != null) {
System.err.println("Caused by " + ex.getCause());
}
}
if (opt == null && ex instanceof RuntimeException
&& !(ex instanceof IllegalArgumentException)) {
ex.printStackTrace();
}
}
}