Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 251748
Collapse All | Expand All

(-)src/org/eclipse/core/internal/content/XMLContentDescriber.java (-45 / +35 lines)
Lines 30-35 Link Here
30
	private static final QualifiedName[] SUPPORTED_OPTIONS = new QualifiedName[] {IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK};
30
	private static final QualifiedName[] SUPPORTED_OPTIONS = new QualifiedName[] {IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK};
31
	private static final String ENCODING = "encoding="; //$NON-NLS-1$
31
	private static final String ENCODING = "encoding="; //$NON-NLS-1$
32
	private static final String XML_PREFIX = "<?xml "; //$NON-NLS-1$
32
	private static final String XML_PREFIX = "<?xml "; //$NON-NLS-1$
33
	private static final String XML_DECL_END = "?>"; //$NON-NLS-1$
33
34
34
	public int describe(InputStream input, IContentDescription description) throws IOException {
35
	public int describe(InputStream input, IContentDescription description) throws IOException {
35
		byte[] bom = getByteOrderMark(input);
36
		byte[] bom = getByteOrderMark(input);
Lines 37-96 Link Here
37
		input.reset();
38
		input.reset();
38
		if (bom != null) {
39
		if (bom != null) {
39
			if (bom == IContentDescription.BOM_UTF_16BE)
40
			if (bom == IContentDescription.BOM_UTF_16BE)
40
				xmlDeclEncoding = "UTF-16BE"; //$NON-NLS-1$
41
				xmlDeclEncoding = "UTF-16";//BE"; //$NON-NLS-1$
41
			else if (bom == IContentDescription.BOM_UTF_16LE)
42
			else if (bom == IContentDescription.BOM_UTF_16LE)
42
				xmlDeclEncoding = "UTF-16LE"; //$NON-NLS-1$
43
				xmlDeclEncoding = "UTF-16";//LE"; //$NON-NLS-1$
43
			// skip BOM to make comparison simpler
44
			// skip BOM to make comparison simpler
44
			input.skip(bom.length);
45
			input.skip(bom.length);
45
			// set the BOM in the description if requested
46
			// set the BOM in the description if requested
46
			if (description != null && description.isRequested(IContentDescription.BYTE_ORDER_MARK))
47
			if (description != null && description.isRequested(IContentDescription.BYTE_ORDER_MARK))
47
				description.setProperty(IContentDescription.BYTE_ORDER_MARK, bom);
48
				description.setProperty(IContentDescription.BYTE_ORDER_MARK, bom);
48
		}
49
		}
49
		byte[] xmlPrefixBytes = XML_PREFIX.getBytes(xmlDeclEncoding);
50
		return internalDescribe(new InputStreamReader(input, xmlDeclEncoding), description);
50
		byte[] prefix = new byte[xmlPrefixBytes.length];
51
		if (input.read(prefix) < prefix.length)
52
			// there is not enough info to say anything
53
			return INDETERMINATE;
54
		for (int i = 0; i < prefix.length; i++)
55
			if (prefix[i] != xmlPrefixBytes[i])
56
				// we don't have a XMLDecl... there is not enough info to say anything
57
				return INDETERMINATE;
58
		if (description == null)
59
			return VALID;
60
		// describe charset if requested
61
		if (description.isRequested(IContentDescription.CHARSET)) {
62
			String fullXMLDecl = readFullXMLDecl(input, xmlDeclEncoding);
63
			if (fullXMLDecl != null) {
64
				String charset = getCharset(fullXMLDecl);
65
				if (charset != null && !isCharsetValid(charset))
66
					return INVALID;
67
				if (charset != null && !charset.matches("[uU][tT][fF](-)?8")) //$NON-NLS-1$
68
					// only set property if value is not default (avoid using a non-default content description)
69
					description.setProperty(IContentDescription.CHARSET, charset);
70
				if (charset == null || !charset.matches("[uU][tT][fF](-)?(8|16)"))
71
					description.setProperty(IContentDescription.BYTE_ORDER_MARK, null);
72
			}
73
		}
74
		return VALID;
75
	}
51
	}
