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