Coverage report

| %line | %branch
--- | --- | ---

org.apache.commons.jelly.XMLOutput

49%

81%

1

     /*

2

      * Copyright 2002,2004 The Apache Software Foundation.

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 org.apache.commons.jelly;

18

19

     import java.io.IOException;

20

     import java.io.OutputStream;

21

     import java.io.UnsupportedEncodingException;

22

     import java.io.Writer;

23

24

     import org.apache.commons.logging.Log;

25

     import org.apache.commons.logging.LogFactory;

26

     import org.dom4j.io.XMLWriter;

27

     import org.xml.sax.Attributes;

28

     import org.xml.sax.ContentHandler;

29

     import org.xml.sax.Locator;

30

     import org.xml.sax.SAXException;

31

     import org.xml.sax.XMLReader;

32

     import org.xml.sax.ext.LexicalHandler;

33

     import org.xml.sax.helpers.AttributesImpl;

34

     import org.xml.sax.helpers.DefaultHandler;

35

36

     /** <p><code>XMLOutput</code> is used to output XML events

37

       * in a SAX-like manner. This also allows pipelining to be done

38

       * such as in the <a href="http://xml.apache.org/cocoon/">Cocoon</a> project.</p>

39

       *

40

       * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>

41

       * @version $Revision: 155420 $

42

       */

43

44

     public class XMLOutput implements ContentHandler, LexicalHandler {

45

46

286

         protected static final String[] LEXICAL_HANDLER_NAMES =

47

             {

48

                 "http://xml.org/sax/properties/lexical-handler",

49

                 "http://xml.org/sax/handlers/LexicalHandler" };

50

51

         /** empty attributes */

52

286

         private static final Attributes EMPTY_ATTRIBUTES = new AttributesImpl();

53

54

         /** The Log to which logging calls will be made. */

55

572

         private static final Log log = LogFactory.getLog(XMLOutput.class);

56

57

         /** the default for escaping of text */

58

         private static final boolean DEFAULT_ESCAPE_TEXT = false;

59

60

         /** The SAX ContentHandler that output goes to */

61

         private ContentHandler contentHandler;

62

63

         /** The SAX LexicalHandler that output goes to */

64

         private LexicalHandler lexicalHandler;

65

66

67

897

         public XMLOutput() {

68

897

         }

69

70

962

         public XMLOutput(ContentHandler contentHandler) {

71

962

             this.contentHandler = contentHandler;

72

             // often classes will implement LexicalHandler as well

73

962

             if (contentHandler instanceof LexicalHandler) {

74

0

                 this.lexicalHandler = (LexicalHandler) contentHandler;

75

             }

76

962

         }

77

78

         public XMLOutput(

79

             ContentHandler contentHandler,

80

26

             LexicalHandler lexicalHandler) {

81

26

             this.contentHandler = contentHandler;

82

26

             this.lexicalHandler = lexicalHandler;

83

26

         }

84

85

         public String toString() {

86

0

             return super.toString()

87

                 + "[contentHandler="

88

                 + contentHandler

89

                 + ";lexicalHandler="

90

                 + lexicalHandler

91

                 + "]";

92

         }

93

94

         /**

95

          * Provides a useful hook that implementations can use to close the

96

          * underlying OutputStream or Writer

97

          */

98

         public void close() throws IOException {

99

0

         }

100

101

         public void flush() throws IOException {

102

11622

             if( contentHandler instanceof XMLWriter )

103

             {

104

3016

                 ((XMLWriter)contentHandler).flush();

105

             }

106

11622

         }

107

108

         // Static helper methods

109

         //-------------------------------------------------------------------------

110

111

         /**

112

          * Creates an XMLOutput from an existing SAX XMLReader

113

          */

114

         public static XMLOutput createXMLOutput(XMLReader xmlReader) {

115

0

             XMLOutput output = new XMLOutput(xmlReader.getContentHandler());

116

117

             // isn't it lovely what we've got to do to find the LexicalHandler... ;-)

118

0

             for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) {

119

                 try {

120

0

                     Object value = xmlReader.getProperty(LEXICAL_HANDLER_NAMES[i]);

121

0

                     if (value instanceof LexicalHandler) {

122

0

                         output.setLexicalHandler((LexicalHandler) value);

123

0

                         break;

124

                     }

125

                 }

126

0

                 catch (Exception e) {

127

                     // ignore any unsupported-operation exceptions

128

0

                     if (log.isDebugEnabled()) log.debug("error setting lexical handler properties", e);

129

0

                 }

130

             }

131

0

             return output;

132

         }