76
	
52
	
77
	private boolean isCharsetValid(String charset){
53
	public int describe(Reader input, IContentDescription description) throws IOException {	
78
		return charset.matches("[A-Za-z]([A-Za-z0-9._\\-])*");
54
		return internalDescribe(input, description);
79
	}
80
81
	private String readFullXMLDecl(InputStream input, String unicodeEncoding) throws IOException {
82
		byte[] xmlDecl = new byte[100];
83
		int c = 0;
84
		// looks for XMLDecl ending char (?)
85
		int read = 0;
86
		while (read < xmlDecl.length && (c = input.read()) != -1 && c !='\r' && c !='\n')
87
			xmlDecl[read++] = (byte) c;
88
		return new String(xmlDecl, 0, read, unicodeEncoding);
89
	}
55
	}
90
56
	
91
	public int describe(Reader input, IContentDescription description) throws IOException {
57
	private int internalDescribe(Reader input, IContentDescription description) throws IOException {	
92
		BufferedReader reader = new BufferedReader(input);
58
		String line = readXMLDecl(input);
93
		String line = reader.readLine();
59
		
94
		// end of stream
60
		// end of stream
95
		if (line == null)
61
		if (line == null)
96
			return INDETERMINATE;
62
			return INDETERMINATE;
Lines 109-114 Link Here
109
				description.setProperty(IContentDescription.CHARSET, charset);
75
				description.setProperty(IContentDescription.CHARSET, charset);
110
		}
76
		}
111
		return VALID;
77
		return VALID;
78
	} 
79
	
80
	private boolean isFullXMLDecl(String xmlDecl) {
81
		return xmlDecl.endsWith(XML_DECL_END);
82
	}
83
84
	private String readXMLDecl(Reader input) throws IOException {
85
		BufferedReader reader = new BufferedReader(input);
86
		StringBuffer buffer = new StringBuffer();
87
		String line = null;
88
89
		while (buffer.length() < 100 && ((line = reader.readLine()) != null)) {
90
			buffer.append(line);
91
			if (line.indexOf(XML_DECL_END) != -1) {
92
				return buffer.substring(0, buffer.indexOf(XML_DECL_END) + XML_DECL_END.length());
93
			}
94
		}
95
		return buffer.toString();
112
	}
96
	}
113
97
114
	private String getCharset(String firstLine) {
98
	private String getCharset(String firstLine) {
Lines 124-134 Link Here
124
		if (firstQuote == -1 || firstLine.length() == firstQuote - 1)
108
		if (firstQuote == -1 || firstLine.length() == firstQuote - 1)
125
			return null;
109
			return null;
126
		int secondQuote = firstLine.indexOf(quoteChar, firstQuote + 1);
110
		int secondQuote = firstLine.indexOf(quoteChar, firstQuote + 1);
127
		if (secondQuote == -1)
111
		if (secondQuote == -1 && !isFullXMLDecl(firstLine))
128
			return null;
112
			return null;
113
		else if (secondQuote == -1 && isFullXMLDecl(firstLine))
114
			return firstLine.substring(firstQuote + 1);
129
		return firstLine.substring(firstQuote + 1, secondQuote);
115
		return firstLine.substring(firstQuote + 1, secondQuote);
130
	}
116
	}
131
117
118
	private boolean isCharsetValid(String charset) {
119
		return charset.matches("[A-Za-z]([A-Za-z0-9._\\-])*");
120
	}
121
132
	public QualifiedName[] getSupportedOptions() {
122
	public QualifiedName[] getSupportedOptions() {
133
		return SUPPORTED_OPTIONS;
123
		return SUPPORTED_OPTIONS;
134
	}
124
	}
(-)src/org/eclipse/core/tests/runtime/content/XMLContentDescriberTest.java (-11 / +41 lines)
Lines 45-66 Link Here
45
45
46
		checkEncodedContents(ENCODING_NOTSUPPORTED, ENCODING_NOTSUPPORTED, ENCODING_UTF8);
46
		checkEncodedContents(ENCODING_NOTSUPPORTED, ENCODING_NOTSUPPORTED, ENCODING_UTF8);
47
		checkEncodedContents(ENCODING_NOTSUPPORTED, ENCODING_NOTSUPPORTED, ENCODING_UTF16);
47
		checkEncodedContents(ENCODING_NOTSUPPORTED, ENCODING_NOTSUPPORTED, ENCODING_UTF16);
48
49
		checkEncodedContents(ENCODING_UTF16, ENCODING_UTF16, ENCODING_UTF16, true);
50
		checkEncodedContents(ENCODING_UTF8, ENCODING_UTF8, ENCODING_UTF8, true);
51
52
		checkEncodedContents(ENCODING_UTF16, ENCODING_UTF16, ENCODING_UTF8, true);
53
		checkEncodedContents(ENCODING_UTF8, ENCODING_UTF8, ENCODING_UTF16, true);
54
55
		checkEncodedContents(ENCODING_NOTSUPPORTED, ENCODING_NOTSUPPORTED, ENCODING_UTF8, true);
56
		checkEncodedContents(ENCODING_NOTSUPPORTED, ENCODING_NOTSUPPORTED, ENCODING_UTF16, true);
48
	}
57
	}
49
58
50
	public void testEncodedContents2() throws Exception {
59
	public void testEncodedContents2() throws Exception {
51
		checkEncodedContents2(ENCODING_UTF16, ENCODING_UTF16);
60
		checkEncodedContents2(ENCODING_UTF16, ENCODING_UTF16);
52
		checkEncodedContents2(ENCODING_UTF8, ENCODING_UTF8);
61
		checkEncodedContents2(ENCODING_UTF8, ENCODING_UTF8);
53
		checkEncodedContents2(ENCODING_NOTSUPPORTED, ENCODING_NOTSUPPORTED);
62
		checkEncodedContents2(ENCODING_NOTSUPPORTED, ENCODING_NOTSUPPORTED);
63
64
		checkEncodedContents2(ENCODING_UTF16, ENCODING_UTF16, true);
65
		checkEncodedContents2(ENCODING_UTF8, ENCODING_UTF8, true);
66
		checkEncodedContents2(ENCODING_NOTSUPPORTED, ENCODING_NOTSUPPORTED, true);
54
	}
67
	}
55
68
56
	public void testEncodedContents3() throws Exception {
69
	public void testEncodedContents3() throws Exception {
57
		IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(getInputStream(ENCODING_INCORRECT, ENCODING_UTF8), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
70
		IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(getInputStream(ENCODING_INCORRECT, ENCODING_UTF8, false), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
71
		assertNull("1.0", description);
72
73
		description = Platform.getContentTypeManager().getDescriptionFor(getInputStream(ENCODING_INCORRECT, ENCODING_UTF16, false), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
74
		assertNull("2.0", description);
75
76
		description = Platform.getContentTypeManager().getDescriptionFor(getReader(ENCODING_INCORRECT, false), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
77
		assertNull("3.0", description);
78
79
		description = Platform.getContentTypeManager().getDescriptionFor(getInputStream(ENCODING_INCORRECT, ENCODING_UTF8, true), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
58
		assertNull("1.0", description);
80
		assertNull("1.0", description);
59
81
60
		description = Platform.getContentTypeManager().getDescriptionFor(getInputStream(ENCODING_INCORRECT, ENCODING_UTF16), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
82
		description = Platform.getContentTypeManager().getDescriptionFor(getInputStream(ENCODING_INCORRECT, ENCODING_UTF16, true), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
61
		assertNull("2.0", description);
83
		assertNull("2.0", description);
62
84
63
		description = Platform.getContentTypeManager().getDescriptionFor(getReader(ENCODING_INCORRECT), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
85
		description = Platform.getContentTypeManager().getDescriptionFor(getReader(ENCODING_INCORRECT, true), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
64
		assertNull("3.0", description);
86
		assertNull("3.0", description);
65
	}
87
	}
66
88
Lines 68-94 Link Here
68
		return new TestSuite(XMLContentDescriberTest.class);
90
		return new TestSuite(XMLContentDescriberTest.class);
69
	}
91
	}
70
92
71
	private void checkEncodedContents(String resultEncoding, String encodingInContent, String encoding) throws Exception {
93
	private void checkEncodedContents(String resultEncoding, String encodingInContent, String encoding, boolean encInNewLine) throws Exception {
72
		IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(getInputStream(encodingInContent, encoding), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
94
		IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(getInputStream(encodingInContent, encoding, encInNewLine), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
73
		assertNotNull("1.0", description);
95
		assertNotNull("1.0", description);
74
		assertEquals("1.1", Platform.PI_RUNTIME + ".xml", description.getContentType().getId());
96
		assertEquals("1.1", Platform.PI_RUNTIME + ".xml", description.getContentType().getId());
75
		assertEquals("1.2", resultEncoding, description.getProperty(IContentDescription.CHARSET));
97
		assertEquals("1.2", resultEncoding, description.getProperty(IContentDescription.CHARSET));
76
	}
98
	}
77
99
78
	private void checkEncodedContents2(String resultEncoding, String encodingInContent) throws Exception {
100
	private void checkEncodedContents(String resultEncoding, String encodingInContent, String encoding) throws Exception {
79
		IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(getReader(encodingInContent), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
101
		checkEncodedContents(resultEncoding, encodingInContent, encoding, false);
102
	}
103
104
	private void checkEncodedContents2(String resultEncoding, String encodingInContent, boolean encInNewLine) throws Exception {
105
		IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(getReader(encodingInContent, encInNewLine), "fake.xml", new QualifiedName[] {IContentDescription.CHARSET});
80
		assertNotNull("2.0", description);
106
		assertNotNull("2.0", description);
81
		assertEquals("2.1", Platform.PI_RUNTIME + ".xml", description.getContentType().getId());
107
		assertEquals("2.1", Platform.PI_RUNTIME + ".xml", description.getContentType().getId());
82
		assertEquals("2.2", resultEncoding, description.getProperty(IContentDescription.CHARSET));
108
		assertEquals("2.2", resultEncoding, description.getProperty(IContentDescription.CHARSET));
83
	}
109
	}
84
110
85
	private InputStream getInputStream(String encodingInContent, String encoding) throws UnsupportedEncodingException {
111
	private void checkEncodedContents2(String resultEncoding, String encodingInContent) throws Exception {
86
		String content = "<?xml version=\"1.0\" encoding=\"" + encodingInContent + "\"?><root attribute=\"" + ENCODED_TEXT + "\">";
112
		checkEncodedContents2(resultEncoding, encodingInContent, false);
113
	}
114
115
	private InputStream getInputStream(String encodingInContent, String encoding, boolean encInNewLine) throws UnsupportedEncodingException {
116
		String content = "<?xml version=\"1.0\"" + (encInNewLine ? "\n" : "") + "encoding=\"" + encodingInContent + "\"?><root attribute=\"" + ENCODED_TEXT + "\">";
87
		return new ByteArrayInputStream(content.getBytes(encoding));
117
		return new ByteArrayInputStream(content.getBytes(encoding));
88
	}
118
	}
89
119
90
	private Reader getReader(String encodingInContent) {
120
	private Reader getReader(String encodingInContent, boolean encInNewLine) {
91
		String content = "<?xml version=\"1.0\" encoding=\"" + encodingInContent + "\"?><root attribute=\"" + ENCODED_TEXT + "\">";
121
		String content = "<?xml version=\"1.0\"" + (encInNewLine ? "\n" : "") + " encoding=\"" + encodingInContent + "\"?><root attribute=\"" + ENCODED_TEXT + "\">";
92
		return new InputStreamReader(new ByteArrayInputStream(content.getBytes()));
122
		return new InputStreamReader(new ByteArrayInputStream(content.getBytes()));
93
	}
123
	}
94
}
124
}

Return to bug 251748