XmiInputStream.java

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
Location : read
Killed by : none
negated conditional → NO_COVERAGE

127

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

133

1.1
Location : read
Killed by : none
Replaced long addition with subtraction → NO_COVERAGE

134

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : read
Killed by : none
negated conditional → NO_COVERAGE

137

1.1
Location : read
Killed by : none
removed call to org/argouml/persistence/AbstractFilePersister$ProgressMgr::nextPhase → NO_COVERAGE

144

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

145

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

146

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

148

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : read
Killed by : none
negated conditional → NO_COVERAGE

150

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

152

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

154

1.1
Location : read
Killed by : none
removed call to org/argouml/persistence/XmiExtensionParser::parse → NO_COVERAGE

162

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

163

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

165

1.1
Location : read
Killed by : none
removed call to org/argouml/persistence/XmiInputStream::callExtensionParser → NO_COVERAGE

171

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

176

1.1
Location : read
Killed by : none
replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE

182

1.1
Location : callExtensionParser
Killed by : none
negated conditional → NO_COVERAGE

185

1.1
Location : callExtensionParser
Killed by : none
negated conditional → NO_COVERAGE

187

1.1
Location : callExtensionParser
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

189

1.1
Location : callExtensionParser
Killed by : none
negated conditional → NO_COVERAGE

191

1.1
Location : callExtensionParser
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

194

1.1
Location : callExtensionParser
Killed by : none
negated conditional → NO_COVERAGE

210

1.1
Location : read
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : read
Killed by : none
Changed increment from 1 to -1 → NO_COVERAGE

3.3
Location : read
Killed by : none
negated conditional → NO_COVERAGE

212

1.1
Location : read
Killed by : none
negated conditional → NO_COVERAGE

215

1.1
Location : read
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

218

1.1
Location : read
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : read
Killed by : none
negated conditional → NO_COVERAGE

219

1.1
Location : read
Killed by : none
replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE

221

1.1
Location : read
Killed by : none
replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE

226

1.1
Location : isNameTerminator
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : isNameTerminator
Killed by : none
negated conditional → NO_COVERAGE

3.3
Location : isNameTerminator
Killed by : none
replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE

4.4
Location : isNameTerminator
Killed by : none
replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE

245

1.1
Location : realClose
Killed by : none
removed call to java/io/BufferedInputStream::close → NO_COVERAGE

260

1.1
Location : getInterruptedException
Killed by : none
mutated return of Object value for org/argouml/persistence/InterruptedIOException::getInterruptedException to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 0.32