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:
andreas.schildbach 2010-10-10 14:29:50 +00:00
parent 8e19081ca9
commit a3ad65eabe
3 changed files with 96 additions and 27 deletions

View file

@ -19,7 +19,8 @@ package de.schildbach.pte;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringReader;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
@ -54,20 +55,24 @@ import de.schildbach.pte.util.XmlPullUtil;
*/
public abstract class AbstractEfaProvider implements NetworkProvider
{
private static final String DEFAULT_ENCODING = "ISO-8859-1";
protected abstract String autocompleteUri(final CharSequence constraint);
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
{
final String uri = autocompleteUri(constraint);
InputStream is = null;
try
{
final CharSequence page = ParserUtils.scrape(uri);
is = ParserUtils.scrapeInputStream(uri);
final List<Location> results = new ArrayList<Location>();
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
final XmlPullParser pp = factory.newPullParser();
pp.setInput(new StringReader(page.toString()));
pp.setInput(is, DEFAULT_ENCODING);
// parse odv name elements
XmlPullUtil.jumpToStartTag(pp, null, "itdOdv");
@ -99,6 +104,15 @@ public abstract class AbstractEfaProvider implements NetworkProvider
{
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
@ -168,8 +182,6 @@ public abstract class AbstractEfaProvider implements NetworkProvider
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 nearbyStationUri(String stationId);
@ -185,16 +197,14 @@ public abstract class AbstractEfaProvider implements NetworkProvider
if (uri == null)
throw new IllegalArgumentException("at least one of stationId or lat/lon must be given");
InputStream is = null;
try
{
final CharSequence page = ParserUtils.scrape(uri);
if (P_NEARBY_MESSAGES.matcher(page).find())
return new NearbyStationsResult(uri, NearbyStationsResult.Status.SERVICE_DOWN);
is = ParserUtils.scrapeInputStream(uri);
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
final XmlPullParser pp = factory.newPullParser();
pp.setInput(new StringReader(page.toString()));
pp.setInput(is, DEFAULT_ENCODING);
XmlPullUtil.jumpToStartTag(pp, null, "itdOdvName");
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);
}
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+");
@ -533,13 +552,14 @@ public abstract class AbstractEfaProvider implements NetworkProvider
public QueryDeparturesResult queryDepartures(final String uri) throws IOException
{
InputStream is = null;
try
{
final CharSequence page = ParserUtils.scrape(uri);
is = ParserUtils.scrapeInputStream(uri);
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
final XmlPullParser pp = factory.newPullParser();
pp.setInput(new StringReader(page.toString()));
pp.setInput(is, DEFAULT_ENCODING);
XmlPullUtil.jumpToStartTag(pp, null, "itdOdvName");
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);
}
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
@ -654,25 +683,49 @@ public abstract class AbstractEfaProvider implements NetworkProvider
{
final String uri = connectionsQueryUri(from, via, to, date, dep, products, walkSpeed) + "&sessionID=0";
final CharSequence page = ParserUtils.scrape(uri);
return queryConnections(uri, page);
InputStream is = null;
try
{
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
{
final CharSequence page = ParserUtils.scrape(uri);
return queryConnections(uri, page);
InputStream is = null;
try
{
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
{
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
final XmlPullParser pp = factory.newPullParser();
pp.setInput(new StringReader(page.toString()));
pp.setInput(is, DEFAULT_ENCODING);
if (!XmlPullUtil.jumpToStartTag(pp, null, "itdRequest"))
throw new IllegalStateException("cannot find <itdRequest />");

View file

@ -27,7 +27,7 @@ public final class QueryConnectionsResult implements Serializable
{
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);

View file

@ -18,6 +18,7 @@
package de.schildbach.pte.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
@ -55,19 +56,19 @@ public final class ParserUtils
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);
}
public static CharSequence scrape(final String url, final boolean isPost, final String request, String encoding, final boolean cookieHandling)
throws IOException
public static final CharSequence scrape(final String url, final boolean isPost, final String request, String encoding,
final boolean cookieHandling) throws IOException
{
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,
int tries) throws IOException
public static final CharSequence scrape(final String url, final boolean isPost, final String request, String encoding,
final boolean cookieHandling, int tries) throws IOException
{
if (encoding == null)
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];
long count = 0;
@ -162,6 +163,21 @@ public final class ParserUtils
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));");
public static String resolveEntities(final CharSequence str)