133

134

         /**

135

          * Creates a text based XMLOutput which converts all XML events into

136

          * text and writes to the underlying Writer.

137

          */

138

         public static XMLOutput createXMLOutput(Writer writer) {

139

169

             return createXMLOutput(writer, DEFAULT_ESCAPE_TEXT);

140

         }

141

142

         /**

143

          * Creates a text based XMLOutput which converts all XML events into

144

          * text and writes to the underlying Writer.

145

          *

146

          * @param writer is the writer to output to

147

          * @param escapeText is whether or not text output will be escaped. This must be true

148

          * if the underlying output is XML or could be false if the underlying output is textual.

149

          */

150

         public static XMLOutput createXMLOutput(Writer writer, boolean escapeText)

151

         {

152

741

             XMLWriter xmlWriter = new XMLWriter(writer);

153

741

             xmlWriter.setEscapeText(escapeText);

154

741

             return createXMLOutput(xmlWriter);

155

         }

156

157

         /**

158

          * Creates a text based XMLOutput which converts all XML events into

159

          * text and writes to the underlying OutputStream.

160

          */

161

         public static XMLOutput createXMLOutput(OutputStream out) throws UnsupportedEncodingException {

162

78

             return createXMLOutput(out, DEFAULT_ESCAPE_TEXT);

163

         }

164

165

         /**

166

          * Creates a text based XMLOutput which converts all XML events into

167

          * text and writes to the underlying OutputStream.

168

          *

169

          * @param out is the output stream to write

170

          * @param escapeText is whether or not text output will be escaped. This must be true

171

          * if the underlying output is XML or could be false if the underlying output is textual.

172

          */

173

         public static XMLOutput createXMLOutput(OutputStream out, boolean escapeText) throws UnsupportedEncodingException {

174

78

             XMLWriter xmlWriter = new XMLWriter(out);

175

78

             xmlWriter.setEscapeText(escapeText);

176

78

             return createXMLOutput(xmlWriter);

177

         }

178

179

         /**

180

          * returns an XMLOutput object that will discard all

181

          * tag-generated XML events.  Useful when tag output is not expected

182

          * or not significant.

183

          *

184

          * @return a no-op XMLOutput

185

          */

186

         public static XMLOutput createDummyXMLOutput() {

187

936

             return new XMLOutput(<span class="keyword">new DefaultHandler());

188

         }

189

190

         // Extra helper methods provided for tag authors

191

         //-------------------------------------------------------------------------

192

193

         /**

194

          * Outputs the given String as a piece of valid text in the

195

          * XML event stream.

196

          * Any special XML characters should be properly escaped.

197

          */

198

         public void write(String text) throws SAXException {

199

1820

             char[] ch = text.toCharArray();

200

1820

             characters(ch, 0, ch.length);

201

1820

         }

202

203

         /**

204

          * Outputs the given String as a piece of CDATA in the

205

          * XML event stream.

206

          */

207

         public void writeCDATA(String text) throws SAXException {

208

0

             startCDATA();

209

0

             char[] ch = text.toCharArray();

210

0

             characters(ch, 0, ch.length);

211

0

             endCDATA();

212

0

         }

213

214

         /**

215

          * Outputs a comment to the XML stream

216

          */

217

         public void writeComment(String text) throws SAXException {

218

0

             char[] ch = text.toCharArray();

219

0

             comment(ch, 0, ch.length);

220

0

         }

221

222

         /**

223

          * Helper method for outputting a start element event for an element in no namespace

224

          */

225

         public void startElement(String localName) throws SAXException {

226

0

             startElement("", localName, localName, EMPTY_ATTRIBUTES);

227

0

         }

228

229

         /**

230

          * Helper method for outputting a start element event for an element in no namespace

231

          */

