I am looking for a way to let a regex.match()
timeout on Android.
Background: I have an app using an IntentService
to scrape HTML content and parse it with regex matchers. Sometimes the format of the HTML pages changes and then regex.match()
operation makes my app hang.
I have tried this solution and also the following code I adapted from Google source:
public class RegexUtils {
public RegexUtils() {
}
public void test() {
long millis = System.currentTimeMillis();
Matcher matcher = createMatcherWithTimeout("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "(x+x+)+y", 10000);
try {
Timber.d("RegexUtils: %s", (matcher.find() ? "Matches found" : "No matches found"));
} catch (RuntimeException e) {
Timber.w("RegexUtils: Operation timed out after " + (System.currentTimeMillis() - millis) + " milliseconds");
}
}
public static Matcher createMatcherWithTimeout(String stringToMatch, String regularExpression, long timeoutMillis) {
Pattern pattern = Pattern.compile(regularExpression);
return createMatcherWithTimeout(stringToMatch, pattern, timeoutMillis);
}
public static Matcher createMatcherWithTimeout(String stringToMatch, Pattern regularExpressionPattern, long timeoutMillis) {
if (timeoutMillis < 0) {
return regularExpressionPattern.matcher(stringToMatch);
}
TimeoutCharSequence charSequence = new TimeoutCharSequence(stringToMatch, timeoutMillis);
return regularExpressionPattern.matcher(charSequence);
}
private static class TimeoutCharSequence implements CharSequence {
long expireTime = 0;
CharSequence chars = null;
TimeoutCharSequence(CharSequence chars, long timeout) {
this.chars = chars;
expireTime = System.currentTimeMillis() + timeout;
}
@Override
public char charAt(int index) {
if (System.currentTimeMillis() > expireTime) {
throw new CharSequenceTimeoutException("TimeoutCharSequence was used after the expiration time.");
}
return chars.charAt(index);
}
@Override
public int length() {
return chars.length();
}
@Override
public CharSequence subSequence(int start, int end) {
return new TimeoutCharSequence(chars.subSequence(start, end), expireTime - System.currentTimeMillis());
}
@Override
public String toString() {
return chars.toString();
}
private static class CharSequenceTimeoutException extends RuntimeException {
public CharSequenceTimeoutException(String message) {
super(message);
}
}
}
}
But using either methods charAt()
is not called, therefore not throwing the timeout exception.
Any ideas on how to solve this are highly appreciated!! Thanks.