summaryrefslogtreecommitdiffstats
path: root/core/java/com/google/android/util
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
commitd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/com/google/android/util
parent076357b8567458d4b6dfdcf839ef751634cd2bfb (diff)
downloadframeworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip
frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz
frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/com/google/android/util')
-rw-r--r--core/java/com/google/android/util/AbstractMessageParser.java1496
-rw-r--r--core/java/com/google/android/util/GoogleWebContentHelper.java270
-rw-r--r--core/java/com/google/android/util/Procedure.java28
-rw-r--r--core/java/com/google/android/util/SimplePullParser.java391
-rw-r--r--core/java/com/google/android/util/SmileyParser.java83
-rw-r--r--core/java/com/google/android/util/SmileyResources.java74
6 files changed, 0 insertions, 2342 deletions
diff --git a/core/java/com/google/android/util/AbstractMessageParser.java b/core/java/com/google/android/util/AbstractMessageParser.java
deleted file mode 100644
index 25f6b33..0000000
--- a/core/java/com/google/android/util/AbstractMessageParser.java
+++ /dev/null
@@ -1,1496 +0,0 @@
-// Copyright 2007 The Android Open Source Project
-// All Rights Reserved.
-
-package com.google.android.util;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.Set;
-import java.util.List;
-
-/**
- *
- * Logic for parsing a text message typed by the user looking for smileys,
- * urls, acronyms,formatting (e.g., '*'s for bold), me commands
- * (e.g., "/me is asleep"), and punctuation.
- *
- * It constructs an array, which breaks the text up into its
- * constituent pieces, which we return to the client.
- *
- */
-public abstract class AbstractMessageParser {
-/**
- * Interface representing the set of resources needed by a message parser
- *
- * @author jessan (Jessan Hutchison-Quillian)
- */
- public static interface Resources {
-
- /** Get the known set of URL schemes. */
- public Set<String> getSchemes();
-
- /** Get the possible values for the last part of a domain name.
- * Values are expected to be reversed in the Trie.
- */
- public TrieNode getDomainSuffixes();
-
- /** Get the smileys accepted by the parser. */
- public TrieNode getSmileys();
-
- /** Get the acronyms accepted by the parser. */
- public TrieNode getAcronyms();
- }
-
- /**
- * Subclasses must define the schemes, domains, smileys and acronyms
- * that are necessary for parsing
- */
- protected abstract Resources getResources();
-
- /** Music note that indicates user is listening to a music track. */
- public static final String musicNote = "\u266B ";
-
- private String text;
- private int nextChar;
- private int nextClass;
- private ArrayList<Part> parts;
- private ArrayList<Token> tokens;
- private HashMap<Character,Format> formatStart;
- private boolean parseSmilies;
- private boolean parseAcronyms;
- private boolean parseFormatting;
- private boolean parseUrls;
- private boolean parseMeText;
- private boolean parseMusic;
-
- /**
- * Create a message parser to parse urls, formatting, acronyms, smileys,
- * /me text and music
- *
- * @param text the text to parse
- */
- public AbstractMessageParser(String text) {
- this(text, true, true, true, true, true, true);
- }
-
- /**
- * Create a message parser, specifying the kinds of text to parse
- *
- * @param text the text to parse
- *
- */
- public AbstractMessageParser(String text, boolean parseSmilies,
- boolean parseAcronyms, boolean parseFormatting, boolean parseUrls,
- boolean parseMusic, boolean parseMeText) {
- this.text = text;
- this.nextChar = 0;
- this.nextClass = 10;
- this.parts = new ArrayList<Part>();
- this.tokens = new ArrayList<Token>();
- this.formatStart = new HashMap<Character,Format>();
- this.parseSmilies = parseSmilies;
- this.parseAcronyms = parseAcronyms;
- this.parseFormatting = parseFormatting;
- this.parseUrls = parseUrls;
- this.parseMusic = parseMusic;
- this.parseMeText = parseMeText;
- }
-
- /** Returns the raw text being parsed. */
- public final String getRawText() { return text; }
-
- /** Return the number of parts. */
- public final int getPartCount() { return parts.size(); }
-
- /** Return the part at the given index. */
- public final Part getPart(int index) { return parts.get(index); }
-
- /** Return the list of parts from the parsed text */
- public final List<Part> getParts() { return parts; }
-
- /** Parses the text string into an internal representation. */
- public void parse() {
- // Look for music track (of which there would be only one and it'll be the
- // first token)
- if (parseMusicTrack()) {
- buildParts(null);
- return;
- }
-
- // Look for me commands.
- String meText = null;
- if (parseMeText && text.startsWith("/me") && (text.length() > 3) &&
- Character.isWhitespace(text.charAt(3))) {
- meText = text.substring(0, 4);
- text = text.substring(4);
- }
-
- // Break the text into tokens.
- boolean wasSmiley = false;
- while (nextChar < text.length()) {
- if (!isWordBreak(nextChar)) {
- if (!wasSmiley || !isSmileyBreak(nextChar)) {
- throw new AssertionError("last chunk did not end at word break");
- }
- }
-
- if (parseSmiley()) {
- wasSmiley = true;
- } else {
- wasSmiley = false;
-
- if (!parseAcronym() && !parseURL() && !parseFormatting()) {
- parseText();
- }
- }
- }
-
- // Trim the whitespace before and after media components.
- for (int i = 0; i < tokens.size(); ++i) {
- if (tokens.get(i).isMedia()) {
- if ((i > 0) && (tokens.get(i - 1) instanceof Html)) {
- ((Html)tokens.get(i - 1)).trimLeadingWhitespace();
- }
- if ((i + 1 < tokens.size()) && (tokens.get(i + 1) instanceof Html)) {
- ((Html)tokens.get(i + 1)).trimTrailingWhitespace();
- }
- }
- }
-
- // Remove any empty html tokens.
- for (int i = 0; i < tokens.size(); ++i) {
- if (tokens.get(i).isHtml() &&
- (tokens.get(i).toHtml(true).length() == 0)) {
- tokens.remove(i);
- --i; // visit this index again
- }
- }
-
- buildParts(meText);
- }
-
- /**
- * Get a the appropriate Token for a given URL
- *
- * @param text the anchor text
- * @param url the url
- *
- */
- public static Token tokenForUrl(String url, String text) {
- if(url == null) {
- return null;
- }
-
- //Look for video links
- Video video = Video.matchURL(url, text);
- if (video != null) {
- return video;
- }
-
- // Look for video links.
- YouTubeVideo ytVideo = YouTubeVideo.matchURL(url, text);
- if (ytVideo != null) {
- return ytVideo;
- }
-
- // Look for photo links.
- Photo photo = Photo.matchURL(url, text);
- if (photo != null) {
- return photo;
- }
-
- // Look for photo links.
- FlickrPhoto flickrPhoto = FlickrPhoto.matchURL(url, text);
- if (flickrPhoto != null) {
- return flickrPhoto;
- }
-
- //Not media, so must be a regular URL
- return new Link(url, text);
- }
-
- /**
- * Builds the parts list.
- *
- * @param meText any meText parsed from the message
- */
- private void buildParts(String meText) {
- for (int i = 0; i < tokens.size(); ++i) {
- Token token = tokens.get(i);
- if (token.isMedia() || (parts.size() == 0) || lastPart().isMedia()) {
- parts.add(new Part());
- }
- lastPart().add(token);
- }
-
- // The first part inherits the meText of the line.
- if (parts.size() > 0) {
- parts.get(0).setMeText(meText);
- }
- }
-
- /** Returns the last part in the list. */
- private Part lastPart() { return parts.get(parts.size() - 1); }
-
- /**
- * Looks for a music track (\u266B is first character, everything else is
- * track info).
- */
- private boolean parseMusicTrack() {
-
- if (parseMusic && text.startsWith(musicNote)) {
- addToken(new MusicTrack(text.substring(musicNote.length())));
- nextChar = text.length();
- return true;
- }
- return false;
- }
-
- /** Consumes all of the text in the next word . */
- private void parseText() {
- StringBuilder buf = new StringBuilder();
- int start = nextChar;
- do {
- char ch = text.charAt(nextChar++);
- switch (ch) {
- case '<': buf.append("&lt;"); break;
- case '>': buf.append("&gt;"); break;
- case '&': buf.append("&amp;"); break;
- case '"': buf.append("&quot;"); break;
- case '\'': buf.append("&apos;"); break;
- case '\n': buf.append("<br>"); break;
- default: buf.append(ch); break;
- }
- } while (!isWordBreak(nextChar));
-
- addToken(new Html(text.substring(start, nextChar), buf.toString()));
- }
-
- /**
- * Looks for smileys (e.g., ":)") in the text. The set of known smileys is
- * loaded from a file into a trie at server start.
- */
- private boolean parseSmiley() {
- if(!parseSmilies) {
- return false;
- }
- TrieNode match = longestMatch(getResources().getSmileys(), this, nextChar,
- true);
- if (match == null) {
- return false;
- } else {
- int previousCharClass = getCharClass(nextChar - 1);
- int nextCharClass = getCharClass(nextChar + match.getText().length());
- if ((previousCharClass == 2 || previousCharClass == 3)
- && (nextCharClass == 2 || nextCharClass == 3)) {
- return false;
- }
- addToken(new Smiley(match.getText()));
- nextChar += match.getText().length();
- return true;
- }
- }
-
- /** Looks for acronyms (e.g., "lol") in the text.
- */
- private boolean parseAcronym() {
- if(!parseAcronyms) {
- return false;
- }
- TrieNode match = longestMatch(getResources().getAcronyms(), this, nextChar);
- if (match == null) {
- return false;
- } else {
- addToken(new Acronym(match.getText(), match.getValue()));
- nextChar += match.getText().length();
- return true;
- }
- }
-
- /** Determines if this is an allowable domain character. */
- private boolean isDomainChar(char c) {
- return c == '-' || Character.isLetter(c) || Character.isDigit(c);
- }
-
- /** Determines if the given string is a valid domain. */
- private boolean isValidDomain(String domain) {
- // For hostnames, check that it ends with a known domain suffix
- if (matches(getResources().getDomainSuffixes(), reverse(domain))) {
- return true;
- }
- return false;
- }
-
- /**
- * Looks for a URL in two possible forms: either a proper URL with a known
- * scheme or a domain name optionally followed by a path, query, or query.
- */
- private boolean parseURL() {
- // Make sure this is a valid place to start a URL.
- if (!parseUrls || !isURLBreak(nextChar)) {
- return false;
- }
-
- int start = nextChar;
-
- // Search for the first block of letters.
- int index = start;
- while ((index < text.length()) && isDomainChar(text.charAt(index))) {
- index += 1;
- }
-
- String url = "";
- boolean done = false;
-
- if (index == text.length()) {
- return false;
- } else if (text.charAt(index) == ':') {
- // Make sure this is a known scheme.
- String scheme = text.substring(nextChar, index);
- if (!getResources().getSchemes().contains(scheme)) {
- return false;
- }
- } else if (text.charAt(index) == '.') {
- // Search for the end of the domain name.
- while (index < text.length()) {
- char ch = text.charAt(index);
- if ((ch != '.') && !isDomainChar(ch)) {
- break;
- } else {
- index += 1;
- }
- }
-
- // Make sure the domain name has a valid suffix. Since tries look for
- // prefix matches, we reverse all the strings to get suffix comparisons.
- String domain = text.substring(nextChar, index);
- if (!isValidDomain(domain)) {
- return false;
- }
-
- // Search for a port. We deal with this specially because a colon can
- // also be a punctuation character.
- if ((index + 1 < text.length()) && (text.charAt(index) == ':')) {
- char ch = text.charAt(index + 1);
- if (Character.isDigit(ch)) {
- index += 1;
- while ((index < text.length()) &&
- Character.isDigit(text.charAt(index))) {
- index += 1;
- }
- }
- }
-
- // The domain name should be followed by end of line, whitespace,
- // punctuation, or a colon, slash, question, or hash character. The
- // tricky part here is that some URL characters are also punctuation, so
- // we need to distinguish them. Since we looked for ports above, a colon
- // is always punctuation here. To distinguish '?' cases, we look at the
- // character that follows it.
- if (index == text.length()) {
- done = true;
- } else {
- char ch = text.charAt(index);
- if (ch == '?') {
- // If the next character is whitespace or punctuation (or missing),
- // then this question mark looks like punctuation.
- if (index + 1 == text.length()) {
- done = true;
- } else {
- char ch2 = text.charAt(index + 1);
- if (Character.isWhitespace(ch2) || isPunctuation(ch2)) {
- done = true;
- }
- }
- } else if (isPunctuation(ch)) {
- done = true;
- } else if (Character.isWhitespace(ch)) {
- done = true;
- } else if ((ch == '/') || (ch == '#')) {
- // In this case, the URL is not done. We will search for the end of
- // it below.
- } else {
- return false;
- }
- }
-
- // We will assume the user meant HTTP. (One weird case is where they
- // type a port of 443. That could mean HTTPS, but they might also want
- // HTTP. We'll let them specify if they don't want HTTP.)
- url = "http://";
- } else {
- return false;
- }
-
- // If the URL is not done, search for the end, which is just before the
- // next whitespace character.
- if (!done) {
- while ((index < text.length()) &&
- !Character.isWhitespace(text.charAt(index))) {
- index += 1;
- }
- }
-
- String urlText = text.substring(start, index);
- url += urlText;
-
- // Figure out the appropriate token type.
- addURLToken(url, urlText);
-
- nextChar = index;
- return true;
- }
-
- /**
- * Adds the appropriate token for the given URL. This might be a simple
- * link or it might be a recognized media type.
- */
- private void addURLToken(String url, String text) {
- addToken(tokenForUrl(url, text));
- }
-
- /**
- * Deal with formatting characters.
- *
- * Parsing is as follows:
- * - Treat all contiguous strings of formatting characters as one block.
- * (This method processes one block.)
- * - Only a single instance of a particular format character within a block
- * is used to determine whether to turn on/off that type of formatting;
- * other instances simply print the character itself.
- * - If the format is to be turned on, we use the _first_ instance; if it
- * is to be turned off, we use the _last_ instance (by appending the
- * format.)
- *
- * Example:
- * **string** turns into <b>*string*</b>
- */
- private boolean parseFormatting() {
- if(!parseFormatting) {
- return false;
- }
- int endChar = nextChar;
- while ((endChar < text.length()) && isFormatChar(text.charAt(endChar))) {
- endChar += 1;
- }
-
- if ((endChar == nextChar) || !isWordBreak(endChar)) {
- return false;
- }
-
- // Keeps track of whether we've seen a character (in map if we've seen it)
- // and whether we should append a closing format token (if value in
- // map is TRUE). Linked hashmap for consistent ordering.
- LinkedHashMap<Character, Boolean> seenCharacters =
- new LinkedHashMap<Character, Boolean>();
-
- for (int index = nextChar; index < endChar; ++index) {
- char ch = text.charAt(index);
- Character key = Character.valueOf(ch);
- if (seenCharacters.containsKey(key)) {
- // Already seen this character, just append an unmatched token, which
- // will print plaintext character
- addToken(new Format(ch, false));
- } else {
- Format start = formatStart.get(key);
- if (start != null) {
- // Match the start token, and ask an end token to be appended
- start.setMatched(true);
- formatStart.remove(key);
- seenCharacters.put(key, Boolean.TRUE);
- } else {
- // Append start token
- start = new Format(ch, true);
- formatStart.put(key, start);
- addToken(start);
- seenCharacters.put(key, Boolean.FALSE);
- }
- }
- }
-
- // Append any necessary end tokens
- for (Character key : seenCharacters.keySet()) {
- if (seenCharacters.get(key) == Boolean.TRUE) {
- Format end = new Format(key.charValue(), false);
- end.setMatched(true);
- addToken(end);
- }
- }
-
- nextChar = endChar;
- return true;
- }
-
- /** Determines whether the given index could be a possible word break. */
- private boolean isWordBreak(int index) {
- return getCharClass(index - 1) != getCharClass(index);
- }
-
- /** Determines whether the given index could be a possible smiley break. */
- private boolean isSmileyBreak(int index) {
- if (index > 0 && index < text.length()) {
- if (isSmileyBreak(text.charAt(index - 1), text.charAt(index))) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Verifies that the character before the given index is end of line,
- * whitespace, or punctuation.
- */
- private boolean isURLBreak(int index) {
- switch (getCharClass(index - 1)) {
- case 2:
- case 3:
- case 4:
- return false;
-
- case 0:
- case 1:
- default:
- return true;
- }
- }
-
- /** Returns the class for the character at the given index. */
- private int getCharClass(int index) {
- if ((index < 0) || (text.length() <= index)) {
- return 0;
- }
-
- char ch = text.charAt(index);
- if (Character.isWhitespace(ch)) {
- return 1;
- } else if (Character.isLetter(ch)) {
- return 2;
- } else if (Character.isDigit(ch)) {
- return 3;
- } else if (isPunctuation(ch)) {
- // For punctuation, we return a unique value every time so that they are
- // always different from any other character. Punctuation should always
- // be considered a possible word break.
- return ++nextClass;
- } else {
- return 4;
- }
- }
-
- /**
- * Returns true if <code>c1</code> could be the last character of
- * a smiley and <code>c2</code> could be the first character of
- * a different smiley, if {@link #isWordBreak} would not already
- * recognize that this is possible.
- */
- private static boolean isSmileyBreak(char c1, char c2) {
- switch (c1) {
- /*
- * These characters can end smileys, but don't normally end words.
- */
- case '$': case '&': case '*': case '+': case '-':
- case '/': case '<': case '=': case '>': case '@':
- case '[': case '\\': case ']': case '^': case '|':
- case '}': case '~':
- switch (c2) {
- /*
- * These characters can begin smileys, but don't normally
- * begin words.
- */
- case '#': case '$': case '%': case '*': case '/':
- case '<': case '=': case '>': case '@': case '[':
- case '\\': case '^': case '~':
- return true;
- }
- }
-
- return false;
- }
-
- /** Determines whether the given character is punctuation. */
- private static boolean isPunctuation(char ch) {
- switch (ch) {
- case '.': case ',': case '"': case ':': case ';':
- case '?': case '!': case '(': case ')':
- return true;
-
- default:
- return false;
- }
- }
-
- /**
- * Determines whether the given character is the beginning or end of a
- * section with special formatting.
- */
- private static boolean isFormatChar(char ch) {
- switch (ch) {
- case '*': case '_': case '^':
- return true;
-
- default:
- return false;
- }
- }
-
- /** Represents a unit of parsed output. */
- public static abstract class Token {
- public enum Type {
-
- HTML ("html"),
- FORMAT ("format"), // subtype of HTML
- LINK ("l"),
- SMILEY ("e"),
- ACRONYM ("a"),
- MUSIC ("m"),
- GOOGLE_VIDEO ("v"),
- YOUTUBE_VIDEO ("yt"),
- PHOTO ("p"),
- FLICKR ("f");
-
- //stringreps for HTML and FORMAT don't really matter
- //because they don't define getInfo(), which is where it is used
- //For the other types, code depends on their stringreps
- private String stringRep;
-
- Type(String stringRep) {
- this.stringRep = stringRep;
- }
-
- /** {@inheritDoc} */
- public String toString() {
- return this.stringRep;
- }
- }
-
- protected Type type;
- protected String text;
-
- protected Token(Type type, String text) {
- this.type = type;
- this.text = text;
- }
-
- /** Returns the type of the token. */
- public Type getType() { return type; }
-
- /**
- * Get the relevant information about a token
- *
- * @return a list of strings representing the token, not null
- * The first item is always a string representation of the type
- */
- public List<String> getInfo() {
- List<String> info = new ArrayList<String>();
- info.add(getType().toString());
- return info;
- }
-
- /** Returns the raw text of the token. */
- public String getRawText() { return text; }
-
- public boolean isMedia() { return false; }
- public abstract boolean isHtml();
- public boolean isArray() { return !isHtml(); }
-
- public String toHtml(boolean caps) { throw new AssertionError("not html"); }
-
- // The token can change the caps of the text after that point.
- public boolean controlCaps() { return false; }
- public boolean setCaps() { return false; }
- }
-
- /** Represents a simple string of html text. */
- public static class Html extends Token {
- private String html;
-
- public Html(String text, String html) {
- super(Type.HTML, text);
- this.html = html;
- }
-
- public boolean isHtml() { return true; }
- public String toHtml(boolean caps) {
- return caps ? html.toUpperCase() : html;
- }
- /**
- * Not supported. Info should not be needed for this type
- */
- public List<String> getInfo() {
- throw new UnsupportedOperationException();
- }
-
- public void trimLeadingWhitespace() {
- text = trimLeadingWhitespace(text);
- html = trimLeadingWhitespace(html);
- }
-
- public void trimTrailingWhitespace() {
- text = trimTrailingWhitespace(text);
- html = trimTrailingWhitespace(html);
- }
-
- private static String trimLeadingWhitespace(String text) {
- int index = 0;
- while ((index < text.length()) &&
- Character.isWhitespace(text.charAt(index))) {
- ++index;
- }
- return text.substring(index);
- }
-
- public static String trimTrailingWhitespace(String text) {
- int index = text.length();
- while ((index > 0) && Character.isWhitespace(text.charAt(index - 1))) {
- --index;
- }
- return text.substring(0, index);
- }
- }
-
- /** Represents a music track token at the beginning. */
- public static class MusicTrack extends Token {
- private String track;
-
- public MusicTrack(String track) {
- super(Type.MUSIC, track);
- this.track = track;
- }
-
- public String getTrack() { return track; }
-
- public boolean isHtml() { return false; }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getTrack());
- return info;
- }
- }
-
- /** Represents a link that was found in the input. */
- public static class Link extends Token {
- private String url;
-
- public Link(String url, String text) {
- super(Type.LINK, text);
- this.url = url;
- }
-
- public String getURL() { return url; }
-
- public boolean isHtml() { return false; }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getURL());
- info.add(getRawText());
- return info;
- }
- }
-
- /** Represents a link to a Google Video. */
- public static class Video extends Token {
- /** Pattern for a video URL. */
- private static final Pattern URL_PATTERN = Pattern.compile(
- "(?i)http://video\\.google\\.[a-z0-9]+(?:\\.[a-z0-9]+)?/videoplay\\?"
- + ".*?\\bdocid=(-?\\d+).*");
-
- private String docid;
-
- public Video(String docid, String text) {
- super(Type.GOOGLE_VIDEO, text);
- this.docid = docid;
- }
-
- public String getDocID() { return docid; }
-
- public boolean isHtml() { return false; }
- public boolean isMedia() { return true; }
-
- /** Returns a Video object if the given url is to a video. */
- public static Video matchURL(String url, String text) {
- Matcher m = URL_PATTERN.matcher(url);
- if (m.matches()) {
- return new Video(m.group(1), text);
- } else {
- return null;
- }
- }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getRssUrl(docid));
- info.add(getURL(docid));
- return info;
- }
-
- /** Returns the URL for the RSS description of the given video. */
- public static String getRssUrl(String docid) {
- return "http://video.google.com/videofeed"
- + "?type=docid&output=rss&sourceid=gtalk&docid=" + docid;
- }
-
- /** (For testing purposes:) Returns a video URL with the given parts. */
- public static String getURL(String docid) {
- return getURL(docid, null);
- }
-
- /** (For testing purposes:) Returns a video URL with the given parts. */
- public static String getURL(String docid, String extraParams) {
- if (extraParams == null) {
- extraParams = "";
- } else if (extraParams.length() > 0) {
- extraParams += "&";
- }
- return "http://video.google.com/videoplay?" + extraParams
- + "docid=" + docid;
- }
- }
-
- /** Represents a link to a YouTube video. */
- public static class YouTubeVideo extends Token {
- /** Pattern for a video URL. */
- private static final Pattern URL_PATTERN = Pattern.compile(
- "(?i)http://(?:[a-z0-9]+\\.)?youtube\\.[a-z0-9]+(?:\\.[a-z0-9]+)?/watch\\?"
- + ".*\\bv=([-_a-zA-Z0-9=]+).*");
-
- private String docid;
-
- public YouTubeVideo(String docid, String text) {
- super(Type.YOUTUBE_VIDEO, text);
- this.docid = docid;
- }
-
- public String getDocID() { return docid; }
-
- public boolean isHtml() { return false; }
- public boolean isMedia() { return true; }
-
- /** Returns a Video object if the given url is to a video. */
- public static YouTubeVideo matchURL(String url, String text) {
- Matcher m = URL_PATTERN.matcher(url);
- if (m.matches()) {
- return new YouTubeVideo(m.group(1), text);
- } else {
- return null;
- }
- }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getRssUrl(docid));
- info.add(getURL(docid));
- return info;
- }
-
- /** Returns the URL for the RSS description of the given video. */
- public static String getRssUrl(String docid) {
- return "http://youtube.com/watch?v=" + docid;
- }
-
- /** (For testing purposes:) Returns a video URL with the given parts. */
- public static String getURL(String docid) {
- return getURL(docid, null);
- }
-
- /** (For testing purposes:) Returns a video URL with the given parts. */
- public static String getURL(String docid, String extraParams) {
- if (extraParams == null) {
- extraParams = "";
- } else if (extraParams.length() > 0) {
- extraParams += "&";
- }
- return "http://youtube.com/watch?" + extraParams + "v=" + docid;
- }
-
- /** (For testing purposes:) Returns a video URL with the given parts.
- * @param http If true, includes http://
- * @param prefix If non-null/non-blank, adds to URL before youtube.com.
- * (e.g., prefix="br." --> "br.youtube.com")
- */
- public static String getPrefixedURL(boolean http, String prefix,
- String docid, String extraParams) {
- String protocol = "";
-
- if (http) {
- protocol = "http://";
- }
-
- if (prefix == null) {
- prefix = "";
- }
-
- if (extraParams == null) {
- extraParams = "";
- } else if (extraParams.length() > 0) {
- extraParams += "&";
- }
-
- return protocol + prefix + "youtube.com/watch?" + extraParams + "v=" +
- docid;
- }
- }
-
- /** Represents a link to a Picasa photo or album. */
- public static class Photo extends Token {
- /** Pattern for an album or photo URL. */
- // TODO (katyarogers) searchbrowse includes search lists and tags,
- // it follows a different pattern than albums - would be nice to add later
- private static final Pattern URL_PATTERN = Pattern.compile(
- "http://picasaweb.google.com/([^/?#&]+)/+((?!searchbrowse)[^/?#&]+)(?:/|/photo)?(?:\\?[^#]*)?(?:#(.*))?");
-
- private String user;
- private String album;
- private String photo; // null for albums
-
- public Photo(String user, String album, String photo, String text) {
- super(Type.PHOTO, text);
- this.user = user;
- this.album = album;
- this.photo = photo;
- }
-
- public String getUser() { return user; }
- public String getAlbum() { return album; }
- public String getPhoto() { return photo; }
-
- public boolean isHtml() { return false; }
- public boolean isMedia() { return true; }
-
- /** Returns a Photo object if the given url is to a photo or album. */
- public static Photo matchURL(String url, String text) {
- Matcher m = URL_PATTERN.matcher(url);
- if (m.matches()) {
- return new Photo(m.group(1), m.group(2), m.group(3), text);
- } else {
- return null;
- }
- }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getRssUrl(getUser()));
- info.add(getAlbumURL(getUser(), getAlbum()));
- if (getPhoto() != null) {
- info.add(getPhotoURL(getUser(), getAlbum(), getPhoto()));
- } else {
- info.add((String)null);
- }
- return info;
- }
-
- /** Returns the URL for the RSS description of the user's albums. */
- public static String getRssUrl(String user) {
- return "http://picasaweb.google.com/data/feed/api/user/" + user +
- "?category=album&alt=rss";
- }
-
- /** Returns the URL for an album. */
- public static String getAlbumURL(String user, String album) {
- return "http://picasaweb.google.com/" + user + "/" + album;
- }
-
- /** Returns the URL for a particular photo. */
- public static String getPhotoURL(String user, String album, String photo) {
- return "http://picasaweb.google.com/" + user + "/" + album + "/photo#"
- + photo;
- }
- }
-
- /** Represents a link to a Flickr photo or album. */
- public static class FlickrPhoto extends Token {
- /** Pattern for a user album or photo URL. */
- private static final Pattern URL_PATTERN = Pattern.compile(
- "http://(?:www.)?flickr.com/photos/([^/?#&]+)/?([^/?#&]+)?/?.*");
- private static final Pattern GROUPING_PATTERN = Pattern.compile(
- "http://(?:www.)?flickr.com/photos/([^/?#&]+)/(tags|sets)/" +
- "([^/?#&]+)/?");
-
- private static final String SETS = "sets";
- private static final String TAGS = "tags";
-
- private String user;
- private String photo; // null for user album
- private String grouping; // either "tags" or "sets"
- private String groupingId; // sets or tags identifier
-
- public FlickrPhoto(String user, String photo, String grouping,
- String groupingId, String text) {
- super(Type.FLICKR, text);
-
- /* System wide tags look like the URL to a Flickr user. */
- if (!TAGS.equals(user)) {
- this.user = user;
- // Don't consider slide show URL a photo
- this.photo = (!"show".equals(photo) ? photo : null);
- this.grouping = grouping;
- this.groupingId = groupingId;
- } else {
- this.user = null;
- this.photo = null;
- this.grouping = TAGS;
- this.groupingId = photo;
- }
- }
-
- public String getUser() { return user; }
- public String getPhoto() { return photo; }
- public String getGrouping() { return grouping; }
- public String getGroupingId() { return groupingId; }
-
- public boolean isHtml() { return false; }
- public boolean isMedia() { return true; }
-
- /**
- * Returns a FlickrPhoto object if the given url is to a photo or Flickr
- * user.
- */
- public static FlickrPhoto matchURL(String url, String text) {
- Matcher m = GROUPING_PATTERN.matcher(url);
- if (m.matches()) {
- return new FlickrPhoto(m.group(1), null, m.group(2), m.group(3), text);
- }
-
- m = URL_PATTERN.matcher(url);
- if (m.matches()) {
- return new FlickrPhoto(m.group(1), m.group(2), null, null, text);
- } else {
- return null;
- }
- }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getUrl());
- info.add(getUser() != null ? getUser() : "");
- info.add(getPhoto() != null ? getPhoto() : "");
- info.add(getGrouping() != null ? getGrouping() : "");
- info.add(getGroupingId() != null ? getGroupingId() : "");
- return info;
- }
-
- public String getUrl() {
- if (SETS.equals(grouping)) {
- return getUserSetsURL(user, groupingId);
- } else if (TAGS.equals(grouping)) {
- if (user != null) {
- return getUserTagsURL(user, groupingId);
- } else {
- return getTagsURL(groupingId);
- }
- } else if (photo != null) {
- return getPhotoURL(user, photo);
- } else {
- return getUserURL(user);
- }
- }
-
- /** Returns the URL for the RSS description. */
- public static String getRssUrl(String user) {
- return null;
- }
-
- /** Returns the URL for a particular tag. */
- public static String getTagsURL(String tag) {
- return "http://flickr.com/photos/tags/" + tag;
- }
-
- /** Returns the URL to the user's Flickr homepage. */
- public static String getUserURL(String user) {
- return "http://flickr.com/photos/" + user;
- }
-
- /** Returns the URL for a particular photo. */
- public static String getPhotoURL(String user, String photo) {
- return "http://flickr.com/photos/" + user + "/" + photo;
- }
-
- /** Returns the URL for a user tag photo set. */
- public static String getUserTagsURL(String user, String tagId) {
- return "http://flickr.com/photos/" + user + "/tags/" + tagId;
- }
-
- /** Returns the URL for user set. */
- public static String getUserSetsURL(String user, String setId) {
- return "http://flickr.com/photos/" + user + "/sets/" + setId;
- }
- }
-
- /** Represents a smiley that was found in the input. */
- public static class Smiley extends Token {
- // TODO: Pass the SWF URL down to the client.
-
- public Smiley(String text) {
- super(Type.SMILEY, text);
- }
-
- public boolean isHtml() { return false; }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getRawText());
- return info;
- }
- }
-
- /** Represents an acronym that was found in the input. */
- public static class Acronym extends Token {
- private String value;
- // TODO: SWF
-
- public Acronym(String text, String value) {
- super(Type.ACRONYM, text);
- this.value = value;
- }
-
- public String getValue() { return value; }
-
- public boolean isHtml() { return false; }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getRawText());
- info.add(getValue());
- return info;
- }
- }
-
- /** Represents a character that changes formatting. */
- public static class Format extends Token {
- private char ch;
- private boolean start;
- private boolean matched;
-
- public Format(char ch, boolean start) {
- super(Type.FORMAT, String.valueOf(ch));
- this.ch = ch;
- this.start = start;
- }
-
- public void setMatched(boolean matched) { this.matched = matched; }
-
- public boolean isHtml() { return true; }
-
- public String toHtml(boolean caps) {
- // This character only implies special formatting if it was matched.
- // Otherwise, it was just a plain old character.
- if (matched) {
- return start ? getFormatStart(ch) : getFormatEnd(ch);
- } else {
- // We have to make sure we escape HTML characters as usual.
- return (ch == '"') ? "&quot;" : String.valueOf(ch);
- }
- }
-
- /**
- * Not supported. Info should not be needed for this type
- */
- public List<String> getInfo() {
- throw new UnsupportedOperationException();
- }
-
- public boolean controlCaps() { return (ch == '^'); }
- public boolean setCaps() { return start; }
-
- private String getFormatStart(char ch) {
- switch (ch) {
- case '*': return "<b>";
- case '_': return "<i>";
- case '^': return "<b><font color=\"#005FFF\">"; // TODO: all caps
- case '"': return "<font color=\"#999999\">\u201c";
- default: throw new AssertionError("unknown format '" + ch + "'");
- }
- }
-
- private String getFormatEnd(char ch) {
- switch (ch) {
- case '*': return "</b>";
- case '_': return "</i>";
- case '^': return "</font></b>"; // TODO: all caps
- case '"': return "\u201d</font>";
- default: throw new AssertionError("unknown format '" + ch + "'");
- }
- }
- }
-
- /** Adds the given token to the parsed output. */
- private void addToken(Token token) {
- tokens.add(token);
- }
-
- /** Converts the entire message into a single HTML display string. */
- public String toHtml() {
- StringBuilder html = new StringBuilder();
-
- for (Part part : parts) {
- boolean caps = false;
-
- html.append("<p>");
- for (Token token : part.getTokens()) {
- if (token.isHtml()) {
- html.append(token.toHtml(caps));
- } else {
- switch (token.getType()) {
- case LINK:
- html.append("<a href=\"");
- html.append(((Link)token).getURL());
- html.append("\">");
- html.append(token.getRawText());
- html.append("</a>");
- break;
-
- case SMILEY:
- // TODO: link to an appropriate image
- html.append(token.getRawText());
- break;
-
- case ACRONYM:
- html.append(token.getRawText());
- break;
-
- case MUSIC:
- // TODO: include a music glyph
- html.append(((MusicTrack)token).getTrack());
- break;
-
- case GOOGLE_VIDEO:
- // TODO: include a Google Video icon
- html.append("<a href=\"");
- html.append(((Video)token).getURL(((Video)token).getDocID()));
- html.append("\">");
- html.append(token.getRawText());
- html.append("</a>");
- break;
-
- case YOUTUBE_VIDEO:
- // TODO: include a YouTube icon
- html.append("<a href=\"");
- html.append(((YouTubeVideo)token).getURL(
- ((YouTubeVideo)token).getDocID()));
- html.append("\">");
- html.append(token.getRawText());
- html.append("</a>");
- break;
-
- case PHOTO: {
- // TODO: include a Picasa Web icon
- html.append("<a href=\"");
- html.append(Photo.getAlbumURL(
- ((Photo)token).getUser(), ((Photo)token).getAlbum()));
- html.append("\">");
- html.append(token.getRawText());
- html.append("</a>");
- break;
- }
-
- case FLICKR:
- // TODO: include a Flickr icon
- Photo p = (Photo) token;
- html.append("<a href=\"");
- html.append(((FlickrPhoto)token).getUrl());
- html.append("\">");
- html.append(token.getRawText());
- html.append("</a>");
- break;
-
- default:
- throw new AssertionError("unknown token type: " + token.getType());
- }
- }
-
- if (token.controlCaps()) {
- caps = token.setCaps();
- }
- }
- html.append("</p>\n");
- }
-
- return html.toString();
- }
-
- /** Returns the reverse of the given string. */
- protected static String reverse(String str) {
- StringBuilder buf = new StringBuilder();
- for (int i = str.length() - 1; i >= 0; --i) {
- buf.append(str.charAt(i));
- }
- return buf.toString();
- }
-
- public static class TrieNode {
- private final HashMap<Character,TrieNode> children =
- new HashMap<Character,TrieNode>();
- private String text;
- private String value;
-
- public TrieNode() { this(""); }
- public TrieNode(String text) {
- this.text = text;
- }
-
- public final boolean exists() { return value != null; }
- public final String getText() { return text; }
- public final String getValue() { return value; }
- public void setValue(String value) { this.value = value; }
-
- public TrieNode getChild(char ch) {
- return children.get(Character.valueOf(ch));
- }
-
- public TrieNode getOrCreateChild(char ch) {
- Character key = Character.valueOf(ch);
- TrieNode node = children.get(key);
- if (node == null) {
- node = new TrieNode(text + String.valueOf(ch));
- children.put(key, node);
- }
- return node;
- }
-
- /** Adds the given string into the trie. */
- public static void addToTrie(TrieNode root, String str, String value) {
- int index = 0;
- while (index < str.length()) {
- root = root.getOrCreateChild(str.charAt(index++));
- }
- root.setValue(value);
- }
- }
-
-
-
- /** Determines whether the given string is in the given trie. */
- private static boolean matches(TrieNode root, String str) {
- int index = 0;
- while (index < str.length()) {
- root = root.getChild(str.charAt(index++));
- if (root == null) {
- break;
- } else if (root.exists()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the longest substring of the given string, starting at the given
- * index, that exists in the trie.
- */
- private static TrieNode longestMatch(
- TrieNode root, AbstractMessageParser p, int start) {
- return longestMatch(root, p, start, false);
- }
-
- /**
- * Returns the longest substring of the given string, starting at the given
- * index, that exists in the trie, with a special tokenizing case for
- * smileys if specified.
- */
- private static TrieNode longestMatch(
- TrieNode root, AbstractMessageParser p, int start, boolean smiley) {
- int index = start;
- TrieNode bestMatch = null;
- while (index < p.getRawText().length()) {
- root = root.getChild(p.getRawText().charAt(index++));
- if (root == null) {
- break;
- } else if (root.exists()) {
- if (p.isWordBreak(index)) {
- bestMatch = root;
- } else if (smiley && p.isSmileyBreak(index)) {
- bestMatch = root;
- }
- }
- }
- return bestMatch;
- }
-
-
- /** Represents set of tokens that are delivered as a single message. */
- public static class Part {
- private String meText;
- private ArrayList<Token> tokens;
-
- public Part() {
- this.tokens = new ArrayList<Token>();
- }
-
- public String getType(boolean isSend) {
- return (isSend ? "s" : "r") + getPartType();
- }
-
- private String getPartType() {
- if (isMedia()) {
- return "d";
- } else if (meText != null) {
- return "m";
- } else {
- return "";
- }
- }
-
- public boolean isMedia() {
- return (tokens.size() == 1) && tokens.get(0).isMedia();
- }
- /**
- * Convenience method for getting the Token of a Part that represents
- * a media Token. Parts of this kind will always only have a single Token
- *
- * @return if this.isMedia(),
- * returns the Token representing the media contained in this Part,
- * otherwise returns null;
- */
- public Token getMediaToken() {
- if(isMedia()) {
- return tokens.get(0);
- }
- return null;
- }
-
- /** Adds the given token to this part. */
- public void add(Token token) {
- if (isMedia()) {
- throw new AssertionError("media ");
- }
- tokens.add(token);
- }
-
- public void setMeText(String meText) {
- this.meText = meText;
- }
-
- /** Returns the original text of this part. */
- public String getRawText() {
- StringBuilder buf = new StringBuilder();
- if (meText != null) {
- buf.append(meText);
- }
- for (int i = 0; i < tokens.size(); ++i) {
- buf.append(tokens.get(i).getRawText());
- }
- return buf.toString();
- }
-
- /** Returns the tokens in this part. */
- public ArrayList<Token> getTokens() { return tokens; }
-
- /** Adds the tokens into the given builder as an array. */
-// public void toArray(JSArrayBuilder array) {
-// if (isMedia()) {
-// // For media, we send its array (i.e., we don't wrap this in another
-// // array as we do for non-media parts).
-// tokens.get(0).toArray(array);
-// } else {
-// array.beginArray();
-// addToArray(array);
-// array.endArray();
-// }
-// }
- }
-}
diff --git a/core/java/com/google/android/util/GoogleWebContentHelper.java b/core/java/com/google/android/util/GoogleWebContentHelper.java
deleted file mode 100644
index 2911420..0000000
--- a/core/java/com/google/android/util/GoogleWebContentHelper.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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 com.google.android.util;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.net.http.SslError;
-import android.os.Message;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.HttpAuthHandler;
-import android.webkit.SslErrorHandler;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.TextView;
-
-import java.util.Locale;
-
-/**
- * Helper to display Google web content, and fallback on a static message if the
- * web content is unreachable. For example, this can be used to display
- * "Legal terms".
- * <p>
- * The typical usage pattern is to have two Gservices settings defined:
- * <ul>
- * <li>A secure URL that will be displayed on the device. This should be HTTPS
- * so hotspots won't intercept it giving us a false positive that the page
- * loaded successfully.
- * <li>A pretty human-readable URL that will be displayed to the user in case we
- * cannot reach the above URL.
- * </ul>
- * <p>
- * The typical call sequence is {@link #setUrlsFromGservices(String, String)},
- * {@link #setUnsuccessfulMessage(String)}, and {@link #loadUrl()}. At some
- * point, you'll want to display the layout via {@link #getLayout()}.
- */
-public class GoogleWebContentHelper {
-
- private Context mContext;
-
- private String mSecureUrl;
- private String mPrettyUrl;
-
- private String mUnsuccessfulMessage;
-
- private ViewGroup mLayout;
- private WebView mWebView;
- private View mProgressBar;
- private TextView mTextView;
-
- private boolean mReceivedResponse;
-
- public GoogleWebContentHelper(Context context) {
- mContext = context;
- }
-
- /**
- * Fetches the URLs from Gservices.
- *
- * @param secureSetting The setting key whose value contains the HTTPS URL.
- * @param prettySetting The setting key whose value contains the pretty URL.
- * @return This {@link GoogleWebContentHelper} so methods can be chained.
- */
- public GoogleWebContentHelper setUrlsFromGservices(String secureSetting, String prettySetting) {
- ContentResolver contentResolver = mContext.getContentResolver();
- mSecureUrl = fillUrl(Settings.Gservices.getString(contentResolver, secureSetting),
- mContext);
- mPrettyUrl = fillUrl(Settings.Gservices.getString(contentResolver, prettySetting),
- mContext);
- return this;
- }
-
- /**
- * Fetch directly from provided urls.
- *
- * @param secureUrl The HTTPS URL.
- * @param prettyUrl The pretty URL.
- * @return This {@link GoogleWebContentHelper} so methods can be chained.
- */
- public GoogleWebContentHelper setUrls(String secureUrl, String prettyUrl) {
- mSecureUrl = fillUrl(secureUrl, mContext);
- mPrettyUrl = fillUrl(prettyUrl, mContext);
- return this;
- }
-
-
- /**
- * Sets the message that will be shown if we are unable to load the page.
- * <p>
- * This should be called after {@link #setUrlsFromGservices(String, String)}
- * .
- *
- * @param message The message to load. The first argument, according to
- * {@link java.util.Formatter}, will be substituted with the pretty
- * URL.
- * @return This {@link GoogleWebContentHelper} so methods can be chained.
- */
- public GoogleWebContentHelper setUnsuccessfulMessage(String message) {
- Locale locale = mContext.getResources().getConfiguration().locale;
- mUnsuccessfulMessage = String.format(locale, message, mPrettyUrl);
- return this;
- }
-
- /**
- * Begins loading the secure URL.
- *
- * @return This {@link GoogleWebContentHelper} so methods can be chained.
- */
- public GoogleWebContentHelper loadUrl() {
- ensureViews();
- mWebView.loadUrl(mSecureUrl);
- return this;
- }
-
- /**
- * Helper to handle the back key. Returns true if the back key was handled,
- * otherwise returns false.
- * @param event the key event sent to {@link Activity#dispatchKeyEvent()}
- */
- public boolean handleKey(KeyEvent event) {
- if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
- && event.getAction() == KeyEvent.ACTION_DOWN) {
- if (mWebView.canGoBack()) {
- mWebView.goBack();
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the layout containing the web view, progress bar, and text view.
- * This class takes care of setting each one's visibility based on current
- * state.
- *
- * @return The layout you should display.
- */
- public ViewGroup getLayout() {
- ensureViews();
- return mLayout;
- }
-
- private synchronized void ensureViews() {
- if (mLayout == null) {
- initializeViews();
- }
- }
-
- /**
- * Fills the URL with the locale.
- *
- * @param url The URL in Formatter style for the extra info to be filled in.
- * @return The filled URL.
- */
- private static String fillUrl(String url, Context context) {
-
- if (TextUtils.isEmpty(url)) {
- return "";
- }
-
- /* We add another layer of indirection here to allow mcc's to fill
- * in Locales for TOS. TODO - REMOVE when needed locales supported
- * natively (when not shipping devices to country X without support
- * for their locale).
- */
- String localeReplacement = context.
- getString(com.android.internal.R.string.locale_replacement);
- if (localeReplacement != null && localeReplacement.length() != 0) {
- url = String.format(url, localeReplacement);
- }
-
- Locale locale = Locale.getDefault();
- String tmp = locale.getLanguage() + "_" + locale.getCountry().toLowerCase();
- return String.format(url, tmp);
- }
-
- private void initializeViews() {
-
- LayoutInflater inflater =
- (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- mLayout = (ViewGroup) inflater.inflate(
- com.android.internal.R.layout.google_web_content_helper_layout, null);
-
- mWebView = (WebView) mLayout.findViewById(com.android.internal.R.id.web);
- mWebView.setWebViewClient(new MyWebViewClient());
- WebSettings settings = mWebView.getSettings();
- settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
-
- mProgressBar = mLayout.findViewById(com.android.internal.R.id.progressContainer);
- TextView message = (TextView) mProgressBar.findViewById(com.android.internal.R.id.message);
- message.setText(com.android.internal.R.string.googlewebcontenthelper_loading);
-
- mTextView = (TextView) mLayout.findViewById(com.android.internal.R.id.text);
- mTextView.setText(mUnsuccessfulMessage);
- }
-
- private synchronized void handleWebViewCompletion(boolean success) {
-
- if (mReceivedResponse) {
- return;
- } else {
- mReceivedResponse = true;
- }
-
- // In both cases, remove the progress bar
- ((ViewGroup) mProgressBar.getParent()).removeView(mProgressBar);
-
- // Remove the view that isn't relevant
- View goneView = success ? mTextView : mWebView;
- ((ViewGroup) goneView.getParent()).removeView(goneView);
-
- // Show the next view, which depends on success
- View visibleView = success ? mWebView : mTextView;
- visibleView.setVisibility(View.VISIBLE);
- }
-
- private class MyWebViewClient extends WebViewClient {
-
- @Override
- public void onPageFinished(WebView view, String url) {
- handleWebViewCompletion(true);
- }
-
- @Override
- public void onReceivedError(WebView view, int errorCode,
- String description, String failingUrl) {
- handleWebViewCompletion(false);
- }
-
- @Override
- public void onReceivedHttpAuthRequest(WebView view,
- HttpAuthHandler handler, String host, String realm) {
- handleWebViewCompletion(false);
- }
-
- @Override
- public void onReceivedSslError(WebView view, SslErrorHandler handler,
- SslError error) {
- handleWebViewCompletion(false);
- }
-
- @Override
- public void onTooManyRedirects(WebView view, Message cancelMsg,
- Message continueMsg) {
- handleWebViewCompletion(false);
- }
-
- }
-
-}
diff --git a/core/java/com/google/android/util/Procedure.java b/core/java/com/google/android/util/Procedure.java
deleted file mode 100644
index 5ede2f0..0000000
--- a/core/java/com/google/android/util/Procedure.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-** Copyright 2007, The Android Open Source Project
-**
-** 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 com.google.android.util;
-
-/**
- * A procedure.
- */
-public interface Procedure<T> {
-
- /**
- * Applies this procedure to the given parameter.
- */
- void apply(T t);
-}
diff --git a/core/java/com/google/android/util/SimplePullParser.java b/core/java/com/google/android/util/SimplePullParser.java
deleted file mode 100644
index 031790b..0000000
--- a/core/java/com/google/android/util/SimplePullParser.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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 com.google.android.util;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringReader;
-import java.io.Reader;
-import java.io.Closeable;
-
-import android.util.Xml;
-import android.util.Log;
-
-/**
- * This is an abstraction of a pull parser that provides several benefits:<ul>
- * <li>it is easier to use robustly because it makes it trivial to handle unexpected tags (which
- * might have children)</li>
- * <li>it makes the handling of text (cdata) blocks more convenient</li>
- * <li>it provides convenient methods for getting a mandatory attribute (and throwing an exception
- * if it is missing) or an optional attribute (and using a default value if it is missing)
- * </ul>
- */
-public class SimplePullParser {
- public static final String TEXT_TAG = "![CDATA[";
-
- private String mLogTag = null;
- private final XmlPullParser mParser;
- private Closeable source;
- private String mCurrentStartTag;
-
- /**
- * Constructs a new SimplePullParser to parse the stream
- * @param stream stream to parse
- * @param encoding the encoding to use
- */
- public SimplePullParser(InputStream stream, String encoding)
- throws ParseException, IOException {
- try {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(stream, encoding);
- moveToStartDocument(parser);
- mParser = parser;
- mCurrentStartTag = null;
- source = stream;
- } catch (XmlPullParserException e) {
- throw new ParseException(e);
- }
- }
-
- /**
- * Constructs a new SimplePullParser to parse the xml
- * @param parser the underlying parser to use
- */
- public SimplePullParser(XmlPullParser parser) {
- mParser = parser;
- mCurrentStartTag = null;
- source = null;
- }
-
- /**
- * Constructs a new SimplePullParser to parse the xml
- * @param xml the xml to parse
- */
- public SimplePullParser(String xml) throws IOException, ParseException {
- this(new StringReader(xml));
- }
-
- /**
- * Constructs a new SimplePullParser to parse the xml
- * @param reader a reader containing the xml
- */
- public SimplePullParser(Reader reader) throws IOException, ParseException {
- try {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(reader);
- moveToStartDocument(parser);
- mParser = parser;
- mCurrentStartTag = null;
- source = reader;
- } catch (XmlPullParserException e) {
- throw new ParseException(e);
- }
- }
-
- private static void moveToStartDocument(XmlPullParser parser)
- throws XmlPullParserException, IOException {
- int eventType;
- eventType = parser.getEventType();
- if (eventType != XmlPullParser.START_DOCUMENT) {
- throw new XmlPullParserException("Not at start of response");
- }
- }
-
- /**
- * Enables logging to the provided log tag. A basic representation of the xml will be logged as
- * the xml is parsed. No logging is done unless this is called.
- *
- * @param logTag the log tag to use when logging
- */
- public void setLogTag(String logTag) {
- mLogTag = logTag;
- }
-
- /**
- * Returns the tag of the next element whose depth is parentDepth plus one
- * or null if there are no more such elements before the next start tag. When this returns,
- * getDepth() and all methods relating to attributes will refer to the element whose tag is
- * returned.
- *
- * @param parentDepth the depth of the parrent of the item to be returned
- * @param textBuilder if null then text blocks will be ignored. If
- * non-null then text blocks will be added to the builder and TEXT_TAG
- * will be returned when one is found
- * @return the next of the next child element's tag, TEXT_TAG if a text block is found, or null
- * if there are no more child elements or DATA blocks
- * @throws IOException propogated from the underlying parser
- * @throws ParseException if there was an error parsing the xml.
- */
- public String nextTagOrText(int parentDepth, StringBuilder textBuilder)
- throws IOException, ParseException {
- while (true) {
- int eventType = 0;
- try {
- eventType = mParser.next();
- } catch (XmlPullParserException e) {
- throw new ParseException(e);
- }
- int depth = mParser.getDepth();
- mCurrentStartTag = null;
-
- if (eventType == XmlPullParser.START_TAG && depth == parentDepth + 1) {
- mCurrentStartTag = mParser.getName();
- if (mLogTag != null && Log.isLoggable(mLogTag, Log.DEBUG)) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < depth; i++) sb.append(" ");
- sb.append("<").append(mParser.getName());
- int count = mParser.getAttributeCount();
- for (int i = 0; i < count; i++) {
- sb.append(" ");
- sb.append(mParser.getAttributeName(i));
- sb.append("=\"");
- sb.append(mParser.getAttributeValue(i));
- sb.append("\"");
- }
- sb.append(">");
- Log.d(mLogTag, sb.toString());
- }
- return mParser.getName();
- }
-
- if (eventType == XmlPullParser.END_TAG && depth == parentDepth) {
- if (mLogTag != null && Log.isLoggable(mLogTag, Log.DEBUG)) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < depth; i++) sb.append(" ");
- sb.append("</>"); // Not quite valid xml but it gets the job done.
- Log.d(mLogTag, sb.toString());
- }
- return null;
- }
-
- if (eventType == XmlPullParser.END_DOCUMENT && parentDepth == 0) {
- // we could just rely on the caller calling close(), which it should, but try
- // to auto-close for clients that might have missed doing so.
- if (source != null) {
- source.close();
- source = null;
- }
- return null;
- }
-
- if (eventType == XmlPullParser.TEXT && depth == parentDepth) {
- if (textBuilder == null) {
- continue;
- }
- String text = mParser.getText();
- textBuilder.append(text);
- return TEXT_TAG;
- }
- }
- }
-
- /**
- * The same as nextTagOrTexxt(int, StringBuilder) but ignores text blocks.
- */
- public String nextTag(int parentDepth) throws IOException, ParseException {
- return nextTagOrText(parentDepth, null /* ignore text */);
- }
-
- /**
- * Returns the depth of the current element. The depth is 0 before the first
- * element has been returned, 1 after that, etc.
- *
- * @return the depth of the current element
- */
- public int getDepth() {
- return mParser.getDepth();
- }
-
- /**
- * Consumes the rest of the children, accumulating any text at this level into the builder.
- *
- * @param textBuilder the builder to contain any text
- * @throws IOException propogated from the XmlPullParser
- * @throws ParseException if there was an error parsing the xml.
- */
- public void readRemainingText(int parentDepth, StringBuilder textBuilder)
- throws IOException, ParseException {
- while (nextTagOrText(parentDepth, textBuilder) != null) {
- }
- }
-
- /**
- * Returns the number of attributes on the current element.
- *
- * @return the number of attributes on the current element
- */
- public int numAttributes() {
- return mParser.getAttributeCount();
- }
-
- /**
- * Returns the name of the nth attribute on the current element.
- *
- * @return the name of the nth attribute on the current element
- */
- public String getAttributeName(int i) {
- return mParser.getAttributeName(i);
- }
-
- /**
- * Returns the namespace of the nth attribute on the current element.
- *
- * @return the namespace of the nth attribute on the current element
- */
- public String getAttributeNamespace(int i) {
- return mParser.getAttributeNamespace(i);
- }
-
- /**
- * Returns the string value of the named attribute.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute
- * @param defaultValue the value to return if the attribute is not specified
- * @return the value of the attribute
- */
- public String getStringAttribute(
- String namespace, String name, String defaultValue) {
- String value = mParser.getAttributeValue(namespace, name);
- if (null == value) return defaultValue;
- return value;
- }
-
- /**
- * Returns the string value of the named attribute. An exception will
- * be thrown if the attribute is not present.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute @return the value of the attribute
- * @throws ParseException thrown if the attribute is missing
- */
- public String getStringAttribute(String namespace, String name) throws ParseException {
- String value = mParser.getAttributeValue(namespace, name);
- if (null == value) {
- throw new ParseException(
- "missing '" + name + "' attribute on '" + mCurrentStartTag + "' element");
- }
- return value;
- }
-
- /**
- * Returns the string value of the named attribute. An exception will
- * be thrown if the attribute is not a valid integer.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute
- * @param defaultValue the value to return if the attribute is not specified
- * @return the value of the attribute
- * @throws ParseException thrown if the attribute not a valid integer.
- */
- public int getIntAttribute(String namespace, String name, int defaultValue)
- throws ParseException {
- String value = mParser.getAttributeValue(namespace, name);
- if (null == value) return defaultValue;
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException e) {
- throw new ParseException("Cannot parse '" + value + "' as an integer");
- }
- }
-
- /**
- * Returns the string value of the named attribute. An exception will
- * be thrown if the attribute is not present or is not a valid integer.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute @return the value of the attribute
- * @throws ParseException thrown if the attribute is missing or not a valid integer.
- */
- public int getIntAttribute(String namespace, String name)
- throws ParseException {
- String value = getStringAttribute(namespace, name);
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException e) {
- throw new ParseException("Cannot parse '" + value + "' as an integer");
- }
- }
-
- /**
- * Returns the string value of the named attribute. An exception will
- * be thrown if the attribute is not a valid long.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute @return the value of the attribute
- * @throws ParseException thrown if the attribute is not a valid long.
- */
- public long getLongAttribute(String namespace, String name, long defaultValue)
- throws ParseException {
- String value = mParser.getAttributeValue(namespace, name);
- if (null == value) return defaultValue;
- try {
- return Long.parseLong(value);
- } catch (NumberFormatException e) {
- throw new ParseException("Cannot parse '" + value + "' as a long");
- }
- }
-
- /**
- * Close this SimplePullParser and any underlying resources (e.g., its InputStream or
- * Reader source) used by this SimplePullParser.
- */
- public void close() {
- if (source != null) {
- try {
- source.close();
- } catch (IOException ioe) {
- // ignore
- }
- }
- }
-
- /**
- * Returns the string value of the named attribute. An exception will
- * be thrown if the attribute is not present or is not a valid long.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute @return the value of the attribute
- * @throws ParseException thrown if the attribute is missing or not a valid long.
- */
- public long getLongAttribute(String namespace, String name)
- throws ParseException {
- String value = getStringAttribute(namespace, name);
- try {
- return Long.parseLong(value);
- } catch (NumberFormatException e) {
- throw new ParseException("Cannot parse '" + value + "' as a long");
- }
- }
-
- public static final class ParseException extends Exception {
- public ParseException(String message) {
- super(message);
- }
-
- public ParseException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public ParseException(Throwable cause) {
- super(cause);
- }
- }
-}
diff --git a/core/java/com/google/android/util/SmileyParser.java b/core/java/com/google/android/util/SmileyParser.java
deleted file mode 100644
index ef5d2a9..0000000
--- a/core/java/com/google/android/util/SmileyParser.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * 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 com.google.android.util;
-
-import android.content.Context;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.style.ImageSpan;
-
-import java.util.ArrayList;
-
-/**
- * Parses a text message typed by the user looking for smileys.
- */
-public class SmileyParser extends AbstractMessageParser {
-
- private SmileyResources mRes;
-
- public SmileyParser(String text, SmileyResources res) {
- super(text,
- true, // smilies
- false, // acronyms
- false, // formatting
- false, // urls
- false, // music
- false // me text
- );
- mRes = res;
- }
-
- @Override
- protected Resources getResources() {
- return mRes;
- }
-
- /**
- * Retrieves the parsed text as a spannable string object.
- * @param context the context for fetching smiley resources.
- * @return the spannable string as CharSequence.
- */
- public CharSequence getSpannableString(Context context) {
- SpannableStringBuilder builder = new SpannableStringBuilder();
-
- if (getPartCount() == 0) {
- return "";
- }
-
- // should have only one part since we parse smiley only
- Part part = getPart(0);
- ArrayList<Token> tokens = part.getTokens();
- int len = tokens.size();
- for (int i = 0; i < len; i++) {
- Token token = tokens.get(i);
- int start = builder.length();
- builder.append(token.getRawText());
- if (token.getType() == AbstractMessageParser.Token.Type.SMILEY) {
- int resid = mRes.getSmileyRes(token.getRawText());
- if (resid != -1) {
- builder.setSpan(new ImageSpan(context, resid),
- start,
- builder.length(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
- return builder;
- }
-
-}
diff --git a/core/java/com/google/android/util/SmileyResources.java b/core/java/com/google/android/util/SmileyResources.java
deleted file mode 100644
index 789158f..0000000
--- a/core/java/com/google/android/util/SmileyResources.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * 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 com.google.android.util;
-
-import com.google.android.util.AbstractMessageParser.TrieNode;
-
-import java.util.HashMap;
-import java.util.Set;
-
-/**
- * Resources for smiley parser.
- */
-public class SmileyResources implements AbstractMessageParser.Resources {
- private HashMap<String, Integer> mSmileyToRes = new HashMap<String, Integer>();
-
- /**
- *
- * @param smilies Smiley text, e.g. ":)", "8-)"
- * @param smileyResIds Resource IDs associated with the smileys.
- */
- public SmileyResources(String[] smilies, int[] smileyResIds) {
- for (int i = 0; i < smilies.length; i++) {
- TrieNode.addToTrie(smileys, smilies[i], "");
- mSmileyToRes.put(smilies[i], smileyResIds[i]);
- }
- }
-
- /**
- * Looks up the resource id of a given smiley.
- * @param smiley The smiley to look up.
- * @return the resource id of the specified smiley, or -1 if no resource
- * id is associated with it.
- */
- public int getSmileyRes(String smiley) {
- Integer i = mSmileyToRes.get(smiley);
- if (i == null) {
- return -1;
- }
- return i.intValue();
- }
-
- private final TrieNode smileys = new TrieNode();
-
- public Set<String> getSchemes() {
- return null;
- }
-
- public TrieNode getDomainSuffixes() {
- return null;
- }
-
- public TrieNode getSmileys() {
- return smileys;
- }
-
- public TrieNode getAcronyms() {
- return null;
- }
-
-}