1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.content; 18 19 import android.net.Uri; 20 import android.util.Xml; 21 22 import org.xml.sax.Attributes; 23 import org.xml.sax.Locator; 24 import org.xml.sax.SAXException; 25 26 import java.io.IOException; 27 import java.io.InputStream; 28 import java.util.Stack; 29 30 /** 31 * Inserts default data from InputStream, should be in XML format. 32 * If the provider syncs data to the server, the imported data will be synced to the server. 33 * <p>Samples:</p> 34 * <br/> 35 * Insert one row: 36 * <pre> 37 * <row uri="content://contacts/people"> 38 * <Col column = "name" value = "foo feebe "/> 39 * <Col column = "addr" value = "Tx"/> 40 * </row></pre> 41 * <br/> 42 * Delete, it must be in order of uri, select, and arg: 43 * <pre> 44 * <del uri="content://contacts/people" select="name=? and addr=?" 45 * arg1 = "foo feebe" arg2 ="Tx"/></pre> 46 * <br/> 47 * Use first row's uri to insert into another table, 48 * content://contacts/people/1/phones: 49 * <pre> 50 * <row uri="content://contacts/people"> 51 * <col column = "name" value = "foo feebe"/> 52 * <col column = "addr" value = "Tx"/> 53 * <row postfix="phones"> 54 * <col column="number" value="512-514-6535"/> 55 * </row> 56 * <row postfix="phones"> 57 * <col column="cell" value="512-514-6535"/> 58 * </row> 59 * </row></pre> 60 * <br/> 61 * Insert multiple rows in to same table and same attributes: 62 * <pre> 63 * <row uri="content://contacts/people" > 64 * <row> 65 * <col column= "name" value = "foo feebe"/> 66 * <col column= "addr" value = "Tx"/> 67 * </row> 68 * <row> 69 * </row> 70 * </row></pre> 71 * 72 * @hide 73 */ 74 public class DefaultDataHandler implements ContentInsertHandler { 75 private final static String ROW = "row"; 76 private final static String COL = "col"; 77 private final static String URI_STR = "uri"; 78 private final static String POSTFIX = "postfix"; 79 private final static String DEL = "del"; 80 private final static String SELECT = "select"; 81 private final static String ARG = "arg"; 82 83 private Stack<Uri> mUris = new Stack<Uri>(); 84 private ContentValues mValues; 85 private ContentResolver mContentResolver; 86 87 public void insert(ContentResolver contentResolver, InputStream in) 88 throws IOException, SAXException { 89 mContentResolver = contentResolver; 90 Xml.parse(in, Xml.Encoding.UTF_8, this); 91 } 92 93 public void insert(ContentResolver contentResolver, String in) 94 throws SAXException { 95 mContentResolver = contentResolver; 96 Xml.parse(in, this); 97 } 98 99 private void parseRow(Attributes atts) throws SAXException { 100 String uriStr = atts.getValue(URI_STR); 101 Uri uri; 102 if (uriStr != null) { 103 // case 1 104 uri = Uri.parse(uriStr); 105 if (uri == null) { 106 throw new SAXException("attribute " + 107 atts.getValue(URI_STR) + " parsing failure"); 108 } 109 110 } else if (mUris.size() > 0){ 111 // case 2 112 String postfix = atts.getValue(POSTFIX); 113 if (postfix != null) { 114 uri = Uri.withAppendedPath(mUris.lastElement(), 115 postfix); 116 } else { 117 uri = mUris.lastElement(); 118 } 119 } else { 120 throw new SAXException("attribute parsing failure"); 121 } 122 123 mUris.push(uri); 124 125 } 126 127 private Uri insertRow() { 128 Uri u = mContentResolver.insert(mUris.lastElement(), mValues); 129 mValues = null; 130 return u; 131 } 132 133 public void startElement(String uri, String localName, String name, 134 Attributes atts) throws SAXException { 135 if (ROW.equals(localName)) { 136 if (mValues != null) { 137 // case 2, <Col> before <Row> insert last uri 138 if (mUris.empty()) { 139 throw new SAXException("uri is empty"); 140 } 141 Uri nextUri = insertRow(); 142 if (nextUri == null) { 143 throw new SAXException("insert to uri " + 144 mUris.lastElement().toString() + " failure"); 145 } else { 146 // make sure the stack lastElement save uri for more than one row 147 mUris.pop(); 148 mUris.push(nextUri); 149 parseRow(atts); 150 } 151 } else { 152 int attrLen = atts.getLength(); 153 if (attrLen == 0) { 154 // case 3, share same uri as last level 155 mUris.push(mUris.lastElement()); 156 } else { 157 parseRow(atts); 158 } 159 } 160 } else if (COL.equals(localName)) { 161 int attrLen = atts.getLength(); 162 if (attrLen != 2) { 163 throw new SAXException("illegal attributes number " + attrLen); 164 } 165 String key = atts.getValue(0); 166 String value = atts.getValue(1); 167 if (key != null && key.length() > 0 && value != null && value.length() > 0) { 168 if (mValues == null) { 169 mValues = new ContentValues(); 170 } 171 mValues.put(key, value); 172 } else { 173 throw new SAXException("illegal attributes value"); 174 } 175 } else if (DEL.equals(localName)){ 176 Uri u = Uri.parse(atts.getValue(URI_STR)); 177 if (u == null) { 178 throw new SAXException("attribute " + 179 atts.getValue(URI_STR) + " parsing failure"); 180 } 181 int attrLen = atts.getLength() - 2; 182 if (attrLen > 0) { 183 String[] selectionArgs = new String[attrLen]; 184 for (int i = 0; i < attrLen; i++) { 185 selectionArgs[i] = atts.getValue(i+2); 186 } 187 mContentResolver.delete(u, atts.getValue(1), selectionArgs); 188 } else if (attrLen == 0){ 189 mContentResolver.delete(u, atts.getValue(1), null); 190 } else { 191 mContentResolver.delete(u, null, null); 192 } 193 194 } else { 195 throw new SAXException("unknown element: " + localName); 196 } 197 } 198 199 public void endElement(String uri, String localName, String name) 200 throws SAXException { 201 if (ROW.equals(localName)) { 202 if (mUris.empty()) { 203 throw new SAXException("uri mismatch"); 204 } 205 if (mValues != null) { 206 insertRow(); 207 } 208 mUris.pop(); 209 } 210 } 211 212 213 public void characters(char[] ch, int start, int length) 214 throws SAXException { 215 // TODO Auto-generated method stub 216 217 } 218 219 public void endDocument() throws SAXException { 220 // TODO Auto-generated method stub 221 222 } 223 224 public void endPrefixMapping(String prefix) throws SAXException { 225 // TODO Auto-generated method stub 226 227 } 228 229 public void ignorableWhitespace(char[] ch, int start, int length) 230 throws SAXException { 231 // TODO Auto-generated method stub 232 233 } 234 235 public void processingInstruction(String target, String data) 236 throws SAXException { 237 // TODO Auto-generated method stub 238 239 } 240 241 public void setDocumentLocator(Locator locator) { 242 // TODO Auto-generated method stub 243 244 } 245 246 public void skippedEntity(String name) throws SAXException { 247 // TODO Auto-generated method stub 248 249 } 250 251 public void startDocument() throws SAXException { 252 // TODO Auto-generated method stub 253 254 } 255 256 public void startPrefixMapping(String prefix, String uri) 257 throws SAXException { 258 // TODO Auto-generated method stub 259 260 } 261 262 } 263