SAXParserBase.java

1
/* $Id: SAXParserBase.java 19907 2012-12-30 13:06:01Z closettop_nightlybuild $
2
 *****************************************************************************
3
 * Copyright (c) 2009-2012 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-2006 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.FileInputStream;
42
import java.io.IOException;
43
import java.io.InputStream;
44
import java.io.Reader;
45
import java.net.URL;
46
import java.util.logging.Level;
47
import java.util.logging.Logger;
48
49
import javax.xml.parsers.ParserConfigurationException;
50
import javax.xml.parsers.SAXParser;
51
import javax.xml.parsers.SAXParserFactory;
52
53
import org.xml.sax.Attributes;
54
import org.xml.sax.InputSource;
55
import org.xml.sax.SAXException;
56
import org.xml.sax.helpers.DefaultHandler;
57
58
/**
59
 * @author Jim Holt
60
 */
61
62
abstract class SAXParserBase extends DefaultHandler {
63
    /**
64
     * Logger.
65
     */
66
    private static final Logger LOG =
67
        Logger.getLogger(SAXParserBase.class.getName());
68
69
    /**
70
     * The constructor.
71
     */
72
    public SAXParserBase() {
73
        // empty constructor
74
    }
75
76
    ////////////////////////////////////////////////////////////////
77
    // static variables
78
79
    /**
80
     * Switching this to true gives some extra logging messages.
81
     */
82
    protected static final boolean DBG = false;
83
84
    /**
85
     * This acts as a stack of elements.<p>
86
     *
87
     * {@link #startElement(String, String, String, Attributes)} places
88
     * an item on the stack end {@link #endElement(String, String, String)}
89
     * removes it.
90
     */
91
    private   static  XMLElement[]  elements      = new XMLElement[100];
92
93
    /**
94
     * The number of items actually in use on the elements stack.
95
     */
96
    private   static  int           nElements     = 0;
97
98
    /**
99
     * This acts as a stack of elements.<p>
100
     *
101
     * {@link #startElement(String, String, String, Attributes)} places
102
     * an item on the stack end {@link #endElement(String, String, String)}
103
     * removes it.
104
     */
105
    private   static  XMLElement[]  freeElements  = new XMLElement[100];
106
    private   static  int           nFreeElements = 0;
107
108
    private   static  boolean       stats         = true;
109
    private   static  long          parseTime     = 0;
110
111
    ////////////////////////////////////////////////////////////////
112
    // accessors
113
114
    /**
115
     * @param s true if statistics have to be shown
116
     */
117
    public void    setStats(boolean s) { stats = s; }
118
119
    /**
120
     * @return  true if statistics have to be shown
121
     */
122 1 1. getStats : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE
    public boolean getStats()              { return stats; }
123
124
    /**
125
     * @return the parsing time
126
     */
127
    public long getParseTime() {
128 1 1. getParseTime : replaced return of long value with value + 1 for org/argouml/persistence/SAXParserBase::getParseTime → NO_COVERAGE
        return parseTime;
129
    }
130
131
132
    /**
133
     * @param reader the reader to read
134
     * @throws SAXException when parsing xml
135
     */
136
    public void parse(Reader reader) throws SAXException {
137 1 1. parse : removed call to org/argouml/persistence/SAXParserBase::parse → NO_COVERAGE
        parse(new InputSource(reader));
138
    }
139
140
    /**
141
     * @param input the InputSource to read
142
     * @throws SAXException when parsing xml
143
     */
144
    public void parse(InputSource input) throws SAXException {
145
146
        long start, end;
147
148
        SAXParserFactory factory = SAXParserFactory.newInstance();
149 1 1. parse : removed call to javax/xml/parsers/SAXParserFactory::setNamespaceAware → NO_COVERAGE
        factory.setNamespaceAware(false);
150 1 1. parse : removed call to javax/xml/parsers/SAXParserFactory::setValidating → NO_COVERAGE
        factory.setValidating(false);
151
152
        try {
153
            SAXParser parser = factory.newSAXParser();
154
155
            // If we weren't given a system ID, attempt to use the URL for the
156
            // JAR that we were loaded from.  (Why? - tfm)
157 1 1. parse : negated conditional → NO_COVERAGE
            if (input.getSystemId() == null) {
158 1 1. parse : removed call to org/xml/sax/InputSource::setSystemId → NO_COVERAGE
                input.setSystemId(getJarResource("org.argouml.kernel.Project"));
159
            }
160
161
            start = System.currentTimeMillis();
162 1 1. parse : removed call to javax/xml/parsers/SAXParser::parse → NO_COVERAGE
            parser.parse(input, this);
163
            end = System.currentTimeMillis();
164 1 1. parse : Replaced long subtraction with addition → NO_COVERAGE
            parseTime = end - start;
165
        } catch (IOException e) {
166
            throw new SAXException(e);
167
        } catch (ParserConfigurationException e) {
168
            throw new SAXException(e);
169
        }
170 1 1. parse : negated conditional → NO_COVERAGE
        if (stats) {
171
            LOG.log(Level.INFO, "Elapsed time: {0} ms", (end - start));
172
        }
173
    }
174
175
    ////////////////////////////////////////////////////////////////
176
    // abstract methods
177
178
    /**
179
     * Implement in the concrete class to handle reaching the start tag of
180
     * an element of interest.
181
     * @param e the element.
182
     * @throws SAXException on any error parsing the element.
183
     */
184
    protected abstract void handleStartElement(XMLElement e)
185
        throws SAXException;
186
    /**
187
     * Implement in the concrete class to handle reaching the end tag of
188
     * an element of interest.
189
     * @param e the element.
190
     * @throws SAXException on any error parsing the element.
191
     */
192
    protected abstract void handleEndElement(XMLElement e)
193
        throws SAXException;
194
195
    ////////////////////////////////////////////////////////////////
196
    // non-abstract methods
197
198
    /*
199
     * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
200
     *         java.lang.String, java.lang.String, org.xml.sax.Attributes)
201
     */
202
    public void startElement(String uri,
203
            String localname,
204
            String name,
205
            Attributes atts) throws SAXException {
206 1 1. startElement : negated conditional → NO_COVERAGE
        if (isElementOfInterest(name)) {
207
208
            XMLElement element = createXmlElement(name, atts);
209
210
            if (LOG.isLoggable(Level.FINE)) {
211
                StringBuffer buf = new StringBuffer();
212
                buf.append("START: ").append(name).append(' ').append(element);
213 3 1. startElement : changed conditional boundary → NO_COVERAGE
2. startElement : Changed increment from 1 to -1 → NO_COVERAGE
3. startElement : negated conditional → NO_COVERAGE
                for (int i = 0; i < atts.getLength(); i++) {
214
            	    buf.append("   ATT: ")
215
                        .append(atts.getLocalName(i))
216
                            .append(' ')
217
                                .append(atts.getValue(i));
218
                }
219
                LOG.log(Level.FINE, "{0}", buf);
220
            }
221
222 1 1. startElement : Replaced integer addition with subtraction → NO_COVERAGE
            elements[nElements++] = element;
223 1 1. startElement : removed call to org/argouml/persistence/SAXParserBase::handleStartElement → NO_COVERAGE
            handleStartElement(element);
224
        }
225
    }
226
227
    /**
228
     * Factory method to return an XMLElement.
229
     * This will reuse previously created elements when possible.
230
     * @param name The element name.
231
     * @param atts The element attributes.
232
     * @return the element.
233
     */
234
    private XMLElement createXmlElement(String name, Attributes atts) {
235 1 1. createXmlElement : negated conditional → NO_COVERAGE
        if (nFreeElements == 0) {
236 1 1. createXmlElement : mutated return of Object value for org/argouml/persistence/SAXParserBase::createXmlElement to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
            return new XMLElement(name, atts);
237
        }
238 1 1. createXmlElement : Replaced integer subtraction with addition → NO_COVERAGE
        XMLElement e = freeElements[--nFreeElements];
239 1 1. createXmlElement : removed call to org/argouml/persistence/XMLElement::setName → NO_COVERAGE
        e.setName(name);
240 1 1. createXmlElement : removed call to org/argouml/persistence/XMLElement::setAttributes → NO_COVERAGE
        e.setAttributes(atts);
241 1 1. createXmlElement : removed call to org/argouml/persistence/XMLElement::resetText → NO_COVERAGE
        e.resetText();
242 1 1. createXmlElement : mutated return of Object value for org/argouml/persistence/SAXParserBase::createXmlElement to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
        return e;
243
    }
244
245
    /*
246
     * @see org.xml.sax.ContentHandler#endElement(java.lang.String,
247
     *         java.lang.String, java.lang.String)
248
     */
249
    public void endElement(String uri, String localname, String name)
250
        throws SAXException {
251 1 1. endElement : negated conditional → NO_COVERAGE
        if (isElementOfInterest(name)) {
252 1 1. endElement : Replaced integer subtraction with addition → NO_COVERAGE
            XMLElement e = elements[--nElements];
253
            if (LOG.isLoggable(Level.FINE)) {
254
                StringBuffer buf = new StringBuffer();
255
                buf.append("END: " + e.getName() + " ["
256
            	       + e.getText() + "] " + e + "\n");
257 3 1. endElement : changed conditional boundary → NO_COVERAGE
2. endElement : Changed increment from 1 to -1 → NO_COVERAGE
3. endElement : negated conditional → NO_COVERAGE
                for (int i = 0; i < e.getNumAttributes(); i++) {
258
                    buf.append("   ATT: " + e.getAttributeName(i) + " "
259
                    	   + e.getAttributeValue(i) + "\n");
260
                }
261
                LOG.log(Level.FINE, "{0}", buf);
262
            }
263 1 1. endElement : removed call to org/argouml/persistence/SAXParserBase::handleEndElement → NO_COVERAGE
            handleEndElement(e);
264
        }
265
    }
266
267
    /**
268
     * Determine if an element of the given name is of interest to
269
     * the parser. The base implementation assumes always true.
270
     *
271
     * @param name the element name.
272
     * @return true if the element name is of interest.
273
     */
274
    protected boolean isElementOfInterest(String name) {
275 1 1. isElementOfInterest : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE
        return true;
276
    }
277
278
    // TODO: remove when code below in characters() is removed
279
//    private static final String    RETURNSTRING  = "\n      ";
280
281
    /*
282
     * @see org.xml.sax.ContentHandler#characters(char[], int, int)
283
     */
284
    public void characters(char[] ch, int start, int length)
285
        throws SAXException {
286
287 2 1. characters : Replaced integer subtraction with addition → NO_COVERAGE
2. characters : removed call to org/argouml/persistence/XMLElement::addText → NO_COVERAGE
        elements[nElements - 1].addText(ch, start, length);
288
289
        // TODO: Remove this old implementation after 0.22 if it's
290
        // demonstrated that it's not needed. - tfm
291
292
        // Why does the text get added to ALL the elements on the stack? - tfm
293
//        for (int i = 0; i < nElements; i++) {
294
//            XMLElement e = elements[i];
295
//            if (e.length() > 0) {
296
//                // This seems wrong since this method can be called
297
//                // multiple times at the parser's discretion - tfm
298
//                e.addText(RETURNSTRING);
299
//            }
300
//            e.addText(ch, start, length);
301
//        }
302
    }
303
304
305
    /*
306
     * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String,
307
     *         java.lang.String)
308
     */
309
    public InputSource resolveEntity (String publicId, String systemId)
310
        throws SAXException {
311
        try {
312
	    URL testIt = new URL(systemId);
313
            InputSource s = new InputSource(testIt.openStream());
314 1 1. resolveEntity : mutated return of Object value for org/argouml/persistence/SAXParserBase::resolveEntity to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
            return s;
315
        } catch (Exception e) {
316
            LOG.log(Level.INFO,
317
                    "NOTE: Could not open DTD " + systemId
318
                    + " due to exception");
319
320 1 1. resolveEntity : Replaced integer addition with subtraction → NO_COVERAGE
            String dtdName = systemId.substring(systemId.lastIndexOf('/') + 1);
321
            String dtdPath = "/org/argouml/persistence/" + dtdName;
322
            InputStream is = SAXParserBase.class.getResourceAsStream(dtdPath);
323 1 1. resolveEntity : negated conditional → NO_COVERAGE
            if (is == null) {
324
                try {
325
                    is = new FileInputStream(dtdPath.substring(1));
326
                } catch (Exception ex) {
327
                    throw new SAXException(e);
328
                }
329
            }
330 1 1. resolveEntity : mutated return of Object value for org/argouml/persistence/SAXParserBase::resolveEntity to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
            return new InputSource(is);
331
        }
332
    }
333
334
    /**
335
     * @param cls the class
336
     * @return the jar
337
     */
338
    public String getJarResource(String cls) {
339
  	//e.g:org.argouml.uml.generator.ui.ClassGenerationDialog -> poseidon.jar
340
        String jarFile = "";
341
        String fileSep = System.getProperty("file.separator");
342
        String classFile = cls.replace('.', fileSep.charAt(0)) + ".class";
343
        ClassLoader thisClassLoader = this.getClass().getClassLoader();
344
        URL url = thisClassLoader.getResource(classFile);
345 1 1. getJarResource : negated conditional → NO_COVERAGE
        if (url != null) {
346
            String urlString = url.getFile();
347
            int idBegin = urlString.indexOf("file:");
348
            int idEnd = urlString.indexOf("!");
349 6 1. getJarResource : changed conditional boundary → NO_COVERAGE
2. getJarResource : changed conditional boundary → NO_COVERAGE
3. getJarResource : changed conditional boundary → NO_COVERAGE
4. getJarResource : negated conditional → NO_COVERAGE
5. getJarResource : negated conditional → NO_COVERAGE
6. getJarResource : negated conditional → NO_COVERAGE
            if (idBegin > -1 && idEnd > -1 && idEnd > idBegin) {
350 1 1. getJarResource : Replaced integer addition with subtraction → NO_COVERAGE
                jarFile = urlString.substring(idBegin + 5, idEnd);
351
            }
352
        }
353
354 1 1. getJarResource : mutated return of Object value for org/argouml/persistence/SAXParserBase::getJarResource to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE
        return jarFile;
355
    }
356
357
    ////////////////////////////////////////////////////////////////
358
    // convenience methods
359
360
    /**
361
     * @param e the element
362
     */
363
    public void ignoreElement(XMLElement e) {
364
        LOG.log(Level.FINE, "NOTE: ignoring tag: {0}", e.getName());
365
    }
366
367
    /**
368
     * @param e the element
369
     */
370
    public void notImplemented(XMLElement e) {
371
        LOG.log(Level.FINE, "NOTE: element not implemented: {0}", e.getName());
372
    }
373
} /* end class SAXParserBase */

