1 /* 2 * Copyright (C) 2011 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 com.android.layoutlib.bridge.impl; 18 19 import com.android.ide.common.rendering.api.XmlParserFactory; 20 21 import org.xmlpull.v1.XmlPullParser; 22 import org.xmlpull.v1.XmlPullParserException; 23 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 27 import java.io.BufferedInputStream; 28 import java.io.ByteArrayInputStream; 29 import java.io.IOException; 30 import java.io.InputStream; 31 32 /** 33 * A factory for {@link XmlPullParser}. 34 */ 35 public class ParserFactory { 36 public final static boolean LOG_PARSER = false; 37 38 // Used to get a new XmlPullParser from the client. 39 @Nullable 40 private static XmlParserFactory sParserFactory; 41 setParserFactory(@ullable XmlParserFactory parserFactory)42 public static void setParserFactory(@Nullable XmlParserFactory parserFactory) { 43 sParserFactory = parserFactory; 44 } 45 46 @Nullable create(@onNull String filePath)47 public static XmlPullParser create(@NonNull String filePath) 48 throws XmlPullParserException { 49 return create(filePath, false); 50 } 51 52 @Nullable create(@onNull String filePath, boolean isLayout)53 public static XmlPullParser create(@NonNull String filePath, boolean isLayout) 54 throws XmlPullParserException { 55 XmlPullParser parser = sParserFactory.createXmlParserForFile(filePath); 56 if (parser != null && isLayout) { 57 try { 58 return new LayoutParserWrapper(parser).peekTillLayoutStart(); 59 } catch (IOException e) { 60 throw new XmlPullParserException(null, parser, e); 61 } 62 } 63 return parser; 64 } 65 66 @NonNull create(@onNull InputStream stream, @Nullable String name)67 public static XmlPullParser create(@NonNull InputStream stream, @Nullable String name) 68 throws XmlPullParserException { 69 XmlPullParser parser = create(); 70 71 stream = readAndClose(stream, name); 72 73 parser.setInput(stream, null); 74 return parser; 75 } 76 77 @NonNull create()78 public static XmlPullParser create() throws XmlPullParserException { 79 if (sParserFactory == null) { 80 throw new XmlPullParserException("ParserFactory not initialized."); 81 } 82 XmlPullParser parser = sParserFactory.createXmlParser(); 83 parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); 84 return parser; 85 } 86 87 @NonNull readAndClose(@onNull InputStream stream, @Nullable String name)88 private static InputStream readAndClose(@NonNull InputStream stream, @Nullable String name) 89 throws XmlPullParserException { 90 // Create a buffered stream to facilitate reading. 91 try (BufferedInputStream bufferedStream = new BufferedInputStream(stream)) { 92 int avail = bufferedStream.available(); 93 94 // Create the initial buffer and read it. 95 byte[] buffer = new byte[avail]; 96 int read = stream.read(buffer); 97 98 // Check if there is more to read (read() does not necessarily read all that 99 // available() returned!) 100 while ((avail = bufferedStream.available()) > 0) { 101 if (read + avail > buffer.length) { 102 // just allocate what is needed. We're mostly reading small files 103 // so it shouldn't be too problematic. 104 byte[] moreBuffer = new byte[read + avail]; 105 System.arraycopy(buffer, 0, moreBuffer, 0, read); 106 buffer = moreBuffer; 107 } 108 109 read += stream.read(buffer, read, avail); 110 } 111 112 // Return a new stream encapsulating this buffer. 113 return new ByteArrayInputStream(buffer); 114 } catch (IOException e) { 115 throw new XmlPullParserException("Failed to read " + name, null, e); 116 } 117 } 118 } 119