1 /* |
|
2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: File Reader for DTD Files. Filters out UTF-8 and 16 byte order |
|
15 * marks. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 package com.nokia.tools.themeinstaller.xmlparser; |
|
21 |
|
22 import java.io.ByteArrayInputStream; |
|
23 import java.io.File; |
|
24 import java.io.FileInputStream; |
|
25 import java.io.FileNotFoundException; |
|
26 import java.io.FileReader; |
|
27 import java.io.IOException; |
|
28 import java.io.Reader; |
|
29 import java.util.Arrays; |
|
30 |
|
31 import org.xml.sax.InputSource; |
|
32 |
|
33 import com.nokia.tools.themeinstaller.installationmanager.InstallationManager; |
|
34 |
|
35 /** |
|
36 * File Reader for DTD Files. Filters out UTF-8 and 16 byte order marks. Byte |
|
37 * order marks need to be filtered because FileReader can not tolerate BOMs. |
|
38 */ |
|
39 public class DTDInputSource extends InputSource { |
|
40 |
|
41 // CONSTANTS |
|
42 private final static int BUFFER_LENGTH = 3; |
|
43 private final static byte[] BOM_UTF8 = { (byte) 0xEF, (byte) 0xBB, |
|
44 (byte) 0xBF }; |
|
45 private final static byte[] BOM_UTF16_BIG = { (byte) 0xFE, (byte) 0xFF }; |
|
46 private final static byte[] BOM_UTF16_LIT = { (byte) 0xFF, (byte) 0xFE }; |
|
47 |
|
48 // DTD File name |
|
49 private String iFileName; |
|
50 |
|
51 /** |
|
52 * Constructor. |
|
53 * |
|
54 * @param aFileName |
|
55 * DTD file name |
|
56 * @throws FileNotFoundException |
|
57 * if the file can not be found |
|
58 */ |
|
59 public DTDInputSource(String aFileName) throws FileNotFoundException { |
|
60 super( new FileReader( aFileName ) ); |
|
61 try { |
|
62 preprocess(aFileName); |
|
63 } catch (IOException e) { |
|
64 e.printStackTrace(); |
|
65 } |
|
66 iFileName = aFileName; |
|
67 } |
|
68 |
|
69 /** |
|
70 * XML-DTD files should not contain invalid entity references. For example, |
|
71 * %N; is valid while %N is not. This method will validate and correct such |
|
72 * instances. Note: This was introduced because of a defect found in loc to |
|
73 * dtd converter tool. Once loc-dtd tool works fine, this step will not be |
|
74 * required. |
|
75 * |
|
76 * @param fileName |
|
77 * the dtd file that needs correction. |
|
78 * @throws IOException |
|
79 */ |
|
80 private void preprocess(String fileName) throws IOException { |
|
81 |
|
82 |
|
83 /** |
|
84 * We won't use this parameter as of now. If required, use |
|
85 * boolean fixDTD = InstallationManager.isFixDTD(); |
|
86 * We may remove this if we find no use in future. |
|
87 */ |
|
88 boolean fixDTD = true; |
|
89 if (!fixDTD) { |
|
90 this.setCharacterStream(new FileReader(fileName)); |
|
91 return; |
|
92 } |
|
93 long fileLen = (new File(fileName)).length(); |
|
94 byte[] fileContents = new byte[(int) fileLen]; |
|
95 FileInputStream fis = new FileInputStream(fileName); |
|
96 fis.read(fileContents); |
|
97 fis.close(); |
|
98 |
|
99 String fileContentsString = new String(fileContents); |
|
100 fileContentsString = fileContentsString.replace("(%N)", "(%N;)"); |
|
101 fileContentsString = fileContentsString.replace("(%U)", " (%U;)"); |
|
102 fileContentsString = fileContentsString.replace("%0U;", "%U;"); |
|
103 fileContentsString = fileContentsString.replace("%U(", "%U;("); |
|
104 fileContentsString = fileContentsString.replace("%0U(", "%U;("); |
|
105 fileContentsString = fileContentsString.replace("%U%N;", "%U;%N;"); |
|
106 fileContentsString = fileContentsString.replace("%U%N", "%U;%N;"); |
|
107 |
|
108 setByteStream(new ByteArrayInputStream(fileContentsString.getBytes())); |
|
109 } |
|
110 |
|
111 /* |
|
112 * (non-Javadoc) |
|
113 * |
|
114 * @see org.xml.sax.InputSource#getCharacterStream() |
|
115 */ |
|
116 public Reader getCharacterStream() { |
|
117 // Get the reader from the base class |
|
118 Reader reader = super.getCharacterStream(); |
|
119 |
|
120 // Read the beginning of the file to get the BOM |
|
121 byte[] buffer = new byte[BUFFER_LENGTH]; |
|
122 try { |
|
123 // Read 3 bytes |
|
124 for (int i = 0; i < buffer.length; i++) { |
|
125 buffer[i] = (byte) reader.read(); |
|
126 } |
|
127 |
|
128 int skip = 0; |
|
129 |
|
130 // UTF-8 byte order mark (length 3 bytes) |
|
131 if (Arrays.equals(BOM_UTF8, buffer)) { |
|
132 skip = BOM_UTF8.length; |
|
133 } |
|
134 // UTF-16 byte order mark (length 2 bytes) |
|
135 else { |
|
136 byte[] compareBuffer = new byte[BOM_UTF16_BIG.length]; |
|
137 System.arraycopy(buffer, 0, compareBuffer, 0, |
|
138 compareBuffer.length); |
|
139 |
|
140 // Big and little endian |
|
141 if (Arrays.equals(BOM_UTF16_BIG, compareBuffer) |
|
142 || Arrays.equals(BOM_UTF16_LIT, compareBuffer)) { |
|
143 skip = BOM_UTF16_BIG.length; |
|
144 } |
|
145 } |
|
146 |
|
147 // Reset not supported, a new reader must be created |
|
148 FileReader fr = new FileReader(iFileName); |
|
149 fr.skip(skip); |
|
150 |
|
151 // Close the old reader |
|
152 reader.close(); |
|
153 |
|
154 // Set the new reader back to the super class |
|
155 super.setCharacterStream(fr); |
|
156 } catch (Exception e) { |
|
157 // Ignore errors, original (unfiltered) stream will be returned |
|
158 } |
|
159 |
|
160 return super.getCharacterStream(); |
|
161 } |
|
162 |
|
163 } |
|