Mutations

122

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

128

1.1
Location : getParseTime
Killed by : none
replaced return of long value with value + 1 for org/argouml/persistence/SAXParserBase::getParseTime → NO_COVERAGE

137

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

149

1.1
Location : parse
Killed by : none
removed call to javax/xml/parsers/SAXParserFactory::setNamespaceAware → NO_COVERAGE

150

1.1
Location : parse
Killed by : none
removed call to javax/xml/parsers/SAXParserFactory::setValidating → NO_COVERAGE

157

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

158

1.1
Location : parse
Killed by : none
removed call to org/xml/sax/InputSource::setSystemId → NO_COVERAGE

162

1.1
Location : parse
Killed by : none
removed call to javax/xml/parsers/SAXParser::parse → NO_COVERAGE

164

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

170

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

206

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

213

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

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

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

222

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

223

1.1
Location : startElement
Killed by : none
removed call to org/argouml/persistence/SAXParserBase::handleStartElement → NO_COVERAGE

235

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

236

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

238

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

239

1.1
Location : createXmlElement
Killed by : none
removed call to org/argouml/persistence/XMLElement::setName → NO_COVERAGE

240

1.1
Location : createXmlElement
Killed by : none
removed call to org/argouml/persistence/XMLElement::setAttributes → NO_COVERAGE

241

1.1
Location : createXmlElement
Killed by : none
removed call to org/argouml/persistence/XMLElement::resetText → NO_COVERAGE

242

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

251

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

252

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

257

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

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

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

263

1.1
Location : endElement
Killed by : none
removed call to org/argouml/persistence/SAXParserBase::handleEndElement → NO_COVERAGE

275

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

287

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

2.2
Location : characters
Killed by : none
removed call to org/argouml/persistence/XMLElement::addText → NO_COVERAGE

314

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

320

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

323

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

330

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

345

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

349

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

2.2
Location : getJarResource
Killed by : none
changed conditional boundary → NO_COVERAGE

3.3
Location : getJarResource
Killed by : none
changed conditional boundary → NO_COVERAGE

4.4
Location : getJarResource
Killed by : none
negated conditional → NO_COVERAGE

5.5
Location : getJarResource
Killed by : none
negated conditional → NO_COVERAGE

6.6
Location : getJarResource
Killed by : none
negated conditional → NO_COVERAGE

350

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

354

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

Active mutators

Tests examined


Report generated by PIT 0.32