232

         public void startElement(String localName, Attributes attributes) throws SAXException {

233

0

             startElement("", localName, localName, attributes);

234

0

         }

235

236

         /**

237

          * Helper method for outputting an end element event for an element in no namespace

238

          */

239

         public void endElement(String localName) throws SAXException {

240

0

             endElement("", localName, localName);

241

0

         }

242

243

244

         // ContentHandler interface

245

         //-------------------------------------------------------------------------

246

247

         /**

248

          * Receive an object for locating the origin of SAX document events.

249

          *

250

          * <p>SAX parsers are strongly encouraged (though not absolutely

251

          * required) to supply a locator: if it does so, it must supply

252

          * the locator to the application by invoking this method before

253

          * invoking any of the other methods in the ContentHandler

254

          * interface.</p>

255

          *

256

          * <p>The locator allows the application to determine the end

257

          * position of any document-related event, even if the parser is

258

          * not reporting an error.  Typically, the application will

259

          * use this information for reporting its own errors (such as

260

          * character content that does not match an application's

261

          * business rules).  The information returned by the locator

262

          * is probably not sufficient for use with a search engine.</p>

263

          *

264

          * <p>Note that the locator will return correct information only

265

          * during the invocation of the events in this interface.  The

266

          * application should not attempt to use it at any other time.</p>

267

          *

268

          * @param locator An object that can return the location of

269

          *                any SAX document event.

270

          * @see org.xml.sax.Locator

271

          */

272

         public void setDocumentLocator(Locator locator) {

273

0

             contentHandler.setDocumentLocator(locator);

274

0

         }

275

276

         /**

277

          * Receive notification of the beginning of a document.

278

          *

279

          * <p>The SAX parser will invoke this method only once, before any

280

          * other event callbacks (except for {@link #setDocumentLocator

281

          * setDocumentLocator}).</p>

282

          *

283

          * @exception org.xml.sax.SAXException Any SAX exception, possibly

284

          *            wrapping another exception.

285

          * @see #endDocument

286

          */

287

         public void startDocument() throws SAXException {

288

104

             contentHandler.startDocument();

289

104

         }

290

291

         /**

292

          * Receive notification of the end of a document.

293

          *

294

          * <p>The SAX parser will invoke this method only once, and it will

295

          * be the last method invoked during the parse.  The parser shall

296

          * not invoke this method until it has either abandoned parsing

297

          * (because of an unrecoverable error) or reached the end of

298

          * input.</p>

299

          *

300

          * @exception org.xml.sax.SAXException Any SAX exception, possibly

301

          *            wrapping another exception.

302

          * @see #startDocument

303

          */

304

         public void endDocument() throws SAXException {

305

104

             contentHandler.endDocument();

306

104

         }

307

308

         /**

309

          * Begin the scope of a prefix-URI Namespace mapping.

310

          *

311

          * <p>The information from this event is not necessary for

312

          * normal Namespace processing: the SAX XML reader will

313

          * automatically replace prefixes for element and attribute

314

          * names when the <code>http://xml.org/sax/features/namespaces</code>

315

          * feature is <var>true</var> (the default).</p>

316

          *

317

          * <p>There are cases, however, when applications need to

318

          * use prefixes in character data or in attribute values,

319

          * where they cannot safely be expanded automatically; the

320

          * start/endPrefixMapping event supplies the information

321

          * to the application to expand prefixes in those contexts

322

          * itself, if necessary.</p>

323

          *

324

          * <p>Note that start/endPrefixMapping events are not

325

          * guaranteed to be properly nested relative to each other:

326

          * all startPrefixMapping events will occur immediately before the

327

          * corresponding {@link #startElement startElement} event,

328

          * and all {@link #endPrefixMapping endPrefixMapping}

329

          * events will occur immediately after the corresponding

330

          * {@link #endElement endElement} event,

331

          * but their order is not otherwise

332

          * guaranteed.</p>

333

          *

334

          * <p>There should never be start/endPrefixMapping events for the

335

          * "xml" prefix, since it is predeclared and immutable.</p>

336

          *

337

          * @param prefix The Namespace prefix being declared.

338

          *  An empty string is used for the default element namespace,

339

          *  which has no prefix.

340

          * @param uri The Namespace URI the prefix is mapped to.

341

          * @exception org.xml.sax.SAXException The client may throw

342

          *            an exception during processing.

343

          * @see #endPrefixMapping

344

          * @see #startElement

345

          */

