themeinstaller/source/src/com/nokia/tools/themeinstaller/xmlparser/DTDInputSource.java
branchRCL_3
changeset 18 04b7640f6fb5
parent 0 05da4621cfb2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/themeinstaller/source/src/com/nokia/tools/themeinstaller/xmlparser/DTDInputSource.java	Wed Sep 01 12:32:13 2010 +0100
@@ -0,0 +1,163 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  File Reader for DTD Files. Filters out UTF-8 and 16 byte order
+ *                marks.
+ *
+*/
+
+
+package com.nokia.tools.themeinstaller.xmlparser;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Arrays;
+
+import org.xml.sax.InputSource;
+
+import com.nokia.tools.themeinstaller.installationmanager.InstallationManager;
+
+/**
+ * File Reader for DTD Files. Filters out UTF-8 and 16 byte order marks. Byte
+ * order marks need to be filtered because FileReader can not tolerate BOMs.
+ */
+public class DTDInputSource extends InputSource {
+
+	// CONSTANTS
+	private final static int BUFFER_LENGTH = 3;
+	private final static byte[] BOM_UTF8 = { (byte) 0xEF, (byte) 0xBB,
+			(byte) 0xBF };
+	private final static byte[] BOM_UTF16_BIG = { (byte) 0xFE, (byte) 0xFF };
+	private final static byte[] BOM_UTF16_LIT = { (byte) 0xFF, (byte) 0xFE };
+
+	// DTD File name
+	private String iFileName;
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param aFileName
+	 *            DTD file name
+	 * @throws FileNotFoundException
+	 *             if the file can not be found
+	 */
+	public DTDInputSource(String aFileName) throws FileNotFoundException {
+		super( new FileReader( aFileName ) );
+		try {
+			preprocess(aFileName);
+		} catch (IOException e) {			
+			e.printStackTrace();
+		}
+		iFileName = aFileName;
+	}
+
+	/**
+	 * XML-DTD files should not contain invalid entity references. For example,
+	 * %N; is valid while %N is not. This method will validate and correct such
+	 * instances. Note: This was introduced because of a defect found in loc to
+	 * dtd converter tool. Once loc-dtd tool works fine, this step will not be
+	 * required.
+	 * 
+	 * @param fileName
+	 *            the dtd file that needs correction.
+	 * @throws IOException
+	 */
+	private void preprocess(String fileName) throws IOException {
+
+		
+		/**
+		 * We won't use this parameter as of now. If required, use
+		 * boolean fixDTD = InstallationManager.isFixDTD();
+		 * We may remove this if we find no use in future.
+		 */
+		boolean fixDTD = true;
+		if (!fixDTD) {
+			this.setCharacterStream(new FileReader(fileName));
+			return;
+		}
+		long fileLen = (new File(fileName)).length();
+		byte[] fileContents = new byte[(int) fileLen];
+		FileInputStream fis = new FileInputStream(fileName);
+		fis.read(fileContents);
+		fis.close();
+
+		String fileContentsString = new String(fileContents);
+		fileContentsString = fileContentsString.replace("(%N)", "(%N;)");
+		fileContentsString = fileContentsString.replace("(%U)", " (%U;)");
+		fileContentsString = fileContentsString.replace("%0U;", "%U;");
+		fileContentsString = fileContentsString.replace("%U(", "%U;(");
+		fileContentsString = fileContentsString.replace("%0U(", "%U;(");
+		fileContentsString = fileContentsString.replace("%U%N;", "%U;%N;");
+		fileContentsString = fileContentsString.replace("%U%N", "%U;%N;");
+
+		setByteStream(new ByteArrayInputStream(fileContentsString.getBytes()));
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.xml.sax.InputSource#getCharacterStream()
+	 */
+	public Reader getCharacterStream() {
+		// Get the reader from the base class
+		Reader reader = super.getCharacterStream();
+
+		// Read the beginning of the file to get the BOM
+		byte[] buffer = new byte[BUFFER_LENGTH];
+		try {
+			// Read 3 bytes
+			for (int i = 0; i < buffer.length; i++) {
+				buffer[i] = (byte) reader.read();
+			}
+
+			int skip = 0;
+
+			// UTF-8 byte order mark (length 3 bytes)
+			if (Arrays.equals(BOM_UTF8, buffer)) {
+				skip = BOM_UTF8.length;
+			}
+			// UTF-16 byte order mark (length 2 bytes)
+			else {
+				byte[] compareBuffer = new byte[BOM_UTF16_BIG.length];
+				System.arraycopy(buffer, 0, compareBuffer, 0,
+						compareBuffer.length);
+
+				// Big and little endian
+				if (Arrays.equals(BOM_UTF16_BIG, compareBuffer)
+						|| Arrays.equals(BOM_UTF16_LIT, compareBuffer)) {
+					skip = BOM_UTF16_BIG.length;
+				}
+			}
+
+			// Reset not supported, a new reader must be created
+			FileReader fr = new FileReader(iFileName);
+			fr.skip(skip);
+
+			// Close the old reader
+			reader.close();
+
+			// Set the new reader back to the super class
+			super.setCharacterStream(fr);
+		} catch (Exception e) {
+			// Ignore errors, original (unfiltered) stream will be returned
+		}
+
+		return super.getCharacterStream();
+	}
+
+}