1 /*******************************************************************************
2  * Copyright (c) 2004, 2018 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Mickael Istria (Red Hat Inc.) - [263316] regexp for file association
14  *******************************************************************************/
15 package org.eclipse.core.tests.resources.content;
16 
17 import static org.eclipse.core.tests.resources.AutomatedTests.PI_RESOURCES_TESTS;
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertNotSame;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertSame;
24 import static org.junit.Assert.assertThrows;
25 import static org.junit.Assert.assertTrue;
26 
27 import java.io.*;
28 import java.nio.charset.Charset;
29 import java.nio.charset.StandardCharsets;
30 import java.util.HashSet;
31 import java.util.Set;
32 import org.eclipse.core.internal.content.*;
33 import org.eclipse.core.runtime.*;
34 import org.eclipse.core.runtime.content.*;
35 import org.eclipse.core.runtime.content.IContentTypeManager.ContentTypeChangeEvent;
36 import org.eclipse.core.runtime.content.XMLContentDescriber;
37 import org.eclipse.core.runtime.jobs.Job;
38 import org.eclipse.core.runtime.preferences.*;
39 import org.eclipse.core.tests.harness.*;
40 import org.junit.After;
41 import org.junit.Test;
42 import org.osgi.service.prefs.BackingStoreException;
43 import org.osgi.service.prefs.Preferences;
44 
45 public class IContentTypeManagerTest extends ContentTypeTest {
46 
47 	private static class ContentTypeChangeTracer implements IContentTypeManager.IContentTypeChangeListener {
48 		private final Set<IContentType> changed = new HashSet<>();
49 
ContentTypeChangeTracer()50 		public ContentTypeChangeTracer() {
51 		}
52 
53 		@Override
contentTypeChanged(ContentTypeChangeEvent event)54 		public void contentTypeChanged(ContentTypeChangeEvent event) {
55 			changed.add(event.getContentType());
56 		}
57 
isOnlyChange(IContentType myType)58 		public boolean isOnlyChange(IContentType myType) {
59 			return changed.size() == 1 && changed.contains(myType);
60 		}
61 
reset()62 		public void reset() {
63 			changed.clear();
64 		}
65 	}
66 
67 	// XXX this is copied from CharsetDeltaJob in the resources plug-in
68 	private static final String FAMILY_CHARSET_DELTA = "org.eclipse.core.resources.charsetJobFamily";
69 
70 	private final static String MINIMAL_XML = "<?xml version=\"1.0\"?><org.eclipse.core.resources.tests.root/>";
71 	private final static String SAMPLE_BIN1_OFFSET = "12345";
72 	private final static byte[] SAMPLE_BIN1_SIGNATURE = { 0x10, (byte) 0xAB, (byte) 0xCD, (byte) 0xFF };
73 	private final static String SAMPLE_BIN2_OFFSET = "";
74 	private final static byte[] SAMPLE_BIN2_SIGNATURE = { 0x10, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF };
75 	private final static String XML_DTD_EXTERNAL_ENTITY = "<?xml version=\"1.0\"?><!DOCTYPE project  SYSTEM \"org.eclipse.core.resources.tests.some.dtd\"  [<!ENTITY someentity SYSTEM \"someentity.xml\">]><org.eclipse.core.resources.tests.root/>";
76 	private final static String XML_DTD_US_ASCII = "<?xml version=\"1.0\" encoding=\"US-ASCII\"?><!DOCTYPE sometype SYSTEM \"org.eclipse.core.resources.tests.some.dtd\"><org.eclipse.core.resources.tests.root/>";
77 	private final static String XML_ISO_8859_1 = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><org.eclipse.core.resources.tests.root/>";
78 	private final static String XML_ISO_8859_1_SINGLE_QUOTES = "<?xml version='1.0' encoding='ISO-8859-1'?><org.eclipse.core.resources.tests.root/>";
79 	private final static String XML_ROOT_ELEMENT_EXTERNAL_ENTITY = "<?xml version=\"1.0\"?><!DOCTYPE project   [<!ENTITY someentity SYSTEM \"someentity.xml\">]><org.eclipse.core.resources.tests.root-element/>";
80 	private final static String XML_ROOT_ELEMENT_EXTERNAL_ENTITY2 = "<?xml version=\"1.0\"?><!DOCTYPE org.eclipse.core.resources.tests.root-element PUBLIC \"org.eclipse.core.resources.tests.root-elementId\" \"org.eclipse.core.resources.tests.root-element.dtd\" ><org.eclipse.core.resources.tests.root-element/>";
81 	private final static String XML_ROOT_ELEMENT_ISO_8859_1 = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><org.eclipse.core.resources.tests.root-element/>";
82 	private final static String XML_ROOT_ELEMENT_NO_DECL = "<org.eclipse.core.resources.tests.root-element/>";
83 	private final static String XML_US_ASCII_INVALID = "<?xml version='1.0' encoding='us-ascii'?><!-- Non-ASCII chars: ����� --><org.eclipse.core.resources.tests.root/>";
84 	private final static String XML_UTF_16 = "<?xml version=\"1.0\" encoding=\"UTF-16\"?><org.eclipse.core.resources.tests.root/>";
85 	private final static String XML_UTF_16BE = "<?xml version=\"1.0\" encoding=\"UTF-16BE\"?><org.eclipse.core.resources.tests.root/>";
86 	private final static String XML_UTF_16LE = "<?xml version=\"1.0\" encoding=\"UTF-16LE\"?><org.eclipse.core.resources.tests.root/>";
87 	private final static String XML_UTF_8 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><org.eclipse.core.resources.tests.root/>";
88 
89 	// used also by FilePropertyTesterTest
90 	public static final String XML_ROOT_ELEMENT_NS_MATCH1 = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><prefix:rootElement1 xmlns:prefix='urn:eclipse.core.runtime.ns1'/>";
91 
92 	private static final String XML_ROOT_ELEMENT_NS_MATCH2 = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE rootElement2 SYSTEM \"org.eclipse.core.resources.tests.nothing\"><rootElement2 xmlns='urn:eclipse.core.runtime.ns2'/>";
93 	private static final String XML_ROOT_ELEMENT_NS_WRONG_ELEM = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><rootElement3 xmlns='urn:eclipse.core.runtime.ns2'/>";
94 	private static final String XML_ROOT_ELEMENT_NS_WRONG_NS = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><prefix:rootElement1 xmlns='http://example.com/'/>";
95 	private static final String XML_ROOT_ELEMENT_NS_MIXUP = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><rootElement2 xmlns='urn:eclipse.core.runtime.ns1'/>";
96 	private static final String XML_ROOT_ELEMENT_NS_WILDCARD = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><weCouldPutAnythingHere xmlns='urn:eclipse.core.runtime.nsWild'/>";
97 	private final static String XML_ROOT_ELEMENT_NS_WILDCARD2 = "<?xml version=\"1.0\" encoding=\"US-ASCII\"?><!DOCTYPE Joker SYSTEM \"org.eclipse.core.resources.tests.some.dtd3\"><Joker/>";
98 	private final static String XML_ROOT_ELEMENT_EMPTY_NS = "<?xml version=\"1.0\" encoding=\"US-ASCII\"?><!DOCTYPE Joker SYSTEM \"org.eclipse.core.resources.tests.some.dtd3\"><rootElement>";
99 
100 	/**
101 	 * Helps to ensure we don't get fooled by case sensitivity in file names/specs.
102 	 */
changeCase(String original)103 	private String changeCase(String original) {
104 		StringBuilder result = new StringBuilder(original);
105 		for (int i = result.length() - 1; i >= 0; i--) {
106 			char originalChar = original.charAt(i);
107 			result.setCharAt(i, i % 2 == 0 ? Character.toLowerCase(originalChar) : Character.toUpperCase(originalChar));
108 		}
109 		return result.toString();
110 	}
111 
contains(Object[] array, Object element)112 	boolean contains(Object[] array, Object element) {
113 		for (Object element2 : array) {
114 			if (element2.equals(element)) {
115 				return true;
116 			}
117 		}
118 		return false;
119 	}
120 
getDescriptionFor(IContentTypeMatcher finder, String contents, Charset encoding, String fileName, QualifiedName[] options, boolean text)121 	private IContentDescription getDescriptionFor(IContentTypeMatcher finder, String contents, Charset encoding,
122 			String fileName, QualifiedName[] options, boolean text) throws IOException {
123 		return text ? finder.getDescriptionFor(getReader(contents), fileName, options)
124 				: finder.getDescriptionFor(getInputStream(contents, encoding), fileName, options);
125 	}
126 
getInputStream(byte[][] contents)127 	public InputStream getInputStream(byte[][] contents) {
128 		int size = 0;
129 		// computes final array size
130 		for (byte[] content : contents) {
131 			size += content.length;
132 		}
133 		byte[] full = new byte[size];
134 		int fullIndex = 0;
135 		// concatenates all byte arrays
136 		for (byte[] content : contents) {
137 			for (byte element : content) {
138 				full[fullIndex++] = element;
139 			}
140 		}
141 		return new ByteArrayInputStream(full);
142 	}
143 
getInputStream(String contents)144 	public InputStream getInputStream(String contents) {
145 		return new ByteArrayInputStream(contents.getBytes());
146 	}
147 
getInputStream(String contents, Charset encoding)148 	public InputStream getInputStream(String contents, Charset encoding) {
149 		return new ByteArrayInputStream(encoding == null ? contents.getBytes() : contents.getBytes(encoding));
150 	}
151 
getReader(String contents)152 	public Reader getReader(String contents) {
153 		return new CharArrayReader(contents.toCharArray());
154 	}
155 
isText(IContentTypeManager manager, IContentType candidate)156 	private boolean isText(IContentTypeManager manager, IContentType candidate) {
157 		IContentType text = manager.getContentType(IContentTypeManager.CT_TEXT);
158 		return candidate.isKindOf(text);
159 	}
160 
161 	@After
tearDown()162 	public void tearDown() throws Exception {
163 		// some tests here will trigger a charset delta job (any causing
164 		// ContentTypeChangeEvents to be broadcast)
165 		// ensure none is left running after we finish
166 		Job.getJobManager().join(FAMILY_CHARSET_DELTA, new FussyProgressMonitor());
167 	}
168 
169 	/**
170 	 * This test shows how we deal with aliases.
171 	 */
172 	@Test
testAlias()173 	public void testAlias() throws IOException {
174 		final IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
175 		IContentType alias = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".alias");
176 		assertNotNull("0.7", alias);
177 		IContentType derived = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".derived-from-alias");
178 		assertNotNull("0.8", derived);
179 		IContentType target = contentTypeManager.getContentType("org.eclipse.bundle02.missing-target");
180 		assertNull("0.9", target);
181 		IContentType[] selected;
182 		selected = contentTypeManager.findContentTypesFor("foo.missing-target");
183 		assertEquals("1.1", 2, selected.length);
184 		assertEquals("1.2", alias, selected[0]);
185 		assertEquals("1.3", derived, selected[1]);
186 		selected = contentTypeManager.findContentTypesFor(getRandomContents(), "foo.missing-target");
187 		assertEquals("1.4", 2, selected.length);
188 		assertEquals("1.5", alias, selected[0]);
189 		assertEquals("1.6", derived, selected[1]);
190 
191 		// test late addition of content type
192 		TestRegistryChangeListener listener = new TestRegistryChangeListener(Platform.PI_RUNTIME,
193 				ContentTypeBuilder.PT_CONTENTTYPES, null, null);
194 		BundleTestingHelper.runWithBundles("2", () -> {
195 			IContentType alias1 = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".alias");
196 			assertNull("2.1.1", alias1);
197 			IContentType derived1 = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".derived-from-alias");
198 			assertNotNull("2.1.2", derived1);
199 			IContentType target1 = contentTypeManager.getContentType("org.eclipse.bundle02.missing-target");
200 			assertNotNull("2.1.3", target1);
201 			// checks associations
202 			IContentType[] selected1 = contentTypeManager.findContentTypesFor("foo.missing-target");
203 			assertEquals("2.2.1", 2, selected1.length);
204 			assertEquals("2.2.2", target1, selected1[0]);
205 			assertEquals("2.2.3", derived1, selected1[1]);
206 			IContentType[] selected2;
207 			try {
208 				selected2 = contentTypeManager.findContentTypesFor(getRandomContents(), "foo.missing-target");
209 			} catch (IOException e) {
210 				throw new AssertionError(e);
211 			}
212 			assertEquals("2.2.5", 2, selected2.length);
213 			assertEquals("2.2.6", target1, selected2[0]);
214 			assertEquals("2.2.7", derived1, selected2[1]);
215 		}, getContext(), new String[] { ContentTypeTest.TEST_FILES_ROOT + "content/bundle02" }, listener);
216 	}
217 
218 	@Test
testAssociationInheritance()219 	public void testAssociationInheritance() throws CoreException {
220 		IContentTypeManager manager = Platform.getContentTypeManager();
221 		IContentTypeMatcher finder = manager.getMatcher(new LocalSelectionPolicy(), null);
222 		IContentType text = manager.getContentType(Platform.PI_RUNTIME + ".text");
223 		IContentType assoc1 = manager.getContentType(PI_RESOURCES_TESTS + ".assoc1");
224 		IContentType assoc2 = manager.getContentType(PI_RESOURCES_TESTS + ".assoc2");
225 
226 		// associate a user-defined file spec
227 		text.addFileSpec("txt_useradded", IContentType.FILE_EXTENSION_SPEC);
228 		assoc1.addFileSpec("txt_assoc1useradded", IContentType.FILE_EXTENSION_SPEC);
229 		assoc2.addFileSpec("txt_assoc2useradded", IContentType.FILE_EXTENSION_SPEC);
230 
231 		// test associations
232 		assertTrue("1.1", assoc1.isAssociatedWith(changeCase("text.txt")));
233 		assertTrue("1.2", assoc1.isAssociatedWith(changeCase("text.txt_useradded")));
234 		assertTrue("1.3", assoc1.isAssociatedWith(changeCase("text.txt_pluginadded")));
235 		assertTrue("1.4", assoc1.isAssociatedWith(changeCase("text.txt_assoc1pluginadded")));
236 		assertTrue("1.5", assoc1.isAssociatedWith(changeCase("text.txt_assoc1useradded")));
237 
238 		assertFalse("2.1", assoc2.isAssociatedWith(changeCase("text.txt")));
239 		assertFalse("2.2", assoc2.isAssociatedWith(changeCase("text.txt_useradded")));
240 		assertFalse("2.3", assoc2.isAssociatedWith(changeCase("text.txt_pluginadded")));
241 		assertTrue("2.4", assoc2.isAssociatedWith(changeCase("text.txt_assoc2pluginadded")));
242 		assertTrue("2.5", assoc2.isAssociatedWith(changeCase("text.txt_assoc2builtin")));
243 		assertTrue("2.6", assoc2.isAssociatedWith(changeCase("text.txt_assoc2useradded")));
244 
245 		IContentType[] selected;
246 		// text built-in associations
247 		selected = finder.findContentTypesFor(changeCase("text.txt"));
248 		assertEquals("3.0", 2, selected.length);
249 		assertEquals("3.1", assoc1, selected[1]);
250 		assertEquals("3.2", text, selected[0]);
251 
252 		// text user-added associations
253 		selected = finder.findContentTypesFor(changeCase("text.txt_useradded"));
254 		assertEquals("4.0", 2, selected.length);
255 		assertEquals("4.1", assoc1, selected[1]);
256 		assertEquals("4.2", text, selected[0]);
257 
258 		// text provider-added associations
259 		selected = finder.findContentTypesFor(changeCase("text.txt_pluginadded"));
260 		assertEquals("5.0", 2, selected.length);
261 		assertEquals("5.1", assoc1, selected[1]);
262 		assertEquals("5.2", text, selected[0]);
263 
264 		selected = finder.findContentTypesFor(changeCase("text.txt_assoc1pluginadded"));
265 		assertEquals("6.0", 1, selected.length);
266 		assertEquals("6.1", assoc1, selected[0]);
267 
268 		selected = finder.findContentTypesFor(changeCase("text.txt_assoc1useradded"));
269 		assertEquals("7.0", 1, selected.length);
270 		assertEquals("7.1", assoc1, selected[0]);
271 
272 		selected = finder.findContentTypesFor(changeCase("text.txt_assoc2pluginadded"));
273 		assertEquals("8.0", 1, selected.length);
274 		assertEquals("8.1", assoc2, selected[0]);
275 
276 		selected = finder.findContentTypesFor(changeCase("text.txt_assoc2useradded"));
277 		assertEquals("9.0", 1, selected.length);
278 		assertEquals("9.1", assoc2, selected[0]);
279 
280 		selected = finder.findContentTypesFor(changeCase("text.txt_assoc2builtin"));
281 		assertEquals("10.0", 1, selected.length);
282 		assertEquals("10.1", assoc2, selected[0]);
283 	}
284 
285 	@Test
testAssociations()286 	public void testAssociations() throws CoreException {
287 		IContentType text = Platform.getContentTypeManager().getContentType(Platform.PI_RUNTIME + ".text");
288 
289 		// associate a user-defined file spec
290 		text.addFileSpec("txt_useradded", IContentType.FILE_EXTENSION_SPEC);
291 
292 		// test associations
293 		assertTrue("0.1", text.isAssociatedWith(changeCase("text.txt")));
294 		assertTrue("0.2", text.isAssociatedWith(changeCase("text.txt_useradded")));
295 		assertTrue("0.3", text.isAssociatedWith(changeCase("text.txt_pluginadded")));
296 
297 		// check provider defined settings
298 		String[] providerDefinedExtensions = text
299 				.getFileSpecs(IContentType.FILE_EXTENSION_SPEC | IContentType.IGNORE_USER_DEFINED);
300 		assertTrue("1.0", contains(providerDefinedExtensions, "txt"));
301 		assertFalse("1.1", contains(providerDefinedExtensions, "txt_useradded"));
302 		assertTrue("1.2", contains(providerDefinedExtensions, "txt_pluginadded"));
303 
304 		// check user defined settings
305 		String[] textUserDefinedExtensions = text
306 				.getFileSpecs(IContentType.FILE_EXTENSION_SPEC | IContentType.IGNORE_PRE_DEFINED);
307 		assertFalse("2.0", contains(textUserDefinedExtensions, "txt"));
308 		assertTrue("2.1", contains(textUserDefinedExtensions, "txt_useradded"));
309 		assertFalse("2.2", contains(textUserDefinedExtensions, "txt_pluginadded"));
310 
311 		// removing pre-defined file specs should not do anything
312 		text.removeFileSpec("txt", IContentType.FILE_EXTENSION_SPEC);
313 		assertTrue("3.0", contains(
314 				text.getFileSpecs(IContentType.FILE_EXTENSION_SPEC | IContentType.IGNORE_USER_DEFINED), "txt"));
315 		assertTrue("3.1", text.isAssociatedWith(changeCase("text.txt")));
316 		assertTrue("3.2", text.isAssociatedWith(changeCase("text.txt_useradded")));
317 		assertTrue("3.3", text.isAssociatedWith(changeCase("text.txt_pluginadded")));
318 
319 		// removing user file specs is the normal case and has to work as expected
320 		text.removeFileSpec("txt_useradded", IContentType.FILE_EXTENSION_SPEC);
321 		assertFalse("4.0",
322 				contains(text.getFileSpecs(IContentType.FILE_EXTENSION_SPEC | IContentType.IGNORE_PRE_DEFINED), "ini"));
323 		assertTrue("4.1", text.isAssociatedWith(changeCase("text.txt")));
324 		assertFalse("4.2", text.isAssociatedWith(changeCase("text.txt_useradded")));
325 		assertTrue("4.3", text.isAssociatedWith(changeCase("text.txt_pluginadded")));
326 	}
327 
328 	@Test
testBinaryTypes()329 	public void testBinaryTypes() throws IOException {
330 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
331 		IContentType sampleBinary1 = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".sample-binary1");
332 		IContentType sampleBinary2 = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".sample-binary2");
333 		InputStream contents;
334 
335 		contents = getInputStream(
336 				new byte[][] { SAMPLE_BIN1_OFFSET.getBytes(), SAMPLE_BIN1_SIGNATURE, " extra contents".getBytes() });
337 		IContentDescription description = contentTypeManager.getDescriptionFor(contents, null, IContentDescription.ALL);
338 		assertNotNull("6.0", description);
339 		assertEquals("6.1", sampleBinary1, description.getContentType());
340 
341 		contents = getInputStream(
342 				new byte[][] { SAMPLE_BIN2_OFFSET.getBytes(), SAMPLE_BIN2_SIGNATURE, " extra contents".getBytes() });
343 		description = contentTypeManager.getDescriptionFor(contents, null, IContentDescription.ALL);
344 		assertNotNull("7.0", description);
345 		assertEquals("7.1", sampleBinary2, description.getContentType());
346 
347 		// make sure we ignore that content type when contents are text
348 		// (see bug 100032)
349 		// first check if our test environment is sane
350 		IContentType[] selected = contentTypeManager.findContentTypesFor("test.samplebin2");
351 		assertEquals("8.1", 1, selected.length);
352 		assertEquals("8.2", sampleBinary2.getId(), selected[0].getId());
353 		// (we used to blow up here)
354 		description = contentTypeManager.getDescriptionFor(getReader(getRandomString()), "test.samplebin2",
355 				IContentDescription.ALL);
356 		assertNull("8.3", description);
357 	}
358 
359 	@Test
testByteOrderMark()360 	public void testByteOrderMark() throws IOException {
361 		IContentType text = Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT);
362 		QualifiedName[] options = new QualifiedName[] { IContentDescription.BYTE_ORDER_MARK };
363 		IContentDescription description;
364 		// tests with UTF-8 BOM
365 		String UTF8_BOM = new String(IContentDescription.BOM_UTF_8, StandardCharsets.ISO_8859_1);
366 		description = text.getDescriptionFor(
367 				new ByteArrayInputStream((UTF8_BOM + MINIMAL_XML).getBytes(StandardCharsets.ISO_8859_1)), options);
368 		assertNotNull("1.0", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
369 		assertEquals("1.1", IContentDescription.BOM_UTF_8,
370 				description.getProperty(IContentDescription.BYTE_ORDER_MARK));
371 		// tests with UTF-16 Little Endian BOM
372 		String UTF16_LE_BOM = new String(IContentDescription.BOM_UTF_16LE, StandardCharsets.ISO_8859_1);
373 		description = text.getDescriptionFor(
374 				new ByteArrayInputStream((UTF16_LE_BOM + MINIMAL_XML).getBytes(StandardCharsets.ISO_8859_1)), options);
375 		assertNotNull("2.0", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
376 		assertEquals("2.1", IContentDescription.BOM_UTF_16LE,
377 				description.getProperty(IContentDescription.BYTE_ORDER_MARK));
378 		// tests with UTF-16 Big Endian BOM
379 		String UTF16_BE_BOM = new String(IContentDescription.BOM_UTF_16BE, StandardCharsets.ISO_8859_1);
380 		description = text.getDescriptionFor(
381 				new ByteArrayInputStream((UTF16_BE_BOM + MINIMAL_XML).getBytes(StandardCharsets.ISO_8859_1)), options);
382 		assertNotNull("3.0", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
383 		assertEquals("3.1", IContentDescription.BOM_UTF_16BE,
384 				description.getProperty(IContentDescription.BYTE_ORDER_MARK));
385 		// test with no BOM
386 		description = text.getDescriptionFor(
387 				new ByteArrayInputStream(MINIMAL_XML.getBytes(StandardCharsets.ISO_8859_1)), options);
388 		assertNull("4.0", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
389 
390 		// tests for partial BOM
391 		// first byte of UTF-16 Big Endian + minimal xml
392 		String UTF16_BE_BOM_1byte = new String(new byte[] { (byte) 0xFE }, "ISO-8859-1");
393 		description = text.getDescriptionFor(
394 				new ByteArrayInputStream((UTF16_BE_BOM_1byte + MINIMAL_XML).getBytes(StandardCharsets.ISO_8859_1)),
395 				options);
396 		assertNull("5.0", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
397 		// first byte of UTF-16 Big Endian only (see
398 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=199252)
399 		description = text.getDescriptionFor(
400 				new ByteArrayInputStream((UTF16_BE_BOM_1byte).getBytes(StandardCharsets.ISO_8859_1)), options);
401 		assertNull("5.1", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
402 
403 		// first byte of UTF-16 Little Endian + minimal xml
404 		String UTF16_LE_BOM_1byte = new String(new byte[] { (byte) 0xFF }, StandardCharsets.ISO_8859_1);
405 		description = text.getDescriptionFor(
406 				new ByteArrayInputStream((UTF16_LE_BOM_1byte + MINIMAL_XML).getBytes(StandardCharsets.ISO_8859_1)),
407 				options);
408 		assertNull("6.0", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
409 		// first byte of UTF-16 Little Endian only
410 		description = text.getDescriptionFor(
411 				new ByteArrayInputStream((UTF16_LE_BOM_1byte).getBytes(StandardCharsets.ISO_8859_1)), options);
412 		assertNull("6.1", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
413 
414 		// first byte of UTF-8 + minimal xml
415 		String UTF8_BOM_1byte = new String(new byte[] { (byte) 0xEF }, StandardCharsets.ISO_8859_1);
416 		description = text.getDescriptionFor(
417 				new ByteArrayInputStream((UTF8_BOM_1byte + MINIMAL_XML).getBytes(StandardCharsets.ISO_8859_1)),
418 				options);
419 		assertNull("7.0", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
420 		// first byte of UTF-8 only
421 		description = text.getDescriptionFor(
422 				new ByteArrayInputStream((UTF8_BOM_1byte).getBytes(StandardCharsets.ISO_8859_1)), options);
423 		assertNull("7.1", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
424 
425 		// two first bytes of UTF-8 + minimal xml
426 		String UTF8_BOM_2bytes = new String(new byte[] { (byte) 0xEF, (byte) 0xBB }, StandardCharsets.ISO_8859_1);
427 		description = text.getDescriptionFor(
428 				new ByteArrayInputStream((UTF8_BOM_2bytes + MINIMAL_XML).getBytes(StandardCharsets.ISO_8859_1)),
429 				options);
430 		assertNull("8.0", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
431 		// two first bytes of UTF-8 only
432 		description = text.getDescriptionFor(
433 				new ByteArrayInputStream((UTF8_BOM_2bytes).getBytes(StandardCharsets.ISO_8859_1)), options);
434 		assertNull("8.1", description.getProperty(IContentDescription.BYTE_ORDER_MARK));
435 	}
436 
437 	/**
438 	 * See bug 90218.
439 	 */
440 	@Test
testContentAndNameMatching()441 	public void testContentAndNameMatching() throws IOException /* not really */ {
442 		IContentTypeManager manager = Platform.getContentTypeManager();
443 
444 		byte[][] contents0 = { { 0x0A, 0x0B, 0x0E, 0x10 } };
445 		byte[][] contents1 = { { 0x0A, 0x0B, 0x0C, 0x10 } };
446 		byte[][] contents2 = { { 0x0A, 0x0B, 0x0D, 0x10 } };
447 		byte[][] invalidContents = { { 0, 0, 0, 0 } };
448 
449 		// base matches *.mybinary files starting with 0x0a 0x0b
450 		IContentType base = manager.getContentType(PI_RESOURCES_TESTS + ".binary_base");
451 		// derived1 matches *.mybinary and specifically foo.mybinary files starting with
452 		// 0x0a 0x0b 0xc
453 		IContentType derived1 = manager.getContentType(PI_RESOURCES_TESTS + ".binary_derived1");
454 		// derived2 matches *.mybinary (inherits filespec from base) files starting with
455 		// 0x0a 0x0b 0xd
456 		IContentType derived2 = manager.getContentType(PI_RESOURCES_TESTS + ".binary_derived2");
457 
458 		IContentType[] selected;
459 
460 		selected = manager.findContentTypesFor(getInputStream(contents0), "anything.mybinary");
461 		assertEquals("1.0", 3, selected.length);
462 		// all we know is the first one is the base type (only one with a VALID match)
463 		assertEquals("1.1", base, selected[0]);
464 
465 		selected = manager.findContentTypesFor(getInputStream(contents0), "foo.mybinary");
466 		// we know also that the second one will be derived1, because it has a full name
467 		// matching
468 		assertEquals("2.0", 3, selected.length);
469 		assertEquals("2.1", base, selected[0]);
470 		assertEquals("2.2", derived1, selected[1]);
471 
472 		selected = manager.findContentTypesFor(getInputStream(contents1), "foo.mybinary");
473 		// derived1 will be first because both base and derived1 have a strong content
474 		// matching, so more specific wins
475 		assertEquals("3.0", 3, selected.length);
476 		assertEquals("3.1", derived1, selected[0]);
477 		assertEquals("3.2", base, selected[1]);
478 
479 		selected = manager.findContentTypesFor(getInputStream(contents2), "foo.mybinary");
480 		// same as 3.* - derived1 is last because content matching is weak, althoug name
481 		// matching is strong
482 		assertEquals("4.0", 3, selected.length);
483 		assertEquals("4.1", derived2, selected[0]);
484 		assertEquals("4.2", base, selected[1]);
485 
486 		selected = manager.findContentTypesFor(getInputStream(invalidContents), "foo.mybinary");
487 		// all types have weak content matching only - derived1 has strong name matching
488 		assertEquals("5.0", 3, selected.length);
489 		assertEquals("5.1", derived1, selected[0]);
490 		assertEquals("5.2", base, selected[1]);
491 
492 		selected = manager.findContentTypesFor(getInputStream(invalidContents), "anything.mybinary");
493 		// all types have weak content/name matching only - most general wins
494 		assertEquals("6.0", 3, selected.length);
495 		assertEquals("6.1", base, selected[0]);
496 	}
497 
498 	/*
499 	 * Tests both text and byte stream-based getDescriptionFor methods.
500 	 */@Test
testContentDescription()501 	public void testContentDescription() throws IOException, CoreException {
502 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
503 		IContentTypeMatcher finder = contentTypeManager.getMatcher(new LocalSelectionPolicy(), null);
504 
505 		IContentType xmlType = contentTypeManager.getContentType(Platform.PI_RUNTIME + ".xml");
506 		IContentType mytext = contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "mytext");
507 		IContentType mytext1 = contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "mytext1");
508 		IContentType mytext2 = contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "mytext2");
509 
510 		boolean text = false;
511 
512 		for (int i = 0; i < 2; i++, text = !text) {
513 			String sufix = text ? "-text" : "-binary";
514 			IContentDescription description;
515 
516 			description = getDescriptionFor(finder, MINIMAL_XML, StandardCharsets.UTF_8, "foo.xml",
517 					IContentDescription.ALL, text);
518 			assertNotNull("1.0" + sufix, description);
519 			assertEquals("1.1" + sufix, xmlType, description.getContentType());
520 			assertSame("1.2", xmlType.getDefaultDescription(), description);
521 
522 			description = getDescriptionFor(finder, MINIMAL_XML, StandardCharsets.UTF_8, "foo.xml",
523 					new QualifiedName[] { IContentDescription.CHARSET }, text);
524 			assertNotNull("2.0" + sufix, description);
525 			assertEquals("2.1" + sufix, xmlType, description.getContentType());
526 			// the default charset should have been filled by the content type manager
527 			assertEquals("2.2" + sufix, "UTF-8", description.getProperty(IContentDescription.CHARSET));
528 			assertSame("2.3", xmlType.getDefaultDescription(), description);
529 
530 			description = getDescriptionFor(finder, XML_ISO_8859_1, StandardCharsets.ISO_8859_1, "foo.xml",
531 					new QualifiedName[] { IContentDescription.CHARSET }, text);
532 			assertNotNull("2.3a" + sufix, description);
533 			assertEquals("2.3b" + sufix, xmlType, description.getContentType());
534 			assertEquals("2.3c" + sufix, "ISO-8859-1", description.getProperty(IContentDescription.CHARSET));
535 			assertNotSame("2.3d", xmlType.getDefaultDescription(), description);
536 
537 			// ensure we handle single quotes properly (bug 65443)
538 			description = getDescriptionFor(finder, XML_ISO_8859_1_SINGLE_QUOTES, StandardCharsets.ISO_8859_1,
539 					"foo.xml", new QualifiedName[] { IContentDescription.CHARSET }, text);
540 			assertNotNull("2.3e" + sufix, description);
541 			assertEquals("2.3f" + sufix, xmlType, description.getContentType());
542 			assertEquals("2.3g" + sufix, "ISO-8859-1", description.getProperty(IContentDescription.CHARSET));
543 			assertNotSame("2.3h", xmlType.getDefaultDescription(), description);
544 
545 			description = getDescriptionFor(finder, XML_UTF_16, StandardCharsets.UTF_16, "foo.xml",
546 					new QualifiedName[] { IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK }, text);
547 			assertNotNull("2.4a" + sufix, description);
548 			assertEquals("2.4b" + sufix, xmlType, description.getContentType());
549 			assertEquals("2.4c" + sufix, "UTF-16", description.getProperty(IContentDescription.CHARSET));
550 			assertTrue("2.4d" + sufix, text || IContentDescription.BOM_UTF_16BE == description
551 					.getProperty(IContentDescription.BYTE_ORDER_MARK));
552 			assertNotSame("2.4e", xmlType.getDefaultDescription(), description);
553 
554 			description = getDescriptionFor(finder, XML_UTF_16BE, StandardCharsets.UTF_8, "foo.xml",
555 					new QualifiedName[] { IContentDescription.CHARSET }, text);
556 			assertNotNull("2.5a" + sufix, description);
557 			assertEquals("2.5b" + sufix, xmlType, description.getContentType());
558 			assertEquals("2.5c" + sufix, "UTF-16BE", description.getProperty(IContentDescription.CHARSET));
559 			assertNotSame("2.5d", xmlType.getDefaultDescription(), description);
560 
561 			description = getDescriptionFor(finder, XML_UTF_16LE, StandardCharsets.UTF_8, "foo.xml",
562 					new QualifiedName[] { IContentDescription.CHARSET }, text);
563 			assertNotNull("2.6a" + sufix, description);
564 			assertEquals("2.6b" + sufix, xmlType, description.getContentType());
565 			// the default charset should have been filled by the content type manager
566 			assertEquals("2.6c" + sufix, "UTF-16LE", description.getProperty(IContentDescription.CHARSET));
567 			assertNotSame("2.6d", xmlType.getDefaultDescription(), description);
568 
569 			description = getDescriptionFor(finder, MINIMAL_XML, StandardCharsets.UTF_8, "foo.xml",
570 					IContentDescription.ALL, text);
571 			assertNotNull("4.0" + sufix, description);
572 			assertEquals("4.1" + sufix, xmlType, description.getContentType());
573 			assertEquals("4.2" + sufix, "UTF-8", description.getProperty(IContentDescription.CHARSET));
574 			assertNotNull("5.0" + sufix, mytext);
575 			assertEquals("5.0b" + sufix, "BAR", mytext.getDefaultCharset());
576 			assertSame("5.0c", xmlType.getDefaultDescription(), description);
577 
578 			description = getDescriptionFor(finder, "some contents", null, "abc.tzt", IContentDescription.ALL, text);
579 			assertNotNull("5.1" + sufix, description);
580 			assertEquals("5.2" + sufix, mytext, description.getContentType());
581 			assertEquals("5.3" + sufix, "BAR", description.getProperty(IContentDescription.CHARSET));
582 			assertSame("5.4", mytext.getDefaultDescription(), description);
583 			// now plays with setting a non-default default charset
584 			mytext.setDefaultCharset("FOO");
585 
586 			description = getDescriptionFor(finder, "some contents", null, "abc.tzt", IContentDescription.ALL, text);
587 			assertNotNull("5.5" + sufix, description);
588 			assertEquals("5.6" + sufix, mytext, description.getContentType());
589 			assertEquals("5.7" + sufix, "FOO", description.getProperty(IContentDescription.CHARSET));
590 			assertSame("5.8", mytext.getDefaultDescription(), description);
591 			mytext.setDefaultCharset(null);
592 
593 			description = getDescriptionFor(finder, "some contents", null, "abc.tzt", IContentDescription.ALL, text);
594 			assertNotNull("5.10" + sufix, description);
595 			assertEquals("5.11" + sufix, mytext, description.getContentType());
596 			assertEquals("5.12" + sufix, "BAR", description.getProperty(IContentDescription.CHARSET));
597 			assertSame("5.13", mytext.getDefaultDescription(), description);
598 
599 			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=176354
600 			description = getDescriptionFor(finder,
601 					"<?xml version=\'1.0\' encoding=\'UTF-8\'?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tns=\"http://www.example.org/\" xmlns:ns0=\"http://another.example.org/\"><soapenv:Header /><soapenv:Body><ns0:x /></soapenv:Body></soapenv:Envelope>",
602 					StandardCharsets.UTF_8, "foo.xml", new QualifiedName[] { IContentDescription.CHARSET }, text);
603 			assertNotNull("5.14" + sufix, description);
604 			assertEquals("5.15" + sufix, xmlType, description.getContentType());
605 			assertEquals("5.16" + sufix, "UTF-8", description.getProperty(IContentDescription.CHARSET));
606 			assertEquals("5.17", xmlType.getDefaultDescription().getCharset(), description.getCharset());
607 		}
608 		assertNotNull("6.0", mytext1);
609 		assertEquals("6.1", "BAR", mytext1.getDefaultCharset());
610 		assertNotNull("6.2", mytext2);
611 		assertEquals("6.3", null, mytext2.getDefaultCharset());
612 
613 	}
614 
615 	@Test
testContentDetection()616 	public void testContentDetection() throws IOException {
617 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
618 		IContentTypeMatcher finder;
619 
620 		IContentType inappropriate = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".sample-binary1");
621 		IContentType appropriate = contentTypeManager.getContentType(Platform.PI_RUNTIME + ".xml");
622 		IContentType appropriateSpecific1 = contentTypeManager
623 				.getContentType(PI_RESOURCES_TESTS + ".xml-based-different-extension");
624 		IContentType appropriateSpecific1LowPriority = contentTypeManager
625 				.getContentType(PI_RESOURCES_TESTS + ".xml-based-different-extension-low-priority");
626 		IContentType appropriateSpecific2 = contentTypeManager
627 				.getContentType(PI_RESOURCES_TESTS + ".xml-based-specific-name");
628 
629 		// if only inappropriate is provided, none will be selected
630 		finder = contentTypeManager.getMatcher(new SubsetSelectionPolicy(new IContentType[] { inappropriate }), null);
631 		assertNull("1.0", finder.findContentTypeFor(getInputStream(MINIMAL_XML), null));
632 
633 		// if inappropriate and appropriate are provided, appropriate will be selected
634 		finder = contentTypeManager
635 				.getMatcher(new SubsetSelectionPolicy(new IContentType[] { inappropriate, appropriate }), null);
636 		assertEquals("2.0", appropriate, finder.findContentTypeFor(getInputStream(MINIMAL_XML), null));
637 
638 		// if inappropriate, appropriate and a more specific appropriate type are
639 		// provided, the specific type will be selected
640 		finder = contentTypeManager.getMatcher(
641 				new SubsetSelectionPolicy(new IContentType[] { inappropriate, appropriate, appropriateSpecific1 }),
642 				null);
643 		assertEquals("3.0", appropriateSpecific1, finder.findContentTypeFor(getInputStream(MINIMAL_XML), null));
644 		finder = contentTypeManager.getMatcher(
645 				new SubsetSelectionPolicy(new IContentType[] { inappropriate, appropriate, appropriateSpecific2 }),
646 				null);
647 		assertEquals("3.1", appropriateSpecific2, finder.findContentTypeFor(getInputStream(MINIMAL_XML), null));
648 
649 		// if all are provided, the more specific types will appear before the more
650 		// generic types
651 		finder = contentTypeManager.getMatcher(
652 				new SubsetSelectionPolicy(
653 						new IContentType[] { inappropriate, appropriate, appropriateSpecific1, appropriateSpecific2 }),
654 				null);
655 		IContentType[] selected = finder.findContentTypesFor(getInputStream(MINIMAL_XML), null);
656 		assertEquals("4.0", 3, selected.length);
657 		assertTrue("4.1", appropriateSpecific1.equals(selected[0]) || appropriateSpecific1.equals(selected[1]));
658 		assertTrue("4.2", appropriateSpecific2.equals(selected[0]) || appropriateSpecific2.equals(selected[1]));
659 		assertTrue("4.3", appropriate.equals(selected[2]));
660 
661 		// if appropriate and a more specific appropriate type (but with low priority)
662 		// are provided, the specific type will be selected
663 		finder = contentTypeManager.getMatcher(
664 				new SubsetSelectionPolicy(new IContentType[] { appropriate, appropriateSpecific1LowPriority }), null);
665 		assertEquals("5.0", appropriateSpecific1LowPriority,
666 				finder.findContentTypeFor(getInputStream(MINIMAL_XML), null));
667 
668 		// if appropriate and two specific appropriate types (but one with lower
669 		// priority) are provided, the specific type with higher priority will be
670 		// selected
671 		finder = contentTypeManager.getMatcher(
672 				new SubsetSelectionPolicy(
673 						new IContentType[] { appropriate, appropriateSpecific1, appropriateSpecific1LowPriority }),
674 				null);
675 		assertEquals("5.1", appropriateSpecific1, finder.findContentTypeFor(getInputStream(MINIMAL_XML), null));
676 	}
677 
678 	@Test
testDefaultProperties()679 	public void testDefaultProperties() throws IOException /* never actually thrown */ {
680 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
681 
682 		IContentType mytext = contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "mytext");
683 		IContentType mytext1 = contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "mytext1");
684 		IContentType mytext2 = contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "mytext2");
685 		assertNotNull("0.1", mytext);
686 		assertNotNull("0.2", mytext1);
687 		assertNotNull("0.3", mytext2);
688 
689 		QualifiedName charset = IContentDescription.CHARSET;
690 		QualifiedName localCharset = new QualifiedName(PI_RESOURCES_TESTS, "charset");
691 		QualifiedName property1 = new QualifiedName(PI_RESOURCES_TESTS, "property1");
692 		QualifiedName property2 = new QualifiedName(PI_RESOURCES_TESTS, "property2");
693 		QualifiedName property3 = new QualifiedName(PI_RESOURCES_TESTS, "property3");
694 		QualifiedName property4 = new QualifiedName(PI_RESOURCES_TESTS, "property4");
695 
696 		IContentDescription description;
697 		IContentTypeMatcher finder = contentTypeManager.getMatcher(new LocalSelectionPolicy(), null);
698 
699 		description = getDescriptionFor(finder, "some contents", null, "abc.tzt", IContentDescription.ALL, true);
700 		assertNotNull("1.0", description);
701 		assertEquals("1.1", mytext, description.getContentType());
702 		assertEquals("1.2", "value1", description.getProperty(property1));
703 		assertNull("1.3", description.getProperty(property2));
704 		assertEquals("1.4", "value3", description.getProperty(property3));
705 		assertEquals("1.5", "BAR", description.getProperty(charset));
706 
707 		description = getDescriptionFor(finder, "some contents", null, "abc.tzt1", IContentDescription.ALL, true);
708 		assertNotNull("2.0", description);
709 		assertEquals("2.1", mytext1, description.getContentType());
710 		assertEquals("2.2", "value1", description.getProperty(property1));
711 		assertEquals("2.3", "value2", description.getProperty(property2));
712 		assertNull("2.4", description.getProperty(property3));
713 		assertEquals("2.5", "value4", description.getProperty(property4));
714 		assertEquals("2.6", "BAR", description.getProperty(charset));
715 
716 		description = getDescriptionFor(finder, "some contents", null, "abc.tzt2", IContentDescription.ALL, true);
717 		assertNotNull("3.0", description);
718 		assertEquals("3.1", mytext2, description.getContentType());
719 		assertNull("3.2", description.getProperty(property1));
720 		assertNull("3.3", description.getProperty(property2));
721 		assertNull("3.4", description.getProperty(property3));
722 		assertNull("3.5", description.getProperty(property4));
723 		assertNull("3.6", description.getProperty(charset));
724 		assertEquals("3.7", "mytext2", description.getProperty(localCharset));
725 	}
726 
727 	/**
728 	 * The fooBar content type is associated with the "foo.bar" file name and the
729 	 * "bar" file extension (what is bogus, anyway). This test ensures it does not
730 	 * appear twice in the list of content types associated with the "foo.bar" file
731 	 * name.
732 	 */
733 	@Test
testDoubleAssociation()734 	public void testDoubleAssociation() {
735 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
736 
737 		IContentType fooBarType = contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "fooBar");
738 		assertNotNull("1.0", fooBarType);
739 		IContentType subFooBarType = contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "subFooBar");
740 		assertNotNull("1.1", subFooBarType);
741 		// ensure we don't get fooBar twice
742 		IContentTypeMatcher finder = contentTypeManager.getMatcher(new LocalSelectionPolicy(), null);
743 		IContentType[] fooBarAssociated = finder.findContentTypesFor(changeCase("foo.bar"));
744 		assertEquals("2.1", 2, fooBarAssociated.length);
745 		assertTrue("2.2", contains(fooBarAssociated, fooBarType));
746 		assertTrue("2.3", contains(fooBarAssociated, subFooBarType));
747 	}
748 
749 	/**
750 	 * Obtains a reference to a known content type, then installs a bundle that
751 	 * contributes a content type, and makes sure a new obtained reference to the
752 	 * same content type is not identical (shows that the content type catalog has
753 	 * been discarded and rebuilt). Then uninstalls that bundle and checks again the
754 	 * same thing (because the content type catalog should be rebuilt whenever
755 	 * content types are dynamicaly added/removed).
756 	 */
757 	@Test
testDynamicChanges()758 	public void testDynamicChanges() {
759 		final IContentType[] text = new IContentType[4];
760 		final IContentTypeManager manager = Platform.getContentTypeManager();
761 		text[0] = manager.getContentType(IContentTypeManager.CT_TEXT);
762 		assertNotNull("1.0", text[0]);
763 		text[1] = manager.getContentType(IContentTypeManager.CT_TEXT);
764 		assertNotNull("1.1", text[1]);
765 		text[0] = ((ContentTypeHandler) text[0]).getTarget();
766 		text[1] = ((ContentTypeHandler) text[1]).getTarget();
767 		assertEquals("2.0", text[0], text[1]);
768 		assertEquals("2.1", text[0], text[1]);
769 		// make arbitrary dynamic changes to the contentTypes extension point
770 		TestRegistryChangeListener listener = new TestRegistryChangeListener(Platform.PI_RUNTIME,
771 				ContentTypeBuilder.PT_CONTENTTYPES, null, null);
772 		BundleTestingHelper.runWithBundles("3", () -> {
773 			IContentType missing = manager.getContentType("org.eclipse.bundle01.missing");
774 			assertNotNull("3.1", missing);
775 			// ensure the content type instances are different
776 			text[2] = manager.getContentType(IContentTypeManager.CT_TEXT);
777 			assertNotNull("3.2", text[2]);
778 			text[2] = ((ContentTypeHandler) text[2]).getTarget();
779 			assertEquals("3.3", text[0], text[2]);
780 			assertNotSame("3.4", text[0], text[2]);
781 		}, getContext(), new String[] { ContentTypeTest.TEST_FILES_ROOT + "content/bundle01" }, listener);
782 		assertNull("4.0", manager.getContentType("org.eclipse.bundle01.missing"));
783 		// ensure the content type instances are all different
784 		text[3] = manager.getContentType(IContentTypeManager.CT_TEXT);
785 		assertNotNull("5.0", text[3]);
786 		text[3] = ((ContentTypeHandler) text[3]).getTarget();
787 		assertEquals("5.1", text[0], text[3]);
788 		assertEquals("5.2", text[2], text[3]);
789 		assertNotSame("5.3", text[0], text[3]);
790 		assertNotSame("5.4", text[2], text[3]);
791 	}
792 
793 	/**
794 	 * Similar to testDynamicChanges, but using the
795 	 * org.eclipse.core.contenttype.contentTypes extension point.
796 	 */
797 	@Test
testDynamicChangesNewExtension()798 	public void testDynamicChangesNewExtension() {
799 		final IContentType[] text = new IContentType[4];
800 		final IContentTypeManager manager = Platform.getContentTypeManager();
801 		text[0] = manager.getContentType(IContentTypeManager.CT_TEXT);
802 		assertNotNull("1.0", text[0]);
803 		text[1] = manager.getContentType(IContentTypeManager.CT_TEXT);
804 		assertNotNull("1.1", text[1]);
805 		text[0] = ((ContentTypeHandler) text[0]).getTarget();
806 		text[1] = ((ContentTypeHandler) text[1]).getTarget();
807 		assertEquals("2.0", text[0], text[1]);
808 		assertSame("2.1", text[0], text[1]);
809 		// make arbitrary dynamic changes to the contentTypes extension point
810 		TestRegistryChangeListener listener = new TestRegistryChangeListener(IContentConstants.CONTENT_NAME,
811 				ContentTypeBuilder.PT_CONTENTTYPES, null, null);
812 		BundleTestingHelper.runWithBundles("3", () -> {
813 			IContentType contentType = manager.getContentType("org.eclipse.bug485227.bug485227_contentType");
814 			assertNotNull("3.1 Contributed content type not found", contentType);
815 			// ensure the content type instances are different
816 			text[2] = manager.getContentType(IContentTypeManager.CT_TEXT);
817 			assertNotNull("3.2 Text content type not modified", text[2]);
818 			text[2] = ((ContentTypeHandler) text[2]).getTarget();
819 			assertEquals("3.3", text[0], text[2]);
820 			assertNotSame("3.4", text[0], text[2]);
821 			assertEquals("3.5 default extension not associated", contentType,
822 					manager.findContentTypeFor("file.bug485227"));
823 			assertEquals("3.6 additional extension not associated", contentType,
824 					manager.findContentTypeFor("file.bug485227_2"));
825 		}, getContext(), new String[] { ContentTypeTest.TEST_FILES_ROOT + "content/bug485227" }, listener);
826 		assertNull("4.0 Content type not cleared after bundle uninstall",
827 				manager.getContentType("org.eclipse.bug485227.bug485227_contentType"));
828 		// ensure the content type instances are all different
829 		text[3] = manager.getContentType(IContentTypeManager.CT_TEXT);
830 		assertNotNull("5.0", text[3]);
831 		text[3] = ((ContentTypeHandler) text[3]).getTarget();
832 		assertEquals("5.1", text[0], text[3]);
833 		assertEquals("5.2", text[2], text[3]);
834 		assertNotSame("5.3", text[0], text[3]);
835 		assertNotSame("5.4", text[2], text[3]);
836 	}
837 
838 	@Test
testEvents()839 	public void testEvents() throws CoreException {
840 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
841 		IContentType myType = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".myContent");
842 		assertNotNull("0.9", myType);
843 
844 		ContentTypeChangeTracer tracer;
845 
846 		tracer = new ContentTypeChangeTracer();
847 		contentTypeManager.addContentTypeChangeListener(tracer);
848 
849 		// add a file spec and check event
850 		myType.addFileSpec("another.file.name", IContentType.FILE_NAME_SPEC);
851 		assertTrue("1.1", tracer.isOnlyChange(myType));
852 
853 		// remove a non-existing file spec - should not cause an event to be fired
854 		tracer.reset();
855 		myType.removeFileSpec("another.file.name", IContentType.FILE_EXTENSION_SPEC);
856 		assertTrue("2.1", !tracer.isOnlyChange(myType));
857 
858 		// add a file spec again and check no event is generated
859 		tracer.reset();
860 		myType.addFileSpec("another.file.name", IContentType.FILE_NAME_SPEC);
861 		assertTrue("3.1", !tracer.isOnlyChange(myType));
862 
863 		// remove a file spec and check event
864 		tracer.reset();
865 		myType.removeFileSpec("another.file.name", IContentType.FILE_NAME_SPEC);
866 		assertTrue("4.1", tracer.isOnlyChange(myType));
867 
868 		// change the default charset and check event
869 		tracer.reset();
870 		myType.setDefaultCharset("FOO");
871 		assertTrue("5.1", tracer.isOnlyChange(myType));
872 
873 		// set the default charset to the same - no event should be generated
874 		tracer.reset();
875 		myType.setDefaultCharset("FOO");
876 		assertTrue("6.1", !tracer.isOnlyChange(myType));
877 
878 		myType.setDefaultCharset("ABC");
879 	}
880 
881 	@Test
testFileSpecConflicts()882 	public void testFileSpecConflicts() throws IOException {
883 		IContentTypeManager manager = Platform.getContentTypeManager();
884 		// when not submitting contents, for related types, most general type prevails
885 		IContentType conflict1a = manager.getContentType(PI_RESOURCES_TESTS + ".base_conflict1");
886 		IContentType conflict1b = manager.getContentType(PI_RESOURCES_TESTS + ".sub_conflict1");
887 		assertNotNull("1.0", conflict1a);
888 		assertNotNull("1.1", conflict1b);
889 		IContentType preferredConflict1 = manager.findContentTypeFor("test.conflict1");
890 		assertNotNull("1.2", preferredConflict1);
891 		assertEquals("1.3", conflict1a, preferredConflict1);
892 
893 		IContentType conflict2base = manager.getContentType(PI_RESOURCES_TESTS + ".base_conflict2");
894 		IContentType conflict2sub = manager.getContentType(PI_RESOURCES_TESTS + ".sub_conflict2");
895 		assertNotNull("2.0", conflict2base);
896 		assertNotNull("2.1", conflict2sub);
897 		// when submitting contents, for related types, descendant comes first
898 
899 		IContentType[] selectedConflict2 = manager.findContentTypesFor(getRandomContents(), "test.conflict2");
900 		assertEquals("2.2", 2, selectedConflict2.length);
901 		assertEquals("2.3", selectedConflict2[0], conflict2base);
902 		assertEquals("2.4", selectedConflict2[1], conflict2sub);
903 
904 		IContentType conflict3base = manager.getContentType(PI_RESOURCES_TESTS + ".base_conflict3");
905 		IContentType conflict3sub = manager.getContentType(PI_RESOURCES_TESTS + ".sub_conflict3");
906 		IContentType conflict3unrelated = manager.getContentType(PI_RESOURCES_TESTS + ".unrelated_conflict3");
907 		assertNotNull("3.0.1", conflict3base);
908 		assertNotNull("3.0.2", conflict3sub);
909 		assertNotNull("3.0.3", conflict3unrelated);
910 
911 		// Two unrelated types (sub_conflict3 and unrelated conflict3) are in conflict.
912 		// Order will be based on depth (more general first since they don't have
913 		// describers)
914 
915 		IContentType[] selectedConflict3 = manager.findContentTypesFor(getRandomContents(), "test.conflict3");
916 		assertEquals("4.0", 2, selectedConflict3.length);
917 		assertEquals("4.1", selectedConflict3[0], conflict3unrelated);
918 		assertEquals("4.2", selectedConflict3[1], conflict3sub);
919 	}
920 
921 	@Test
testFindContentType()922 	public void testFindContentType() throws IOException {
923 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
924 		IContentTypeMatcher finder = contentTypeManager.getMatcher(new LocalSelectionPolicy(), null);
925 
926 		IContentType textContentType = contentTypeManager.getContentType(Platform.PI_RUNTIME + '.' + "text");
927 		IContentType xmlContentType = contentTypeManager.getContentType(Platform.PI_RUNTIME + ".xml");
928 
929 		IContentType single;
930 
931 		single = finder.findContentTypeFor(getInputStream("Just a test"), changeCase("file.txt"));
932 		assertNotNull("1.0", single);
933 		assertEquals("1.1", textContentType, single);
934 
935 		single = finder.findContentTypeFor(getInputStream(XML_UTF_8, StandardCharsets.UTF_8), changeCase("foo.xml"));
936 		assertNotNull("2.0", single);
937 		assertEquals("2.1", xmlContentType, single);
938 
939 		IContentType[] multiple = finder.findContentTypesFor(getInputStream(XML_UTF_8, StandardCharsets.UTF_8), null);
940 		assertTrue("3.0", contains(multiple, xmlContentType));
941 	}
942 
943 	@Test
testFindContentTypPredefinedRegexp()944 	public void testFindContentTypPredefinedRegexp() throws IOException, CoreException {
945 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
946 		IContentTypeMatcher finder = contentTypeManager.getMatcher(new LocalSelectionPolicy(), null);
947 
948 		IContentType targetContentType = contentTypeManager
949 				.getContentType("org.eclipse.core.tests.resources.predefinedContentTypeWithRegexp");
950 		assertNotNull("Target content-type not found", targetContentType);
951 
952 		IContentType single = finder.findContentTypeFor(getInputStream("Just a test"),
953 				"somepredefinedContentTypeWithRegexpFile");
954 		assertEquals(targetContentType, single);
955 		single = finder.findContentTypeFor(getInputStream("Just a test"), "somepredefinedContentTypeWithPatternFile");
956 		assertEquals(targetContentType, single);
957 		single = finder.findContentTypeFor(getInputStream("Just a test"), "somepredefinedContentTypeWithWildcardsFile");
958 		assertEquals(targetContentType, single);
959 	}
960 
961 	@Test
testFindContentTypeUserRegexp()962 	public void testFindContentTypeUserRegexp() throws IOException, CoreException {
963 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
964 		IContentTypeMatcher finder = contentTypeManager.getMatcher(new LocalSelectionPolicy(), null);
965 
966 		IContentType textContentType = contentTypeManager.getContentType(Platform.PI_RUNTIME + '.' + "text");
967 
968 		IContentType single = finder.findContentTypeFor(getInputStream("Just a test"), "someText.unknown");
969 		assertNull("File pattern unknown at that point", single);
970 
971 		textContentType.addFileSpec("*Text*", IContentType.FILE_PATTERN_SPEC);
972 		single = finder.findContentTypeFor(getInputStream("Just a test"), "someText.unknown");
973 		assertEquals("Text content should now match *Text* files", textContentType, single);
974 	}
975 
976 	@Test
testImportFileAssociation()977 	public void testImportFileAssociation() throws CoreException {
978 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
979 		assertNull(contentTypeManager.findContentTypeFor("*.bug122217"));
980 		IPreferencesService service = Platform.getPreferencesService();
981 		String prefs = "file_export_version=3.0\n/instance/org.eclipse.core.runtime/content-types/org.eclipse.core.runtime.xml/file-extensions=bug122217";
982 		IExportedPreferences exported = service.readPreferences(new ByteArrayInputStream(prefs.getBytes()));
983 		assertTrue(service.applyPreferences(exported).isOK());
984 		assertNotNull(contentTypeManager.findContentTypeFor("*.bug122217"));
985 	}
986 
987 	@Test
testInvalidMarkup()988 	public void testInvalidMarkup() {
989 		final IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
990 		IContentTypeMatcher finder = contentTypeManager.getMatcher(new LocalSelectionPolicy(), null);
991 		assertEquals("1.0", 0, finder.findContentTypesFor("invalid.missing.identifier").length);
992 		assertEquals("2.0", 0, finder.findContentTypesFor("invalid.missing.name").length);
993 		assertNull("3.0", contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "invalid-missing-name"));
994 		TestRegistryChangeListener listener = new TestRegistryChangeListener(Platform.PI_RUNTIME,
995 				ContentTypeBuilder.PT_CONTENTTYPES, null, null);
996 		BundleTestingHelper.runWithBundles("1", () -> {
997 			// ensure the invalid content types are not available
998 			assertEquals("1.2", 0, contentTypeManager.findContentTypesFor("invalid.missing.identifier").length);
999 			assertEquals("1.3", 0, contentTypeManager.findContentTypesFor("invalid.missing.name").length);
1000 			assertNull("1.4", contentTypeManager.getContentType("org.eclipse.bundle03.invalid-missing-name"));
1001 			// this content type has good markup, but invalid describer class
1002 			IContentType invalidDescriber = contentTypeManager.getContentType("org.eclipse.bundle03.invalid-describer");
1003 			assertNotNull("1.5", invalidDescriber);
1004 			// name based matching should work fine
1005 			assertEquals("1.6", invalidDescriber, contentTypeManager.findContentTypeFor("invalid.describer"));
1006 			// the describer class is invalid, content matchong should fail
1007 			IContentType nullContentType;
1008 			try {
1009 				nullContentType = contentTypeManager.findContentTypeFor(getRandomContents(), "invalid.describer");
1010 			} catch (IOException e) {
1011 				throw new AssertionError(e);
1012 			}
1013 			assertNull("1.7", nullContentType);
1014 		}, getContext(), new String[] { ContentTypeTest.TEST_FILES_ROOT + "content/bundle03" }, listener);
1015 	}
1016 
1017 	/**
1018 	 * Bugs 67841 and 62443
1019 	 */
1020 	@Test
testIOException()1021 	public void testIOException() throws IOException {
1022 		IContentTypeManager manager = Platform.getContentTypeManager();
1023 		IContentType xml = manager.getContentType(Platform.PI_RUNTIME + ".xml");
1024 		IContentType rootElement = manager.getContentType(PI_RESOURCES_TESTS + ".root-element");
1025 		// a SAXException is usually caught (and silently ignored) in
1026 		// XMLRootElementDescriber in these cases
1027 		IContentType[] selected = manager
1028 				.findContentTypesFor(getInputStream(XML_US_ASCII_INVALID, StandardCharsets.ISO_8859_1), "test.xml");
1029 		assertTrue("1.1", contains(selected, xml));
1030 		assertTrue("1.2", contains(selected, rootElement));
1031 
1032 		// induce regular IOExceptions... these should be thrown to clients
1033 		class FakeIOException extends IOException {
1034 			/**
1035 			 * All serializable objects should have a stable serialVersionUID
1036 			 */
1037 			private static final long serialVersionUID = 1L;
1038 
1039 			@Override
1040 			public String getMessage() {
1041 				return "This exception was thrown for testing purposes";
1042 			}
1043 		}
1044 		assertThrows(FakeIOException.class, () -> manager.findContentTypesFor(new InputStream() {
1045 
1046 			@Override
1047 			public int available() {
1048 				// trick the client into reading the file
1049 				return Integer.MAX_VALUE;
1050 			}
1051 
1052 			@Override
1053 			public int read() throws IOException {
1054 				throw new FakeIOException();
1055 			}
1056 
1057 			@Override
1058 			public int read(byte[] b, int off, int len) throws IOException {
1059 				throw new FakeIOException();
1060 			}
1061 		}, "test.xml"));
1062 	}
1063 
1064 	@Test
testIsKindOf()1065 	public void testIsKindOf() {
1066 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
1067 		IContentType textContentType = contentTypeManager.getContentType(Platform.PI_RUNTIME + '.' + "text");
1068 		IContentType xmlContentType = contentTypeManager.getContentType(Platform.PI_RUNTIME + ".xml");
1069 		IContentType xmlBasedDifferentExtensionContentType = contentTypeManager
1070 				.getContentType(PI_RESOURCES_TESTS + '.' + "xml-based-different-extension");
1071 		IContentType xmlBasedSpecificNameContentType = contentTypeManager
1072 				.getContentType(PI_RESOURCES_TESTS + '.' + "xml-based-specific-name");
1073 		IContentType binaryContentType = contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "sample-binary1");
1074 		assertTrue("1.0", textContentType.isKindOf(textContentType));
1075 		assertTrue("2.0", xmlContentType.isKindOf(textContentType));
1076 		assertFalse("2.1", textContentType.isKindOf(xmlContentType));
1077 		assertTrue("2.2", xmlContentType.isKindOf(xmlContentType));
1078 		assertTrue("3.0", xmlBasedDifferentExtensionContentType.isKindOf(textContentType));
1079 		assertTrue("3.1", xmlBasedDifferentExtensionContentType.isKindOf(xmlContentType));
1080 		assertFalse("4.0", xmlBasedDifferentExtensionContentType.isKindOf(xmlBasedSpecificNameContentType));
1081 		assertFalse("5.0", binaryContentType.isKindOf(textContentType));
1082 	}
1083 
1084 	@Test
testListParsing()1085 	public void testListParsing() {
1086 		String[] list;
1087 		list = Util.parseItems(null);
1088 		assertEquals("0.0", 0, list.length);
1089 		list = Util.parseItems("");
1090 		assertEquals("1.0", 1, list.length);
1091 		assertEquals("1.1", "", list[0]);
1092 		list = Util.parseItems("foo");
1093 		assertEquals("2.0", 1, list.length);
1094 		assertEquals("2.1", "foo", list[0]);
1095 		list = Util.parseItems(",");
1096 		assertEquals("3.0", 2, list.length);
1097 		assertEquals("3.1", "", list[0]);
1098 		assertEquals("3.2", "", list[1]);
1099 		list = Util.parseItems(",foo,bar");
1100 		assertEquals("4.0", 3, list.length);
1101 		assertEquals("4.1", "", list[0]);
1102 		assertEquals("4.2", "foo", list[1]);
1103 		assertEquals("4.3", "bar", list[2]);
1104 		list = Util.parseItems("foo,bar,");
1105 		assertEquals("5.0", 3, list.length);
1106 		assertEquals("5.1", "foo", list[0]);
1107 		assertEquals("5.2", "bar", list[1]);
1108 		assertEquals("5.3", "", list[2]);
1109 		list = Util.parseItems("foo,,bar");
1110 		assertEquals("6.0", 3, list.length);
1111 		assertEquals("6.1", "foo", list[0]);
1112 		assertEquals("6.2", "", list[1]);
1113 		assertEquals("6.3", "bar", list[2]);
1114 		list = Util.parseItems("foo,,,bar");
1115 		assertEquals("7.0", 4, list.length);
1116 		assertEquals("7.1", "foo", list[0]);
1117 		assertEquals("7.2", "", list[1]);
1118 		assertEquals("7.3", "", list[2]);
1119 		assertEquals("7.4", "bar", list[3]);
1120 		list = Util.parseItems(",,foo,bar");
1121 		assertEquals("8.0", 4, list.length);
1122 		assertEquals("8.1", "", list[0]);
1123 		assertEquals("8.2", "", list[1]);
1124 		assertEquals("8.3", "foo", list[2]);
1125 		assertEquals("8.4", "bar", list[3]);
1126 		list = Util.parseItems("foo,bar,,");
1127 		assertEquals("9.0", 4, list.length);
1128 		assertEquals("9.1", "foo", list[0]);
1129 		assertEquals("9.2", "bar", list[1]);
1130 		assertEquals("9.3", "", list[2]);
1131 		assertEquals("9.4", "", list[3]);
1132 		list = Util.parseItems(",,,");
1133 		assertEquals("10.0", 4, list.length);
1134 		assertEquals("10.1", "", list[0]);
1135 		assertEquals("10.2", "", list[1]);
1136 		assertEquals("10.3", "", list[2]);
1137 		assertEquals("10.4", "", list[3]);
1138 	}
1139 
1140 	@Test
testMyContentDescriber()1141 	public void testMyContentDescriber() throws IOException {
1142 		IContentTypeManager manager = Platform.getContentTypeManager();
1143 		IContentType myContent = manager.getContentType(PI_RESOURCES_TESTS + '.' + "myContent");
1144 		assertNotNull("0.5", myContent);
1145 		assertEquals("0.6", myContent, manager.findContentTypeFor("myContent.mc1"));
1146 		assertEquals("0.7", myContent, manager.findContentTypeFor("myContent.mc2"));
1147 		assertEquals("0.8", myContent, manager.findContentTypeFor("foo.myContent1"));
1148 		assertEquals("0.9", myContent, manager.findContentTypeFor("bar.myContent2"));
1149 		IContentDescription description = manager.getDescriptionFor(
1150 				getInputStream(MyContentDescriber.SIGNATURE, StandardCharsets.US_ASCII), "myContent.mc1",
1151 				IContentDescription.ALL);
1152 		assertNotNull("1.0", description);
1153 		assertEquals("1.1", myContent, description.getContentType());
1154 		assertNotSame("1.2", myContent.getDefaultDescription(), description);
1155 		for (int i = 0; i < MyContentDescriber.MY_OPTIONS.length; i++) {
1156 			assertEquals("2." + i, MyContentDescriber.MY_OPTION_VALUES[i],
1157 					description.getProperty(MyContentDescriber.MY_OPTIONS[i]));
1158 		}
1159 	}
1160 
1161 	@Test
testNoExtensionAssociation()1162 	public void testNoExtensionAssociation() {
1163 		// TODO use a IContentTypeMatcher instead
1164 		final IContentTypeManager manager = Platform.getContentTypeManager();
1165 
1166 		IContentType[] selected = manager.findContentTypesFor("file_with_no_extension");
1167 		assertEquals("0.1", 0, selected.length);
1168 
1169 		TestRegistryChangeListener listener = new TestRegistryChangeListener(Platform.PI_RUNTIME,
1170 				ContentTypeBuilder.PT_CONTENTTYPES, null, null);
1171 		BundleTestingHelper.runWithBundles("1", () -> {
1172 			final String namespace = "org.eclipse.bundle04";
1173 
1174 			IContentType empty1 = manager.getContentType(namespace + ".empty_extension1");
1175 			IContentType empty2 = manager.getContentType(namespace + ".empty_extension2");
1176 			IContentType empty3 = manager.getContentType(namespace + ".empty_extension3");
1177 			IContentType empty4 = manager.getContentType(namespace + ".empty_extension4");
1178 			IContentType nonEmpty = manager.getContentType(namespace + ".non_empty_extension");
1179 
1180 			assertNotNull("1.1.1", empty1);
1181 			assertNotNull("1.1.2", empty2);
1182 			assertNotNull("1.1.3", empty3);
1183 			assertNotNull("1.1.4", empty4);
1184 			assertNotNull("1.1.5", nonEmpty);
1185 
1186 			IContentType[] selected1 = manager.findContentTypesFor("file_with_no_extension");
1187 			assertEquals("1.2.0", 4, selected1.length);
1188 			assertTrue("1.2.1", contains(selected1, empty1));
1189 			assertTrue("1.2.2", contains(selected1, empty2));
1190 			assertTrue("1.2.3", contains(selected1, empty3));
1191 			assertTrue("1.2.4", contains(selected1, empty4));
1192 
1193 			selected1 = manager.findContentTypesFor("file_with_extension.non-empty");
1194 			assertEquals("1.2.5", 1, selected1.length);
1195 			assertTrue("1.2.6", contains(selected1, nonEmpty));
1196 
1197 			try {
1198 				nonEmpty.addFileSpec("", IContentType.FILE_EXTENSION_SPEC);
1199 			} catch (CoreException e) {
1200 				throw new AssertionError(e);
1201 			}
1202 			try {
1203 				selected1 = manager.findContentTypesFor("file_with_no_extension");
1204 				assertEquals("1.3.1", 5, selected1.length);
1205 				assertTrue("1.3.2", contains(selected1, nonEmpty));
1206 			} finally {
1207 				try {
1208 					nonEmpty.removeFileSpec("", IContentType.FILE_EXTENSION_SPEC);
1209 				} catch (CoreException e) {
1210 					throw new AssertionError(e);
1211 				}
1212 			}
1213 			selected1 = manager.findContentTypesFor("file_with_no_extension");
1214 			assertEquals("1.4.0", 4, selected1.length);
1215 			assertFalse("1.4.1", contains(selected1, nonEmpty));
1216 		}, getContext(), new String[] { ContentTypeTest.TEST_FILES_ROOT + "content/bundle04" }, listener);
1217 	}
1218 
1219 	@Test
testOrderWithEmptyFiles()1220 	public void testOrderWithEmptyFiles() throws IOException {
1221 		IContentTypeManager manager = Platform.getContentTypeManager();
1222 		IContentTypeMatcher finder = manager.getMatcher(new LocalSelectionPolicy(), null);
1223 
1224 		IContentType xml = manager.getContentType(Platform.PI_RUNTIME + ".xml");
1225 		manager.getContentType(PI_RESOURCES_TESTS + ".root-element");
1226 		manager.getContentType(PI_RESOURCES_TESTS + ".dtd");
1227 		// for an empty file, the most generic content type should be returned
1228 		IContentType selected = finder.findContentTypeFor(getInputStream(""), "foo.xml");
1229 		assertEquals("1.0", xml, selected);
1230 		// it should be equivalent to omitting the contents
1231 		assertEquals("1.1", xml, finder.findContentTypeFor("foo.xml"));
1232 	}
1233 
1234 	/**
1235 	 * This test shows how we deal with orphan file associations (associations whose
1236 	 * content types are missing).
1237 	 */
1238 	@Test
testOrphanContentType()1239 	public void testOrphanContentType() {
1240 		final IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
1241 		IContentType orphan = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".orphan");
1242 		assertNull("0.8", orphan);
1243 		IContentType missing = contentTypeManager.getContentType("org.eclipse.bundle01.missing");
1244 		assertNull("0.9", missing);
1245 		assertEquals("1.1", 0, contentTypeManager.findContentTypesFor("foo.orphan").length);
1246 		assertEquals("1.2", 0, contentTypeManager.findContentTypesFor("orphan.orphan").length);
1247 		assertEquals("1.3", 0, contentTypeManager.findContentTypesFor("foo.orphan2").length);
1248 
1249 		// test late addition of content type - orphan2 should become visible
1250 		TestRegistryChangeListener listener = new TestRegistryChangeListener(Platform.PI_RUNTIME,
1251 				ContentTypeBuilder.PT_CONTENTTYPES, null, null);
1252 
1253 		BundleTestingHelper.runWithBundles("2", () -> {
1254 			IContentType orphan1 = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".orphan");
1255 			assertNotNull("2.1", orphan1);
1256 			IContentType missing1 = contentTypeManager.getContentType("org.eclipse.bundle01.missing");
1257 			assertNotNull("2.2", missing1);
1258 			// checks orphan's associations
1259 			assertEquals("2.3", 1, contentTypeManager.findContentTypesFor("foo.orphan").length);
1260 			assertEquals("2.4", orphan1, contentTypeManager.findContentTypesFor("foo.orphan")[0]);
1261 			assertEquals("2.5", 1, contentTypeManager.findContentTypesFor("orphan.orphan").length);
1262 			assertEquals("2.6", orphan1, contentTypeManager.findContentTypesFor("foo.orphan")[0]);
1263 			// check whether an orphan association was added to the dynamically added bundle
1264 			assertEquals("2.7", 1, contentTypeManager.findContentTypesFor("foo.orphan2").length);
1265 			assertEquals("2.8", missing1, contentTypeManager.findContentTypesFor("foo.orphan2")[0]);
1266 		}, getContext(), new String[] { ContentTypeTest.TEST_FILES_ROOT + "content/bundle01" }, listener);
1267 	}
1268 
1269 	/**
1270 	 * Regression test for bug 68894
1271 	 */
1272 	@Test
testPreferences()1273 	public void testPreferences() throws CoreException, BackingStoreException {
1274 		IContentTypeManager manager = Platform.getContentTypeManager();
1275 		IContentType text = manager.getContentType(IContentTypeManager.CT_TEXT);
1276 		Preferences textPrefs = InstanceScope.INSTANCE.getNode(ContentTypeManager.CONTENT_TYPE_PREF_NODE)
1277 				.node(text.getId());
1278 		assertNotNull("0.1", text);
1279 
1280 		// ensure the "default charset" preference is being properly used
1281 		assertNull("1.0", text.getDefaultCharset());
1282 		assertNull("1.1", textPrefs.get(ContentType.PREF_DEFAULT_CHARSET, null));
1283 		text.setDefaultCharset("UTF-8");
1284 		assertEquals("1.2", "UTF-8", textPrefs.get(ContentType.PREF_DEFAULT_CHARSET, null));
1285 		text.setDefaultCharset(null);
1286 		assertNull("1.3", textPrefs.get(ContentType.PREF_DEFAULT_CHARSET, null));
1287 
1288 		// ensure the file spec preferences are being properly used
1289 		// some sanity checking
1290 		assertFalse("2.01", text.isAssociatedWith("xyz.foo"));
1291 		assertFalse("2.01", text.isAssociatedWith("xyz.bar"));
1292 		assertFalse("2.03", text.isAssociatedWith("foo.ext"));
1293 		assertFalse("2.04", text.isAssociatedWith("bar.ext"));
1294 		// Null entries first to avoid interference from other tests
1295 		textPrefs.remove(ContentType.PREF_FILE_NAMES);
1296 		textPrefs.remove(ContentType.PREF_FILE_EXTENSIONS);
1297 		// play with file name associations first...
1298 		assertNull("2.0a", textPrefs.get(ContentType.PREF_FILE_NAMES, null));
1299 		assertNull("2.0b", textPrefs.get(ContentType.PREF_FILE_EXTENSIONS, null));
1300 		text.addFileSpec("foo.ext", IContentType.FILE_NAME_SPEC);
1301 		assertTrue("2.1", text.isAssociatedWith("foo.ext"));
1302 		assertEquals("2.2", "foo.ext", textPrefs.get(ContentType.PREF_FILE_NAMES, null));
1303 		text.addFileSpec("bar.ext", IContentType.FILE_NAME_SPEC);
1304 		assertTrue("2.3", text.isAssociatedWith("bar.ext"));
1305 		assertEquals("2.4", "foo.ext,bar.ext", textPrefs.get(ContentType.PREF_FILE_NAMES, null));
1306 		// ... and then with file extensions
1307 		text.addFileSpec("foo", IContentType.FILE_EXTENSION_SPEC);
1308 		assertTrue("2.5", text.isAssociatedWith("xyz.foo"));
1309 		assertEquals("2.6", "foo", textPrefs.get(ContentType.PREF_FILE_EXTENSIONS, null));
1310 		text.addFileSpec("bar", IContentType.FILE_EXTENSION_SPEC);
1311 		assertTrue("2.7", text.isAssociatedWith("xyz.bar"));
1312 		assertEquals("2.4", "foo,bar", textPrefs.get(ContentType.PREF_FILE_EXTENSIONS, null));
1313 		// remove all associations made
1314 		text.removeFileSpec("foo.ext", IContentType.FILE_NAME_SPEC);
1315 		text.removeFileSpec("bar.ext", IContentType.FILE_NAME_SPEC);
1316 		text.removeFileSpec("foo", IContentType.FILE_EXTENSION_SPEC);
1317 		text.removeFileSpec("bar", IContentType.FILE_EXTENSION_SPEC);
1318 		// ensure all is as before
1319 		assertFalse("3.1", text.isAssociatedWith("xyz.foo"));
1320 		assertFalse("3.2", text.isAssociatedWith("xyz.bar"));
1321 		assertFalse("3.3", text.isAssociatedWith("foo.ext"));
1322 		assertFalse("3.4", text.isAssociatedWith("bar.ext"));
1323 
1324 		// ensure the serialization format is correct
1325 		try {
1326 			text.addFileSpec("foo.bar", IContentType.FILE_NAME_SPEC);
1327 			textPrefs.sync();
1328 			assertEquals("4.0", "foo.bar", textPrefs.get(ContentType.PREF_FILE_NAMES, null));
1329 		} finally {
1330 			// clean-up
1331 			text.removeFileSpec("foo.bar", IContentType.FILE_NAME_SPEC);
1332 		}
1333 	}
1334 
1335 	@Test
testRegistry()1336 	public void testRegistry() {
1337 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
1338 		IContentTypeMatcher finder = contentTypeManager.getMatcher(new LocalSelectionPolicy(), null);
1339 
1340 		IContentType textContentType = contentTypeManager.getContentType(Platform.PI_RUNTIME + '.' + "text");
1341 		assertNotNull("1.0", textContentType);
1342 		assertTrue("1.1", isText(contentTypeManager, textContentType));
1343 		assertNotNull("1.2", ((ContentTypeHandler) textContentType).getTarget().getDescriber());
1344 
1345 		IContentType xmlContentType = contentTypeManager.getContentType(Platform.PI_RUNTIME + ".xml");
1346 		assertNotNull("2.0", xmlContentType);
1347 		assertTrue("2.1", isText(contentTypeManager, xmlContentType));
1348 		assertEquals("2.2", textContentType, xmlContentType.getBaseType());
1349 		IContentDescriber xmlDescriber = ((ContentTypeHandler) xmlContentType).getTarget().getDescriber();
1350 		assertNotNull("2.3", xmlDescriber);
1351 		assertTrue("2.4", xmlDescriber instanceof XMLContentDescriber);
1352 
1353 		IContentType xmlBasedDifferentExtensionContentType = contentTypeManager
1354 				.getContentType(PI_RESOURCES_TESTS + '.' + "xml-based-different-extension");
1355 		assertNotNull("3.0", xmlBasedDifferentExtensionContentType);
1356 		assertTrue("3.1", isText(contentTypeManager, xmlBasedDifferentExtensionContentType));
1357 		assertEquals("3.2", xmlContentType, xmlBasedDifferentExtensionContentType.getBaseType());
1358 
1359 		IContentType xmlBasedSpecificNameContentType = contentTypeManager
1360 				.getContentType(PI_RESOURCES_TESTS + '.' + "xml-based-specific-name");
1361 		assertNotNull("4.0", xmlBasedSpecificNameContentType);
1362 		assertTrue("4.1", isText(contentTypeManager, xmlBasedSpecificNameContentType));
1363 		assertEquals("4.2", xmlContentType, xmlBasedSpecificNameContentType.getBaseType());
1364 
1365 		IContentType[] xmlTypes = finder.findContentTypesFor(changeCase("foo.xml"));
1366 		assertTrue("5.1", contains(xmlTypes, xmlContentType));
1367 
1368 		IContentType binaryContentType = contentTypeManager.getContentType(PI_RESOURCES_TESTS + '.' + "sample-binary1");
1369 		assertNotNull("6.0", binaryContentType);
1370 		assertFalse("6.1", isText(contentTypeManager, binaryContentType));
1371 		assertNull("6.2", binaryContentType.getBaseType());
1372 
1373 		IContentType[] binaryTypes = finder.findContentTypesFor(changeCase("foo.samplebin1"));
1374 		assertEquals("7.0", 1, binaryTypes.length);
1375 		assertEquals("7.1", binaryContentType, binaryTypes[0]);
1376 
1377 		IContentType myText = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".mytext");
1378 		assertNotNull("8.0", myText);
1379 		assertEquals("8.1", "BAR", myText.getDefaultCharset());
1380 
1381 		IContentType[] fooBarTypes = finder.findContentTypesFor(changeCase("foo.bar"));
1382 		assertEquals("9.0", 2, fooBarTypes.length);
1383 
1384 		IContentType fooBar = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".fooBar");
1385 		assertNotNull("9.1", fooBar);
1386 		IContentType subFooBar = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".subFooBar");
1387 		assertNotNull("9.2", subFooBar);
1388 		assertTrue("9.3", contains(fooBarTypes, fooBar));
1389 		assertTrue("9.4", contains(fooBarTypes, subFooBar));
1390 	}
1391 
1392 	@Test
testRootElementAndDTDDescriber()1393 	public void testRootElementAndDTDDescriber() throws IOException {
1394 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
1395 		IContentType rootElement = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".root-element");
1396 		IContentType dtdElement = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".dtd");
1397 		IContentType nsRootElement = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".ns-root-element");
1398 		IContentType nsWildcard = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".ns-wildcard");
1399 		IContentType emptyNsRootElement = contentTypeManager
1400 				.getContentType(PI_RESOURCES_TESTS + ".empty-ns-root-element");
1401 		IContentType xmlType = contentTypeManager.getContentType(Platform.PI_RUNTIME + ".xml");
1402 
1403 		IContentType[] contentTypes = contentTypeManager.findContentTypesFor(
1404 				getInputStream(XML_ROOT_ELEMENT_ISO_8859_1, StandardCharsets.ISO_8859_1), "fake.xml");
1405 		assertTrue("1.0", contentTypes.length > 0);
1406 		assertEquals("1.1", rootElement, contentTypes[0]);
1407 
1408 		// bugs 64053 and 63298
1409 		contentTypes = contentTypeManager.findContentTypesFor(
1410 				getInputStream(XML_ROOT_ELEMENT_EXTERNAL_ENTITY, StandardCharsets.UTF_8), "fake.xml");
1411 		assertTrue("2.0", contentTypes.length > 0);
1412 		assertEquals("2.1", rootElement, contentTypes[0]);
1413 
1414 		// bug 63625
1415 		contentTypes = contentTypeManager.findContentTypesFor(
1416 				getInputStream(XML_ROOT_ELEMENT_EXTERNAL_ENTITY2, StandardCharsets.UTF_8), "fake.xml");
1417 		assertTrue("3.0", contentTypes.length > 0);
1418 		assertEquals("3.1", rootElement, contentTypes[0]);
1419 
1420 		// bug 135575
1421 		contentTypes = contentTypeManager
1422 				.findContentTypesFor(getInputStream(XML_ROOT_ELEMENT_NS_MATCH1, StandardCharsets.UTF_8), "fake.xml");
1423 		assertTrue("4.0", contentTypes.length > 0);
1424 		assertEquals("4.1", nsRootElement, contentTypes[0]);
1425 		contentTypes = contentTypeManager
1426 				.findContentTypesFor(getInputStream(XML_ROOT_ELEMENT_NS_MATCH2, StandardCharsets.UTF_8), "fake.xml");
1427 		assertTrue("4.2", contentTypes.length > 0);
1428 		assertEquals("4.3", nsRootElement, contentTypes[0]);
1429 		contentTypes = contentTypeManager.findContentTypesFor(
1430 				getInputStream(XML_ROOT_ELEMENT_NS_WRONG_ELEM, StandardCharsets.UTF_8), "fake.xml");
1431 		assertTrue("4.4", contentTypes.length > 0);
1432 		assertEquals("4.5", xmlType, contentTypes[0]);
1433 		contentTypes = contentTypeManager
1434 				.findContentTypesFor(getInputStream(XML_ROOT_ELEMENT_NS_WRONG_NS, StandardCharsets.UTF_8), "fake.xml");
1435 		assertTrue("4.6", contentTypes.length > 0);
1436 		assertEquals("4.7", xmlType, contentTypes[0]);
1437 		contentTypes = contentTypeManager
1438 				.findContentTypesFor(getInputStream(XML_ROOT_ELEMENT_NS_MIXUP, StandardCharsets.UTF_8), "fake.xml");
1439 		assertTrue("4.8", contentTypes.length > 0);
1440 		assertEquals("4.9", xmlType, contentTypes[0]);
1441 		contentTypes = contentTypeManager
1442 				.findContentTypesFor(getInputStream(XML_ROOT_ELEMENT_NS_WILDCARD, StandardCharsets.UTF_8), "fake.xml");
1443 		assertTrue("4.10", contentTypes.length > 0);
1444 		assertEquals("4.11", nsWildcard, contentTypes[0]);
1445 		contentTypes = contentTypeManager
1446 				.findContentTypesFor(getInputStream(XML_ROOT_ELEMENT_NS_WILDCARD2, StandardCharsets.UTF_8), "fake.xml");
1447 		assertTrue("4.12", contentTypes.length > 0);
1448 		assertEquals("4.13", nsWildcard, contentTypes[0]);
1449 		contentTypes = contentTypeManager
1450 				.findContentTypesFor(getInputStream(XML_ROOT_ELEMENT_EMPTY_NS, StandardCharsets.UTF_8), "fake.xml");
1451 		assertTrue("4.14", contentTypes.length > 0);
1452 		assertEquals("4.15", emptyNsRootElement, contentTypes[0]);
1453 
1454 		contentTypes = contentTypeManager
1455 				.findContentTypesFor(getInputStream(XML_DTD_US_ASCII, StandardCharsets.US_ASCII), "fake.xml");
1456 		assertTrue("5.0", contentTypes.length > 0);
1457 		assertEquals("5.1", dtdElement, contentTypes[0]);
1458 		contentTypes = contentTypeManager
1459 				.findContentTypesFor(getInputStream(XML_DTD_EXTERNAL_ENTITY, StandardCharsets.UTF_8), "fake.xml");
1460 		assertTrue("5.4", contentTypes.length > 0);
1461 		assertEquals("5.5", dtdElement, contentTypes[0]);
1462 
1463 		// bug 67975
1464 		IContentDescription description = contentTypeManager.getDescriptionFor(getInputStream(
1465 				new byte[][] { IContentDescription.BOM_UTF_16BE, XML_ROOT_ELEMENT_NO_DECL.getBytes("UTF-16BE") }),
1466 				"fake.xml", IContentDescription.ALL);
1467 		assertNotNull("6.0", description);
1468 		assertEquals("6.1", rootElement, description.getContentType());
1469 		assertEquals("6.2", IContentDescription.BOM_UTF_16BE,
1470 				description.getProperty(IContentDescription.BYTE_ORDER_MARK));
1471 
1472 		description = contentTypeManager.getDescriptionFor(getInputStream(
1473 				new byte[][] { IContentDescription.BOM_UTF_16LE, XML_ROOT_ELEMENT_NO_DECL.getBytes("UTF-16LE") }),
1474 				"fake.xml", IContentDescription.ALL);
1475 		assertNotNull("7.0", description);
1476 		assertEquals("7.1", rootElement, description.getContentType());
1477 		assertEquals("7.2", IContentDescription.BOM_UTF_16LE,
1478 				description.getProperty(IContentDescription.BYTE_ORDER_MARK));
1479 
1480 		// due to bug 67048, the test below fails with Crimson parser (does not handle
1481 		// UTF-8 BOMs)
1482 		// description = contentTypeManager.getDescriptionFor(getInputStream(new
1483 		// byte[][]
1484 		// {IContentDescription.BOM_UTF_8,XML_ROOT_ELEMENT_NO_DECL.getBytes("UTF-8")}),
1485 		// "fake.xml", IContentDescription.ALL);
1486 		// assertTrue("7.0", description != null);
1487 		// assertEquals("7.1", rootElement, description.getContentType());
1488 		// assertEquals("7.2", IContentDescription.BOM_UTF_8,
1489 		// description.getProperty(IContentDescription.BYTE_ORDER_MARK));
1490 
1491 		// bug 84354
1492 		contentTypes = contentTypeManager
1493 				.findContentTypesFor(getInputStream(XML_ROOT_ELEMENT_NO_DECL, StandardCharsets.UTF_8), "test.txt");
1494 		assertTrue("8.0", contentTypes.length > 0);
1495 		assertEquals("8.1", contentTypeManager.getContentType(IContentTypeManager.CT_TEXT), contentTypes[0]);
1496 	}
1497 
1498 	/**
1499 	 * Bug 66976
1500 	 */
1501 	@Test
testSignatureBeyondBufferLimit()1502 	public void testSignatureBeyondBufferLimit() throws IOException {
1503 		int bufferLimit = ContentTypeManager.BLOCK_SIZE * 4;
1504 		// create a long XML comment as prefix
1505 		StringBuilder comment = new StringBuilder("<!--");
1506 		for (int i = 0; i < bufferLimit; i++) {
1507 			comment.append('*');
1508 		}
1509 		comment.append("-->");
1510 		IContentTypeManager manager = Platform.getContentTypeManager();
1511 		IContentType rootElement = manager.getContentType(PI_RESOURCES_TESTS + ".root-element");
1512 		IContentType selected = manager.findContentTypeFor(
1513 				getInputStream(comment + XML_ROOT_ELEMENT_NO_DECL, StandardCharsets.US_ASCII), "fake.xml");
1514 		assertNotNull("1.0", selected);
1515 		assertEquals("1.1", rootElement, selected);
1516 	}
1517 
1518 	/**
1519 	 * See also: bug 72796.
1520 	 */
1521 	@Test
testUserDefinedAssociations()1522 	public void testUserDefinedAssociations() throws CoreException {
1523 		IContentTypeManager manager = Platform.getContentTypeManager();
1524 		IContentType text = manager.getContentType((Platform.PI_RUNTIME + ".text"));
1525 
1526 		assertNull("0.1", manager.findContentTypeFor("test.mytext"));
1527 		// associate a user-defined file spec
1528 		text.addFileSpec("mytext", IContentType.FILE_EXTENSION_SPEC);
1529 		boolean assertionFailed = false;
1530 		try {
1531 			IContentType result = manager.findContentTypeFor("test.mytext");
1532 			assertNotNull("1.1", result);
1533 			assertEquals("1.2", text, result);
1534 		} catch (AssertionError afe) {
1535 			assertionFailed = true;
1536 			throw afe;
1537 		} finally {
1538 			text.removeFileSpec("mytext", IContentType.FILE_EXTENSION_SPEC);
1539 			assertFalse(assertionFailed);
1540 		}
1541 		IContentType result = manager.findContentTypeFor("test.mytext");
1542 		assertNull("3.0", result);
1543 	}
1544 
1545 	@Test
testDescriberInvalidation()1546 	public void testDescriberInvalidation() throws IOException {
1547 		IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
1548 		IContentType type_bug182337_A = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".Bug182337_A");
1549 		IContentType type_bug182337_B = contentTypeManager.getContentType(PI_RESOURCES_TESTS + ".Bug182337_B");
1550 
1551 		IContentType[] contentTypes = contentTypeManager.findContentTypesFor(
1552 				getInputStream(XML_ROOT_ELEMENT_NS_MATCH2, StandardCharsets.UTF_8), "Bug182337.Bug182337");
1553 		assertEquals("1.0", 2, contentTypes.length);
1554 		assertEquals("1.1", type_bug182337_A, contentTypes[0]);
1555 		assertEquals("1.1", type_bug182337_B, contentTypes[1]);
1556 
1557 		InputStream is = new InputStream() {
1558 			@Override
1559 			public int read() {
1560 				// throw a non checked exception to emulate a problem with the describer itself
1561 				throw new RuntimeException();
1562 			}
1563 		};
1564 		contentTypes = contentTypeManager.findContentTypesFor(is, "Bug182337.Bug182337");
1565 		assertEquals("1.2", 0, contentTypes.length);
1566 
1567 		// Describer should be invalidated by now
1568 		contentTypes = contentTypeManager.findContentTypesFor(
1569 				getInputStream(XML_ROOT_ELEMENT_NS_MATCH2, StandardCharsets.UTF_8), "Bug182337.Bug182337");
1570 		assertEquals("1.3", 0, contentTypes.length);
1571 	}
1572 
1573 }
1574