346

         public void startPrefixMapping(String prefix, String uri) throws SAXException {

347

13

             contentHandler.startPrefixMapping(prefix, uri);

348

13

         }

349

350

         /**

351

          * End the scope of a prefix-URI mapping.

352

          *

353

          * <p>See {@link #startPrefixMapping startPrefixMapping} for

354

          * details.  These events will always occur immediately after the

355

          * corresponding {@link #endElement endElement} event, but the order of

356

          * {@link #endPrefixMapping endPrefixMapping} events is not otherwise

357

          * guaranteed.</p>

358

          *

359

          * @param prefix The prefix that was being mapped.

360

          *  This is the empty string when a default mapping scope ends.

361

          * @exception org.xml.sax.SAXException The client may throw

362

          *            an exception during processing.

363

          * @see #startPrefixMapping

364

          * @see #endElement

365

          */

366

         public void endPrefixMapping(String prefix) throws SAXException {

367

13

             contentHandler.endPrefixMapping(prefix);

368

13

         }

369

370

         /**

371

          * Receive notification of the beginning of an element.

372

          *

373

          * <p>The Parser will invoke this method at the beginning of every

374

          * element in the XML document; there will be a corresponding

375

          * {@link #endElement endElement} event for every startElement event

376

          * (even when the element is empty). All of the element's content will be

377

          * reported, in order, before the corresponding endElement

378

          * event.</p>

379

          *

380

          * <p>This event allows up to three name components for each

381

          * element:</p>

382

          *

383

          * <ol>

384

          * <li>the Namespace URI;</li>

385

          * <li>the local name; and</li>

386

          * <li>the qualified (prefixed) name.</li>

387

          * </ol>

388

          *

389

          * <p>Any or all of these may be provided, depending on the

390

          * values of the <var>http://xml.org/sax/features/namespaces</var>

391

          * and the <var>http://xml.org/sax/features/namespace-prefixes</var>

392

          * properties:</p>

393

          *

394

          * <ul>

395

          * <li>the Namespace URI and local name are required when

396

          * the namespaces property is <var>true</var> (the default), and are

397

          * optional when the namespaces property is <var>false</var> (if one is

398

          * specified, both must be);</li>

399

          * <li>the qualified name is required when the namespace-prefixes property

400

          * is <var>true</var>, and is optional when the namespace-prefixes property

401

          * is <var>false</var> (the default).</li>

402

          * </ul>

403

          *

404

          * <p>Note that the attribute list provided will contain only

405

          * attributes with explicit values (specified or defaulted):

406

          * #IMPLIED attributes will be omitted.  The attribute list

407

          * will contain attributes used for Namespace declarations

408

          * (xmlns* attributes) only if the

409

          * <code>http://xml.org/sax/features/namespace-prefixes</code>

410

          * property is true (it is false by default, and support for a

411

          * true value is optional).</p>

412

          *

413

          * <p>Like {@link #characters characters()}, attribute values may have

414

          * characters that need more than one <code>char</code> value.  </p>

415

          *

416

          * @param uri The Namespace URI, or the empty string if the

417

          *        element has no Namespace URI or if Namespace

418

          *        processing is not being performed.

419

          * @param localName The local name (without prefix), or the

420

          *        empty string if Namespace processing is not being

421

          *        performed.

422

          * @param qName The qualified name (with prefix), or the

423

          *        empty string if qualified names are not available.

424

          * @param atts The attributes attached to the element.  If

425

          *        there are no attributes, it shall be an empty

426

          *        Attributes object.

427

          * @exception org.xml.sax.SAXException Any SAX exception, possibly

428

          *            wrapping another exception.

429

          * @see #endElement

430

          * @see org.xml.sax.Attributes

431

          */

432

         public void startElement(

433

             String uri,

434

             String localName,

435

             String qName,

436

             Attributes atts)

437

             throws SAXException {

438

156

             contentHandler.startElement(uri, localName, qName, atts);

439

156

         }

440

441

         /**

442

          * Receive notification of the end of an element.

443

          *

444

          * <p>The SAX parser will invoke this method at the end of every

445

          * element in the XML document; there will be a corresponding

446

          * {@link #startElement startElement} event for every endElement

447

          * event (even when the element is empty).</p>

448

          *

449

          * <p>For information on the names, see startElement.</p>

450

          *

451

          * @param uri The Namespace URI, or the empty string if the

452

          *        element has no Namespace URI or if Namespace

453

          *        processing is not being performed.

454

          * @param localName The local name (without prefix), or the

455

          *        empty string if Namespace processing is not being

456

          *        performed.

457

          * @param qName The qualified XML 1.0 name (with prefix), or the

458

          *        empty string if qualified names are not available.

459

          * @exception org.xml.sax.SAXException Any SAX exception, possibly

460

          *            wrapping another exception.

461

          */

462

         public void endElement(String uri, String localName, String qName)

463

             throws SAXException {

464

156

             contentHandler.endElement(uri, localName, qName);

465

156

         }

466

467

         /**

468

          * Receive notification of character data.

469

          *

470

          * <p>The Parser will call this method to report each chunk of

471

          * character data.  SAX parsers may return all contiguous character

472

          * data in a single chunk, or they may split it into several

473

          * chunks; however, all of the characters in any single event

474

          * must come from the same external entity so that the Locator

475

          * provides useful information.</p>

476

          *

477

          * <p>The application must not attempt to read from the array

478

          * outside of the specified range.</p>

479

          *

480

          * <p>Individual characters may consist of more than one Java

481

          * <code>char</code> value.  There are two important cases where this

482

          * happens, because characters can't be represented in just sixteen bits.

483

          * In one case, characters are represented in a <em>Surrogate Pair</em>,

484

          * using two special Unicode values. Such characters are in the so-called

485

          * "Astral Planes", with a code point above U+FFFF.  A second case involves

486

          * composite characters, such as a base character combining with one or

487

          * more accent characters. </p>

488

          *

489

          * <p> Your code should not assume that algorithms using

490

          * <code>char</code>-at-a-time idioms will be working in character

491

          * units; in some cases they will split characters.  This is relevant

492

          * wherever XML permits arbitrary characters, such as attribute values,

493

          * processing instruction data, and comments as well as in data reported

494

          * from this method.  It's also generally relevant whenever Java code

495

          * manipulates internationalized text; the issue isn't unique to XML.</p>

496

          *

497

          * <p>Note that some parsers will report whitespace in element

498

          * content using the {@link #ignorableWhitespace ignorableWhitespace}

499

          * method rather than this one (validating parsers <em>must</em>

500

          * do so).</p>

501

          *

502

          * @param ch The characters from the XML document.

503

          * @param start The start position in the array.

504

          * @param length The number of characters to read from the array.

505

          * @exception org.xml.sax.SAXException Any SAX exception, possibly

506

          *            wrapping another exception.

507

          * @see #ignorableWhitespace

508

          * @see org.xml.sax.Locator

509

          */

510

         public void characters(char ch[], int start, <span class="keyword">int length) throws SAXException {

511

1820

             contentHandler.characters(ch, start, length);

512

1820

         }

513

514

         /**

515

          * Receive notification of ignorable whitespace in element content.

516

          *

517

          * <p>Validating Parsers must use this method to report each chunk

518

          * of whitespace in element content (see the W3C XML 1.0 recommendation,

519

          * section 2.10): non-validating parsers may also use this method

520

          * if they are capable of parsing and using content models.</p>

521

          *

522

          * <p>SAX parsers may return all contiguous whitespace in a single

523

          * chunk, or they may split it into several chunks; however, all of

524

          * the characters in any single event must come from the same

525

          * external entity, so that the Locator provides useful

526

          * information.</p>

527

          *

528

          * <p>The application must not attempt to read from the array

529

          * outside of the specified range.</p>

530

          *

531

          * @param ch The characters from the XML document.

532

          * @param start The start position in the array.

533

          * @param length The number of characters to read from the array.

534

          * @exception org.xml.sax.SAXException Any SAX exception, possibly

535

          *            wrapping another exception.

536

          * @see #characters

537

          */

538

         public void ignorableWhitespace(char ch[], int start, <span class="keyword">int length)

539

             throws SAXException {

540

0

             contentHandler.ignorableWhitespace(ch, start, length);

541

0

         }

542

543

         /**

544

          * Receive notification of a processing instruction.

545

          *

546

          * <p>The Parser will invoke this method once for each processing

547

          * instruction found: note that processing instructions may occur

548

          * before or after the main document element.</p>

549

          *

550

          * <p>A SAX parser must never report an XML declaration (XML 1.0,

551

          * section 2.8) or a text declaration (XML 1.0, section 4.3.1)

552

          * using this method.</p>

553

          *

554

          * <p>Like {@link #characters characters()}, processing instruction

555

          * data may have characters that need more than one <code>char</code>

556

          * value. </p>

557

          *

558

          * @param target The processing instruction target.

559

          * @param data The processing instruction data, or null if

560

          *        none was supplied.  The data does not include any

561

          *        whitespace separating it from the target.

562

          * @exception org.xml.sax.SAXException Any SAX exception, possibly

563

          *            wrapping another exception.

564

          */

565

         public void processingInstruction(String target, String data)

566

             throws SAXException {

567

0

             contentHandler.processingInstruction(target, data);

568

0

         }

569

570

         /**

571

          * Receive notification of a skipped entity.

572

          * This is not called for entity references within markup constructs

573

          * such as element start tags or markup declarations.  (The XML

574

          * recommendation requires reporting skipped external entities.

575

          * SAX also reports internal entity expansion/non-expansion, except

576

          * within markup constructs.)

577

          *

578

          * <p>The Parser will invoke this method each time the entity is

579

          * skipped.  Non-validating processors may skip entities if they

580

          * have not seen the declarations (because, for example, the

581

          * entity was declared in an external DTD subset).  All processors

582

          * may skip external entities, depending on the values of the

583

          * <code>http://xml.org/sax/features/external-general-entities</code>

584

          * and the

585

          * <code>http://xml.org/sax/features/external-parameter-entities</code>

586

          * properties.</p>

587

          *

588

          * @param name The name of the skipped entity.  If it is a

589

          *        parameter entity, the name will begin with '%', and if

590

          *        it is the external DTD subset, it will be the string

591

          *        "[dtd]".

592

          * @exception org.xml.sax.SAXException Any SAX exception, possibly

593

          *            wrapping another exception.

594

          */

595

         public void skippedEntity(String name) throws SAXException {

596

0

             contentHandler.skippedEntity(name);

597

0

         }

598

599

600

         // Lexical Handler interface

601

         //-------------------------------------------------------------------------

602

603

         /**

604

          * Report the start of DTD declarations, if any.

605

          *

606

          * <p>This method is intended to report the beginning of the

607

          * DOCTYPE declaration; if the document has no DOCTYPE declaration,

608

          * this method will not be invoked.</p>

609

          *

610

          * <p>All declarations reported through

611

          * {@link org.xml.sax.DTDHandler DTDHandler} or

612

          * {@link org.xml.sax.ext.DeclHandler DeclHandler} events must appear

613

          * between the startDTD and {@link #endDTD endDTD} events.

614

          * Declarations are assumed to belong to the internal DTD subset

615

          * unless they appear between {@link #startEntity startEntity}

616

          * and {@link #endEntity endEntity} events.  Comments and

617

          * processing instructions from the DTD should also be reported

618

          * between the startDTD and endDTD events, in their original

619

          * order of (logical) occurrence; they are not required to

620

          * appear in their correct locations relative to DTDHandler

621

          * or DeclHandler events, however.</p>

622

          *

623

          * <p>Note that the start/endDTD events will appear within

624

          * the start/endDocument events from ContentHandler and

625

          * before the first

626

          * {@link org.xml.sax.ContentHandler#startElement startElement}

627

          * event.</p>

628

          *

629

          * @param name The document type name.

630

          * @param publicId The declared public identifier for the

631

          *        external DTD subset, or null if none was declared.

632

          * @param systemId The declared system identifier for the

633

          *        external DTD subset, or null if none was declared.

634

          *        (Note that this is not resolved against the document

635

          *        base URI.)

636

          * @exception SAXException The application may raise an

637

          *            exception.

638

          * @see #endDTD

639

          * @see #startEntity

640

          */

641

         public void startDTD(String name, String <span class="keyword">publicId, String systemId)

642

             throws SAXException {

643

0

             if (lexicalHandler != null) {

644

0

                 lexicalHandler.startDTD(name, publicId, systemId);

645

             }

646

0

         }

647

648

         /**

649

          * Report the end of DTD declarations.

650

          *

651

          * <p>This method is intended to report the end of the

652

          * DOCTYPE declaration; if the document has no DOCTYPE declaration,

653

          * this method will not be invoked.</p>

654

          *

655

          * @exception SAXException The application may raise an exception.

656

          * @see #startDTD

657

          */

658

         public void endDTD() throws SAXException {

659

0

             if (lexicalHandler != null) {

660

0

                 lexicalHandler.endDTD();

661

             }

662

0

         }

663

664

         /**

665

          * Report the beginning of some internal and external XML entities.

666

          *

667

          * <p>The reporting of parameter entities (including

668

          * the external DTD subset) is optional, and SAX2 drivers that

669

          * report LexicalHandler events may not implement it; you can use the

670

          * <code

671

          * >http://xml.org/sax/features/lexical-handler/parameter-entities</code>

672

          * feature to query or control the reporting of parameter entities.</p>

673

          *

674

          * <p>General entities are reported with their regular names,

675

          * parameter entities have '%' prepended to their names, and

676

          * the external DTD subset has the pseudo-entity name "[dtd]".</p>

677

          *

678

          * <p>When a SAX2 driver is providing these events, all other

679

          * events must be properly nested within start/end entity

680

          * events.  There is no additional requirement that events from

681

          * {@link org.xml.sax.ext.DeclHandler DeclHandler} or

682

          * {@link org.xml.sax.DTDHandler DTDHandler} be properly ordered.</p>

683

          *

684

          * <p>Note that skipped entities will be reported through the

685

          * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}

686

          * event, which is part of the ContentHandler interface.</p>

687

          *

688

          * <p>Because of the streaming event model that SAX uses, some

689

          * entity boundaries cannot be reported under any

690

          * circumstances:</p>

691

          *

692

          * <ul>

693

          * <li>general entities within attribute values</li>

694

          * <li>parameter entities within declarations</li>

695

          * </ul>

696

          *

697

          * <p>These will be silently expanded, with no indication of where

698

          * the original entity boundaries were.</p>

699

          *

700

          * <p>Note also that the boundaries of character references (which

701

          * are not really entities anyway) are not reported.</p>

702

          *

703

          * <p>All start/endEntity events must be properly nested.

704

          *

705

          * @param name The name of the entity.  If it is a parameter

706

          *        entity, the name will begin with '%', and if it is the

707

          *        external DTD subset, it will be "[dtd]".

708

          * @exception SAXException The application may raise an exception.

709

          * @see #endEntity

710

          * @see org.xml.sax.ext.DeclHandler#internalEntityDecl

711

          * @see org.xml.sax.ext.DeclHandler#externalEntityDecl

712

          */

713

         public void startEntity(String name) throws SAXException {

714

0

             if (lexicalHandler != null) {

715

0

                 lexicalHandler.startEntity(name);

716

             }

717

0

         }

718

719

         /**

720

          * Report the end of an entity.

721

          *

722

          * @param name The name of the entity that is ending.

723

          * @exception SAXException The application may raise an exception.

724

          * @see #startEntity

725

          */

726

         public void endEntity(String name) throws SAXException {

727

0

             if (lexicalHandler != null) {

728

0

                 lexicalHandler.endEntity(name);

729

             }

730

0

         }

731

732

         /**

733

          * Report the start of a CDATA section.

734

          *

735

          * <p>The contents of the CDATA section will be reported through

736

          * the regular {@link org.xml.sax.ContentHandler#characters

737

          * characters} event; this event is intended only to report

738

          * the boundary.</p>

739

          *

740

          * @exception SAXException The application may raise an exception.

741

          * @see #endCDATA

742

          */

