mirror of
https://gitlab.com/oeffi/public-transport-enabler.git
synced 2025-07-14 08:40:29 +00:00
parse XML directly from input stream
git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@271 0924bc21-9374-b0fa-ee44-9ff1593b38f0
This commit is contained in:
parent
8e19081ca9
commit
a3ad65eabe
3 changed files with 96 additions and 27 deletions
|
@ -19,7 +19,8 @@ package de.schildbach.pte;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.InputStream;
|
||||||
|
import java.net.SocketTimeoutException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -54,20 +55,24 @@ import de.schildbach.pte.util.XmlPullUtil;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractEfaProvider implements NetworkProvider
|
public abstract class AbstractEfaProvider implements NetworkProvider
|
||||||
{
|
{
|
||||||
|
private static final String DEFAULT_ENCODING = "ISO-8859-1";
|
||||||
|
|
||||||
protected abstract String autocompleteUri(final CharSequence constraint);
|
protected abstract String autocompleteUri(final CharSequence constraint);
|
||||||
|
|
||||||
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
||||||
{
|
{
|
||||||
final String uri = autocompleteUri(constraint);
|
final String uri = autocompleteUri(constraint);
|
||||||
|
|
||||||
|
InputStream is = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
final CharSequence page = ParserUtils.scrape(uri);
|
is = ParserUtils.scrapeInputStream(uri);
|
||||||
|
|
||||||
final List<Location> results = new ArrayList<Location>();
|
final List<Location> results = new ArrayList<Location>();
|
||||||
|
|
||||||
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
|
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
|
||||||
final XmlPullParser pp = factory.newPullParser();
|
final XmlPullParser pp = factory.newPullParser();
|
||||||
pp.setInput(new StringReader(page.toString()));
|
pp.setInput(is, DEFAULT_ENCODING);
|
||||||
|
|
||||||
// parse odv name elements
|
// parse odv name elements
|
||||||
XmlPullUtil.jumpToStartTag(pp, null, "itdOdv");
|
XmlPullUtil.jumpToStartTag(pp, null, "itdOdv");
|
||||||
|
@ -99,6 +104,15 @@ public abstract class AbstractEfaProvider implements NetworkProvider
|
||||||
{
|
{
|
||||||
throw new RuntimeException(x);
|
throw new RuntimeException(x);
|
||||||
}
|
}
|
||||||
|
catch (final SocketTimeoutException x)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(x);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (is != null)
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Location processOdvNameElem(final XmlPullParser pp) throws XmlPullParserException, IOException
|
private Location processOdvNameElem(final XmlPullParser pp) throws XmlPullParserException, IOException
|
||||||
|
@ -168,8 +182,6 @@ public abstract class AbstractEfaProvider implements NetworkProvider
|
||||||
return new Location(LocationType.STATION, id, lat, lon, name);
|
return new Location(LocationType.STATION, id, lat, lon, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern P_NEARBY_MESSAGES = Pattern.compile("(unsere Server zur Zeit ausgelastet)");
|
|
||||||
|
|
||||||
protected abstract String nearbyLatLonUri(int lat, int lon);
|
protected abstract String nearbyLatLonUri(int lat, int lon);
|
||||||
|
|
||||||
protected abstract String nearbyStationUri(String stationId);
|
protected abstract String nearbyStationUri(String stationId);
|
||||||
|
@ -185,16 +197,14 @@ public abstract class AbstractEfaProvider implements NetworkProvider
|
||||||
if (uri == null)
|
if (uri == null)
|
||||||
throw new IllegalArgumentException("at least one of stationId or lat/lon must be given");
|
throw new IllegalArgumentException("at least one of stationId or lat/lon must be given");
|
||||||
|
|
||||||
|
InputStream is = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
final CharSequence page = ParserUtils.scrape(uri);
|
is = ParserUtils.scrapeInputStream(uri);
|
||||||
|
|
||||||
if (P_NEARBY_MESSAGES.matcher(page).find())
|
|
||||||
return new NearbyStationsResult(uri, NearbyStationsResult.Status.SERVICE_DOWN);
|
|
||||||
|
|
||||||
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
|
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
|
||||||
final XmlPullParser pp = factory.newPullParser();
|
final XmlPullParser pp = factory.newPullParser();
|
||||||
pp.setInput(new StringReader(page.toString()));
|
pp.setInput(is, DEFAULT_ENCODING);
|
||||||
|
|
||||||
XmlPullUtil.jumpToStartTag(pp, null, "itdOdvName");
|
XmlPullUtil.jumpToStartTag(pp, null, "itdOdvName");
|
||||||
final String nameState = pp.getAttributeValue(null, "state");
|
final String nameState = pp.getAttributeValue(null, "state");
|
||||||
|
@ -274,6 +284,15 @@ public abstract class AbstractEfaProvider implements NetworkProvider
|
||||||
{
|
{
|
||||||
return new NearbyStationsResult(uri, NearbyStationsResult.Status.SERVICE_DOWN);
|
return new NearbyStationsResult(uri, NearbyStationsResult.Status.SERVICE_DOWN);
|
||||||
}
|
}
|
||||||
|
catch (final SocketTimeoutException x)
|
||||||
|
{
|
||||||
|
return new NearbyStationsResult(uri, NearbyStationsResult.Status.SERVICE_DOWN);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (is != null)
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern P_LINE_IRE = Pattern.compile("IRE\\d+");
|
private static final Pattern P_LINE_IRE = Pattern.compile("IRE\\d+");
|
||||||
|
@ -533,13 +552,14 @@ public abstract class AbstractEfaProvider implements NetworkProvider
|
||||||
|
|
||||||
public QueryDeparturesResult queryDepartures(final String uri) throws IOException
|
public QueryDeparturesResult queryDepartures(final String uri) throws IOException
|
||||||
{
|
{
|
||||||
|
InputStream is = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
final CharSequence page = ParserUtils.scrape(uri);
|
is = ParserUtils.scrapeInputStream(uri);
|
||||||
|
|
||||||
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
|
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
|
||||||
final XmlPullParser pp = factory.newPullParser();
|
final XmlPullParser pp = factory.newPullParser();
|
||||||
pp.setInput(new StringReader(page.toString()));
|
pp.setInput(is, DEFAULT_ENCODING);
|
||||||
|
|
||||||
XmlPullUtil.jumpToStartTag(pp, null, "itdOdvName");
|
XmlPullUtil.jumpToStartTag(pp, null, "itdOdvName");
|
||||||
final String nameState = pp.getAttributeValue(null, "state");
|
final String nameState = pp.getAttributeValue(null, "state");
|
||||||
|
@ -602,6 +622,15 @@ public abstract class AbstractEfaProvider implements NetworkProvider
|
||||||
{
|
{
|
||||||
return new QueryDeparturesResult(uri, QueryDeparturesResult.Status.SERVICE_DOWN);
|
return new QueryDeparturesResult(uri, QueryDeparturesResult.Status.SERVICE_DOWN);
|
||||||
}
|
}
|
||||||
|
catch (final SocketTimeoutException x)
|
||||||
|
{
|
||||||
|
return new QueryDeparturesResult(uri, QueryDeparturesResult.Status.SERVICE_DOWN);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (is != null)
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processItdDateTime(final XmlPullParser pp, final Calendar calendar) throws XmlPullParserException, IOException
|
private void processItdDateTime(final XmlPullParser pp, final Calendar calendar) throws XmlPullParserException, IOException
|
||||||
|
@ -654,25 +683,49 @@ public abstract class AbstractEfaProvider implements NetworkProvider
|
||||||
{
|
{
|
||||||
final String uri = connectionsQueryUri(from, via, to, date, dep, products, walkSpeed) + "&sessionID=0";
|
final String uri = connectionsQueryUri(from, via, to, date, dep, products, walkSpeed) + "&sessionID=0";
|
||||||
|
|
||||||
final CharSequence page = ParserUtils.scrape(uri);
|
InputStream is = null;
|
||||||
|
try
|
||||||
return queryConnections(uri, page);
|
{
|
||||||
|
is = ParserUtils.scrapeInputStream(uri);
|
||||||
|
return queryConnections(uri, is);
|
||||||
|
}
|
||||||
|
catch (final SocketTimeoutException x)
|
||||||
|
{
|
||||||
|
return new QueryConnectionsResult(QueryConnectionsResult.Status.SERVICE_DOWN);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (is != null)
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
|
public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
|
||||||
{
|
{
|
||||||
final CharSequence page = ParserUtils.scrape(uri);
|
InputStream is = null;
|
||||||
|
try
|
||||||
return queryConnections(uri, page);
|
{
|
||||||
|
is = ParserUtils.scrapeInputStream(uri);
|
||||||
|
return queryConnections(uri, is);
|
||||||
|
}
|
||||||
|
catch (final SocketTimeoutException x)
|
||||||
|
{
|
||||||
|
return new QueryConnectionsResult(QueryConnectionsResult.Status.SERVICE_DOWN);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (is != null)
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryConnectionsResult queryConnections(final String uri, final CharSequence page) throws IOException
|
private QueryConnectionsResult queryConnections(final String uri, final InputStream is) throws IOException
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
|
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
|
||||||
final XmlPullParser pp = factory.newPullParser();
|
final XmlPullParser pp = factory.newPullParser();
|
||||||
pp.setInput(new StringReader(page.toString()));
|
pp.setInput(is, DEFAULT_ENCODING);
|
||||||
|
|
||||||
if (!XmlPullUtil.jumpToStartTag(pp, null, "itdRequest"))
|
if (!XmlPullUtil.jumpToStartTag(pp, null, "itdRequest"))
|
||||||
throw new IllegalStateException("cannot find <itdRequest />");
|
throw new IllegalStateException("cannot find <itdRequest />");
|
||||||
|
|
|
@ -27,7 +27,7 @@ public final class QueryConnectionsResult implements Serializable
|
||||||
{
|
{
|
||||||
public enum Status
|
public enum Status
|
||||||
{
|
{
|
||||||
OK, AMBIGUOUS, TOO_CLOSE, NO_CONNECTIONS, INVALID_DATE;
|
OK, AMBIGUOUS, TOO_CLOSE, NO_CONNECTIONS, INVALID_DATE, SERVICE_DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final QueryConnectionsResult TOO_CLOSE = new QueryConnectionsResult(Status.TOO_CLOSE);
|
public static final QueryConnectionsResult TOO_CLOSE = new QueryConnectionsResult(Status.TOO_CLOSE);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package de.schildbach.pte.util;
|
package de.schildbach.pte.util;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
@ -55,19 +56,19 @@ public final class ParserUtils
|
||||||
stateCookie = null;
|
stateCookie = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CharSequence scrape(final String url) throws IOException
|
public static final CharSequence scrape(final String url) throws IOException
|
||||||
{
|
{
|
||||||
return scrape(url, false, null, null, false);
|
return scrape(url, false, null, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CharSequence scrape(final String url, final boolean isPost, final String request, String encoding, final boolean cookieHandling)
|
public static final CharSequence scrape(final String url, final boolean isPost, final String request, String encoding,
|
||||||
throws IOException
|
final boolean cookieHandling) throws IOException
|
||||||
{
|
{
|
||||||
return scrape(url, isPost, request, encoding, cookieHandling, 3);
|
return scrape(url, isPost, request, encoding, cookieHandling, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CharSequence scrape(final String url, final boolean isPost, final String request, String encoding, final boolean cookieHandling,
|
public static final CharSequence scrape(final String url, final boolean isPost, final String request, String encoding,
|
||||||
int tries) throws IOException
|
final boolean cookieHandling, int tries) throws IOException
|
||||||
{
|
{
|
||||||
if (encoding == null)
|
if (encoding == null)
|
||||||
encoding = SCRAPE_DEFAULT_ENCODING;
|
encoding = SCRAPE_DEFAULT_ENCODING;
|
||||||
|
@ -149,7 +150,7 @@ public final class ParserUtils
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long copy(final Reader reader, final StringBuilder builder) throws IOException
|
private static final long copy(final Reader reader, final StringBuilder builder) throws IOException
|
||||||
{
|
{
|
||||||
final char[] buffer = new char[SCRAPE_INITIAL_CAPACITY];
|
final char[] buffer = new char[SCRAPE_INITIAL_CAPACITY];
|
||||||
long count = 0;
|
long count = 0;
|
||||||
|
@ -162,6 +163,21 @@ public final class ParserUtils
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final InputStream scrapeInputStream(final String url) throws IOException
|
||||||
|
{
|
||||||
|
final HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.setDoOutput(false);
|
||||||
|
connection.setConnectTimeout(SCRAPE_CONNECT_TIMEOUT);
|
||||||
|
connection.setReadTimeout(SCRAPE_READ_TIMEOUT);
|
||||||
|
connection.addRequestProperty("User-Agent", SCRAPE_USER_AGENT);
|
||||||
|
// workaround to disable Vodafone compression
|
||||||
|
connection.addRequestProperty("Cache-Control", "no-cache");
|
||||||
|
|
||||||
|
return connection.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
private static final Pattern P_ENTITY = Pattern.compile("&(?:#(x[\\da-f]+|\\d+)|(amp|quot|apos));");
|
private static final Pattern P_ENTITY = Pattern.compile("&(?:#(x[\\da-f]+|\\d+)|(amp|quot|apos));");
|
||||||
|
|
||||||
public static String resolveEntities(final CharSequence str)
|
public static String resolveEntities(final CharSequence str)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue