1 | /* $Id: XmiInputStream.java 17832 2010-01-12 19:02:29Z linus $ | |
2 | ***************************************************************************** | |
3 | * Copyright (c) 2009 Contributors - see below | |
4 | * All rights reserved. This program and the accompanying materials | |
5 | * are made available under the terms of the Eclipse Public License v1.0 | |
6 | * which accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * tfmorris | |
11 | ***************************************************************************** | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // Copyright (c) 1996-2007 The Regents of the University of California. All | |
17 | // Rights Reserved. Permission to use, copy, modify, and distribute this | |
18 | // software and its documentation without fee, and without a written | |
19 | // agreement is hereby granted, provided that the above copyright notice | |
20 | // and this paragraph appear in all copies. This software program and | |
21 | // documentation are copyrighted by The Regents of the University of | |
22 | // California. The software program and documentation are supplied "AS | |
23 | // IS", without any accompanying services from The Regents. The Regents | |
24 | // does not warrant that the operation of the program will be | |
25 | // uninterrupted or error-free. The end-user understands that the program | |
26 | // was developed for research purposes and is advised not to rely | |
27 | // exclusively on the program for any reason. IN NO EVENT SHALL THE | |
28 | // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | |
29 | // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | |
30 | // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | |
31 | // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF | |
32 | // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY | |
33 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
34 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE | |
35 | // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF | |
36 | // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, | |
37 | // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
38 | ||
39 | package org.argouml.persistence; | |
40 | ||
41 | import java.io.BufferedInputStream; | |
42 | import java.io.IOException; | |
43 | import java.io.InputStream; | |
44 | import java.util.StringTokenizer; | |
45 | ||
46 | import org.argouml.persistence.AbstractFilePersister.ProgressMgr; | |
47 | ||
48 | /** | |
49 | * A BufferInputStream that is aware of XML structure. | |
50 | * It can search for the first occurrence of a named tag | |
51 | * and reads only the data (inclusively) from that tag | |
52 | * to the matching end tag or it can search for the first | |
53 | * occurrence of a named tag and read on the child tags. | |
54 | * The tag is not expected to be an empty tag. | |
55 | * @author Bob Tarling | |
56 | */ | |
57 | class XmiInputStream extends BufferedInputStream { | |
58 | | |
59 | private String tagName; | |
60 | private String endTagName; | |
61 | private String attributes; | |
62 | private boolean extensionFound; | |
63 | private boolean endFound; | |
64 | private boolean parsingExtension; | |
65 | private boolean readingName; | |
66 | | |
67 | private XmiExtensionParser xmiExtensionParser; | |
68 | | |
69 | private StringBuffer stringBuffer; | |
70 | private String type; | |
71 | | |
72 | /** | |
73 | * The number of bytes to be read between each progress | |
74 | * event. | |
75 | */ | |
76 | private long eventSpacing; | |
77 | ||
78 | /** | |
79 | * The number of characters read so far. | |
80 | */ | |
81 | private long readCount; | |
82 | ||
83 | /** | |
84 | * The expected stream length. | |
85 | */ | |
86 | private ProgressMgr progressMgr; | |
87 | ||
88 | /** | |
89 | * Construct a new XmlInputStream. | |
90 | * | |
91 | * @param inputStream the input stream to wrap. | |
92 | * @param extParser the parser to call to read any | |
93 | * XMI.extension elements | |
94 | * @param spacing the number of characters to read before | |
95 | * firing a progress event. | |
96 | * @param prgrssMgr the progress manager | |
97 | */ | |
98 | public XmiInputStream( | |
99 | InputStream inputStream, | |
100 | XmiExtensionParser extParser, | |
101 | long spacing, | |
102 | ProgressMgr prgrssMgr) { | |
103 | super(inputStream); | |
104 | eventSpacing = spacing; | |
105 | xmiExtensionParser = extParser; | |
106 | progressMgr = prgrssMgr; | |
107 | } | |
108 | ||
109 | ||
110 | /* | |
111 | * @see java.io.InputStream#read() | |
112 | */ | |
113 | @Override | |
114 | public synchronized int read() throws IOException { | |
115 | ||
116 |
1
1. read : negated conditional → NO_COVERAGE |
if (endFound) { |
117 | extensionFound = false; | |
118 | parsingExtension = false; | |
119 | endFound = false; | |
120 | readingName = false; | |
121 | tagName = null; | |
122 | endTagName = null; | |
123 | } | |
124 | ||
125 | int ch = super.read(); | |
126 | | |
127 |
1
1. read : negated conditional → NO_COVERAGE |
if (parsingExtension) { |
128 | stringBuffer.append((char) ch); | |
129 | } | |
130 | // else { | |
131 | // TODO: Only progress when reading standard XMI | |
132 | // extension parsers will continue progression. | |
133 |
1
1. read : Replaced long addition with subtraction → NO_COVERAGE |
++readCount; |
134 |
2
1. read : negated conditional → NO_COVERAGE 2. read : negated conditional → NO_COVERAGE |
if (progressMgr != null && readCount == eventSpacing) { |
135 | try { | |
136 | readCount = 0; | |
137 |
1
1. read : removed call to org/argouml/persistence/AbstractFilePersister$ProgressMgr::nextPhase → NO_COVERAGE |
progressMgr.nextPhase(); |
138 | } catch (InterruptedException e) { | |
139 | throw new InterruptedIOException(e); | |
140 | } | |
141 | } | |
142 | // } | |
143 | | |
144 |
1
1. read : negated conditional → NO_COVERAGE |
if (xmiExtensionParser != null) { |
145 |
1
1. read : negated conditional → NO_COVERAGE |
if (readingName) { |
146 |
1
1. read : negated conditional → NO_COVERAGE |
if (isNameTerminator((char) ch)) { |
147 | readingName = false; | |
148 |
2
1. read : negated conditional → NO_COVERAGE 2. read : negated conditional → NO_COVERAGE |
if (parsingExtension && endTagName == null) { |
149 | endTagName = "/" + tagName; | |
150 |
1
1. read : negated conditional → NO_COVERAGE |
} else if (tagName.equals("XMI.extension")) { |
151 | extensionFound = true; | |
152 |
1
1. read : negated conditional → NO_COVERAGE |
} else if (tagName.equals(endTagName)) { |
153 | endFound = true; | |
154 |
1
1. read : removed call to org/argouml/persistence/XmiExtensionParser::parse → NO_COVERAGE |
xmiExtensionParser.parse(type, stringBuffer.toString()); |
155 | stringBuffer.delete(0, stringBuffer.length()); | |
156 | } | |
157 | } else { | |
158 | tagName += (char) ch; | |
159 | } | |
160 | } | |
161 | ||
162 |
1
1. read : negated conditional → NO_COVERAGE |
if (extensionFound) { |
163 |
1
1. read : negated conditional → NO_COVERAGE |
if (ch == '>') { |
164 | extensionFound = false; | |
165 |
1
1. read : removed call to org/argouml/persistence/XmiInputStream::callExtensionParser → NO_COVERAGE |
callExtensionParser(); |
166 | } else { | |
167 | attributes += (char) ch; | |
168 | } | |
169 | } | |
170 | | |
171 |
1
1. read : negated conditional → NO_COVERAGE |
if (ch == '<') { |
172 | readingName = true; | |
173 | tagName = ""; | |
174 | } | |
175 | } | |
176 |
1
1. read : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return ch; |
177 | } | |
178 | | |
179 | private void callExtensionParser() { | |
180 | String label = null; | |
181 | String extender = null; | |
182 |
1
1. callExtensionParser : negated conditional → NO_COVERAGE |
for (StringTokenizer st = new StringTokenizer(attributes, " ="); |
183 | st.hasMoreTokens(); ) { | |
184 | String attributeType = st.nextToken(); | |
185 |
1
1. callExtensionParser : negated conditional → NO_COVERAGE |
if (attributeType.equals("xmi.extender")) { |
186 | extender = st.nextToken(); | |
187 |
1
1. callExtensionParser : Replaced integer subtraction with addition → NO_COVERAGE |
extender = extender.substring(1, extender.length() - 1); |
188 | } | |
189 |
1
1. callExtensionParser : negated conditional → NO_COVERAGE |
if (attributeType.equals("xmi.label")) { |
190 | label = st.nextToken(); | |
191 |
1
1. callExtensionParser : Replaced integer subtraction with addition → NO_COVERAGE |
label = label.substring(1, label.length() - 1); |
192 | } | |
193 | } | |
194 |
1
1. callExtensionParser : negated conditional → NO_COVERAGE |
if ("ArgoUML".equals(extender)) { |
195 | type = label; | |
196 | stringBuffer = new StringBuffer(); | |
197 | parsingExtension = true; | |
198 | endTagName = null; | |
199 | } | |
200 | } | |
201 | | |
202 | /* | |
203 | * @see java.io.InputStream#read(byte[], int, int) | |
204 | */ | |
205 | @Override | |
206 | public synchronized int read(byte[] b, int off, int len) | |
207 | throws IOException { | |
208 | ||
209 | int cnt; | |
210 |
3
1. read : changed conditional boundary → NO_COVERAGE 2. read : Changed increment from 1 to -1 → NO_COVERAGE 3. read : negated conditional → NO_COVERAGE |
for (cnt = 0; cnt < len; ++cnt) { |
211 | int read = read(); | |
212 |
1
1. read : negated conditional → NO_COVERAGE |
if (read == -1) { |
213 | break; | |
214 | } | |
215 |
1
1. read : Replaced integer addition with subtraction → NO_COVERAGE |
b[cnt + off] = (byte) read; |
216 | } | |
217 | ||
218 |
2
1. read : changed conditional boundary → NO_COVERAGE 2. read : negated conditional → NO_COVERAGE |
if (cnt > 0) { |
219 |
1
1. read : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return cnt; |
220 | } | |
221 |
1
1. read : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return -1; |
222 | } | |
223 | ||
224 | ||
225 | private boolean isNameTerminator(char ch) { | |
226 |
4
1. isNameTerminator : negated conditional → NO_COVERAGE 2. isNameTerminator : negated conditional → NO_COVERAGE 3. isNameTerminator : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE 4. isNameTerminator : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return (ch == '>' || Character.isWhitespace(ch)); |
227 | } | |
228 | ||
229 | /** | |
230 | * The close method is overridden to prevent some class out of | |
231 | * our control from closing the stream (such as a SAX parser). | |
232 | * Use realClose() to finally close the stream for real. | |
233 | * @throws IOException to satisfy ancestor but will never happen. | |
234 | */ | |
235 | @Override | |
236 | public void close() throws IOException { | |
237 | } | |
238 | ||
239 | /** | |
240 | * Really close the input. | |
241 | * | |
242 | * @throws IOException if an I/O error occurs. | |
243 | */ | |
244 | public void realClose() throws IOException { | |
245 |
1
1. realClose : removed call to java/io/BufferedInputStream::close → NO_COVERAGE |
super.close(); |
246 | } | |
247 | } | |
248 | ||
249 | class InterruptedIOException extends IOException { | |
250 | | |
251 | private static final long serialVersionUID = 5654808047803205851L; | |
252 | | |
253 | private InterruptedException cause; | |
254 | | |
255 | public InterruptedIOException(InterruptedException theCause) { | |
256 | cause = theCause; | |
257 | } | |
258 | | |
259 | public InterruptedException getInterruptedException() { | |
260 |
1
1. getInterruptedException : mutated return of Object value for org/argouml/persistence/InterruptedIOException::getInterruptedException to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return cause; |
261 | } | |
262 | } | |
Mutations | ||
116 |
1.1 |
|
127 |
1.1 |
|
133 |
1.1 |
|
134 |
1.1 2.2 |
|
137 |
1.1 |
|
144 |
1.1 |
|
145 |
1.1 |
|
146 |
1.1 |
|
148 |
1.1 2.2 |
|
150 |
1.1 |
|
152 |
1.1 |
|
154 |
1.1 |
|
162 |
1.1 |
|
163 |
1.1 |
|
165 |
1.1 |
|
171 |
1.1 |
|
176 |
1.1 |
|
182 |
1.1 |
|
185 |
1.1 |
|
187 |
1.1 |
|
189 |
1.1 |
|
191 |
1.1 |
|
194 |
1.1 |
|
210 |
1.1 2.2 3.3 |
|
212 |
1.1 |
|
215 |
1.1 |
|
218 |
1.1 2.2 |
|
219 |
1.1 |
|
221 |
1.1 |
|
226 |
1.1 2.2 3.3 4.4 |
|
245 |
1.1 |
|
260 |
1.1 |