743

         public void startCDATA() throws SAXException {

744

0

             if (lexicalHandler != null) {

745

0

                 lexicalHandler.startCDATA();

746

             }

747

0

         }

748

749

         /**

750

          * Report the end of a CDATA section.

751

          *

752

          * @exception SAXException The application may raise an exception.

753

          * @see #startCDATA

754

          */

755

         public void endCDATA() throws SAXException {

756

0

             if (lexicalHandler != null) {

757

0

                 lexicalHandler.endCDATA();

758

             }

759

0

         }

760

761

         /**

762

          * Report an XML comment anywhere in the document.

763

          *

764

          * <p>This callback will be used for comments inside or outside the

765

          * document element, including comments in the external DTD

766

          * subset (if read).  Comments in the DTD must be properly

767

          * nested inside start/endDTD and start/endEntity events (if

768

          * used).</p>

769

          *

770

          * @param ch An array holding the characters in the comment.

771

          * @param start The starting position in the array.

772

          * @param length The number of characters to use from the array.

773

          * @exception SAXException The application may raise an exception.

774

          */

775

         public void comment(char ch[], int start, <span class="keyword">int length) throws SAXException {

776

0

             if (lexicalHandler != null) {

777

0

                 lexicalHandler.comment(ch, start, length);

778

             }

779

0

         }

780

781

         /** Pass data through the pipline.

782

           * By default, this call is ignored.

783

           * Subclasses are invited to use this as a way for children tags to

784

           * pass data to their parent.

785

           *

786

           * @param object the data to pass

787

           * @exception SAXException The application may raise an exception.

788

           */

789

         public void objectData(Object object) throws SAXException {

790

520

             if(contentHandler instanceof XMLOutput)

791

0

                 ((XMLOutput) contentHandler).objectData(object);

792

             else {

793

520

                 if(object!=null) {

794

520

                     String output=object.toString();

795

520

                     write(output);

796

520

                 } else {

797

                     // we could have a "configurable null-toString"...

798

0

                     write("null");

799

                 }

800

             }

801

520

         }

802

803

         // Properties

804

         //-------------------------------------------------------------------------

805

         /**

806

          * @return the SAX ContentHandler to use to pipe SAX events into

807

          */

808

         public ContentHandler getContentHandler() {

809

78

             return contentHandler;

810

         }

811

812

         /**

813

          * Sets the SAX ContentHandler to pipe SAX events into

814

          *

815

          * @param contentHandler is the new ContentHandler to use.

816

          *      This value cannot be null.

817

          */

818

         public void setContentHandler(ContentHandler contentHandler) {

819

975

             if (contentHandler == null) {

820

0

                 throw new NullPointerException("ContentHandler cannot be null!");

821

             }

822

975

             this.contentHandler = contentHandler;

823

975

         }

824

825

         /**

826

          * @return the SAX LexicalHandler to use to pipe SAX events into

827

          */

828

         public LexicalHandler getLexicalHandler() {

829

0

             return lexicalHandler;

830

         }

831

832

         /**

833

          * Sets the SAX LexicalHandler to pipe SAX events into

834

          *

835

          * @param lexicalHandler is the new LexicalHandler to use.

836

          *      This value can be null.

837

          */

838

         public void setLexicalHandler(LexicalHandler lexicalHandler) {

839

897

             this.lexicalHandler = lexicalHandler;

840

897

         }

841

842

         // Implementation methods

843

         //-------------------------------------------------------------------------

844

         /**

845

          * Factory method to create a new XMLOutput from an XMLWriter

846

          */

847

         protected static XMLOutput createXMLOutput(final XMLWriter xmlWriter) {

848

819

             XMLOutput answer = new XMLOutput() {

849

                 public void close() throws IOException {

850

                     xmlWriter.close();

851

                 }

852

             };

853

819

             answer.setContentHandler(xmlWriter);

854

819

             answer.setLexicalHandler(xmlWriter);

855

819

             return answer;

856

         }

857

858

     }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.