/******************************************************************************* * Copyright (c) 2005, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.core.tests.resources; import java.io.ByteArrayInputStream; import java.io.InputStream; import junit.framework.Test; import junit.framework.TestSuite; import org.eclipse.core.internal.content.*; import org.eclipse.core.internal.resources.ContentDescriptionManager; import org.eclipse.core.internal.resources.Workspace; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.content.*; import org.eclipse.core.runtime.jobs.Job; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; public class ContentDescriptionManagerTest extends ResourceTest { private static final String CONTENT_TYPE_RELATED_NATURE1 = "org.eclipse.core.tests.resources.contentTypeRelated1"; private static final String CONTENT_TYPE_RELATED_NATURE2 = "org.eclipse.core.tests.resources.contentTypeRelated2"; public static Test suite() { return new TestSuite(ContentDescriptionManagerTest.class); } /** * Blocks the calling thread until the cache flush job completes. */ public static void waitForCacheFlush() { try { Job.getJobManager().join(ContentDescriptionManager.FAMILY_DESCRIPTION_CACHE_FLUSH, null); } catch (OperationCanceledException e) { //ignore } catch (InterruptedException e) { //ignore } } public ContentDescriptionManagerTest(String name) { super(name); } private IContentDescription getDescription(String tag, IFile file) { IContentDescription description; description = null; try { description = file.getContentDescription(); } catch (CoreException e) { fail(tag, e); } return description; } protected InputStream projectDescriptionWithNatures(String project, String[] natures) { StringBuffer contents = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?><projectDescription><name>" + project + "</name><natures>"); for (String nature : natures) { contents.append("<nature>" + nature + "</nature>"); } contents.append("</natures></projectDescription>"); return new ByteArrayInputStream(contents.toString().getBytes()); } /** * Ensure we react to changes to the content type registry in an appropriated way. */ public void testBug79151() { IWorkspace workspace = getWorkspace(); IProject project = workspace.getRoot().getProject("MyProject"); IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); IContentType xml = contentTypeManager.getContentType("org.eclipse.core.runtime.xml"); String newExtension = "xml_bug_79151"; IFile file1 = project.getFile("file.xml"); IFile file2 = project.getFile("file." + newExtension); ensureExistsInWorkspace(file1, getContents(CharsetTest.SAMPLE_XML_ISO_8859_1_ENCODING)); ensureExistsInWorkspace(file2, getContents(CharsetTest.SAMPLE_XML_US_ASCII_ENCODING)); // ensure we start in a known state ((Workspace) workspace).getContentDescriptionManager().invalidateCache(true, null); // wait for cache flush to finish waitForCacheFlush(); // cache is new at this point assertEquals("0.9", ContentDescriptionManager.EMPTY_CACHE, ((Workspace) workspace).getContentDescriptionManager().getCacheState()); IContentDescription description1a = null, description1b = null, description1c = null, description1d = null; IContentDescription description2 = null; description1a = getDescription("1.0a", file1); description2 = getDescription("1.0b", file2); assertNotNull("1.1", description1a); assertEquals("1.2", xml, description1a.getContentType()); assertNull("1.3", description2); description1b = getDescription("2.0", file1); // ensure it comes from the cache (should be the very same object) assertNotNull(" 2.1", description1b); assertSame("2.2", description1a, description1b); try { // change the content type xml.addFileSpec(newExtension, IContentType.FILE_EXTENSION_SPEC); } catch (CoreException e) { fail("3.0", e); } try { description1c = getDescription("4.0a", file1); description2 = getDescription("4.0b", file2); // ensure it does *not* come from the cache (should be a different object) assertNotNull("4.1", description1c); assertNotSame("4.2", description1a, description1c); assertEquals("4.3", xml, description1c.getContentType()); assertNotNull("4.4", description2); assertEquals("4.5", xml, description2.getContentType()); } finally { try { // dissociate the xml2 extension from the XML content type xml.removeFileSpec(newExtension, IContentType.FILE_EXTENSION_SPEC); } catch (CoreException e) { fail("4.99", e); } } description1d = getDescription("5.0a", file1); description2 = getDescription("5.0b", file2); // ensure it does *not* come from the cache (should be a different object) assertNotNull("5.1", description1d); assertNotSame("5.2", description1c, description1d); assertEquals("5.3", xml, description1d.getContentType()); assertNull("5.4", description2); } public void testBug94516() { IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); IContentType text = contentTypeManager.getContentType("org.eclipse.core.runtime.text"); assertNotNull("0.1", text); IProject project = getWorkspace().getRoot().getProject("proj1"); IFile unrelatedFile = project.getFile("file." + getName()); ensureExistsInWorkspace(unrelatedFile, ""); IContentDescription description = null; description = getDescription("0.7", unrelatedFile); assertNull("0.8", description); try { try { text.addFileSpec(unrelatedFile.getName(), IContentType.FILE_NAME_SPEC); } catch (CoreException e) { fail("0.99", e); } description = getDescription("1.0", unrelatedFile); assertNotNull("1.1", description); assertEquals("1.2", text, description.getContentType()); final ProjectScope projectScope = new ProjectScope(project); Preferences contentTypePrefs = projectScope.getNode(ContentTypeManager.CONTENT_TYPE_PREF_NODE); // enable project-specific settings for this project contentTypePrefs.putBoolean("enabled", true); try { contentTypePrefs.flush(); } catch (BackingStoreException e) { fail("1.99", e); } // global settings should not matter anymore description = getDescription("2.0", unrelatedFile); assertNull("2.1", description); IContentTypeSettings settings = null; try { settings = text.getSettings(projectScope); } catch (CoreException e) { fail("3.0", e); } assertNotNull("3.1", settings); assertNotSame("3.2", text, settings); assertTrue("3.3", settings instanceof ContentTypeSettings); try { settings.addFileSpec(unrelatedFile.getFullPath().getFileExtension(), IContentType.FILE_EXTENSION_SPEC); } catch (CoreException e) { fail("4.0", e); } try { contentTypePrefs.flush(); } catch (BackingStoreException e) { fail("4.1", e); } description = getDescription("5.0", unrelatedFile); assertNotNull("5.1", description); assertEquals("5.2", text, description.getContentType()); } finally { try { text.removeFileSpec(unrelatedFile.getName(), IContentType.FILE_NAME_SPEC); } catch (CoreException e) { fail("6.0", e); } } } /** * Ensures content type-nature associations work as expected. */ public void testNatureContentTypeAssociation() { IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); IContentType baseType = contentTypeManager.getContentType("org.eclipse.core.tests.resources.nature_associated_1"); IContentType derivedType = contentTypeManager.getContentType("org.eclipse.core.tests.resources.nature_associated_2"); assertNotNull("0.1", baseType); assertNotNull("0.2", derivedType); IProject project = getWorkspace().getRoot().getProject("proj1"); IFile file = project.getFile("file.nature-associated"); IFile descFile = project.getFile(IProjectDescription.DESCRIPTION_FILE_NAME); ensureExistsInWorkspace(file, "it really does not matter"); IContentDescription description = null; // originally, project description has no natures try { descFile.setContents(projectDescriptionWithNatures(project.getName(), new String[0]), IResource.FORCE, getMonitor()); } catch (CoreException e) { fail("1.0", e); } waitForCacheFlush(); description = getDescription("1.1", file); assertNotNull("1.2", description); assertSame("1.3", ((ContentTypeHandler) baseType).getTarget(), ((ContentTypeHandler) description.getContentType()).getTarget()); // change project description to include one of the natures try { descFile.setContents(projectDescriptionWithNatures(project.getName(), new String[] {CONTENT_TYPE_RELATED_NATURE1}), IResource.FORCE, getMonitor()); } catch (CoreException e) { fail("2.0", e); } waitForCacheFlush(); description = getDescription("2.1", file); assertNotNull("2.2", description); assertSame("2.3", ((ContentTypeHandler) baseType).getTarget(), ((ContentTypeHandler) description.getContentType()).getTarget()); // change project description to include the other nature try { descFile.setContents(projectDescriptionWithNatures(project.getName(), new String[] {CONTENT_TYPE_RELATED_NATURE2}), IResource.FORCE, getMonitor()); } catch (CoreException e) { fail("3.0", e); } waitForCacheFlush(); description = getDescription("3.1", file); assertNotNull("3.2", description); assertSame("3.3", ((ContentTypeHandler) derivedType).getTarget(), ((ContentTypeHandler) description.getContentType()).getTarget()); // change project description to include both of the natures try { descFile.setContents(projectDescriptionWithNatures(project.getName(), new String[] {CONTENT_TYPE_RELATED_NATURE1, CONTENT_TYPE_RELATED_NATURE2}), IResource.FORCE, getMonitor()); } catch (CoreException e) { fail("4.0", e); } waitForCacheFlush(); description = getDescription("4.1", file); assertNotNull("4.2", description); assertSame("4.3", ((ContentTypeHandler) baseType).getTarget(), ((ContentTypeHandler) description.getContentType()).getTarget()); // back to no natures try { descFile.setContents(projectDescriptionWithNatures(project.getName(), new String[0]), IResource.FORCE, getMonitor()); } catch (CoreException e) { fail("5.0", e); } waitForCacheFlush(); description = getDescription("5.1", file); assertNotNull("5.2", description); assertSame("5.3", ((ContentTypeHandler) baseType).getTarget(), ((ContentTypeHandler) description.getContentType()).getTarget()); } public void testProjectSpecificCharset() throws CoreException { IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); IContentType text = contentTypeManager.getContentType("org.eclipse.core.runtime.text"); IContentType xml = contentTypeManager.getContentType("org.eclipse.core.runtime.xml"); assertNotNull("0.1", text); assertNotNull("0.2", xml); IProject project = getWorkspace().getRoot().getProject("proj1"); IFile txtFile = project.getFile(getName() + ".txt"); IFile xmlFile = project.getFile(getName() + ".xml"); ensureExistsInWorkspace(txtFile, ""); ensureExistsInWorkspace(xmlFile, ""); project.setDefaultCharset("FOO", getMonitor()); assertEquals("1.0", "FOO", txtFile.getCharset()); assertEquals("1.1", "UTF-8", xmlFile.getCharset()); final ProjectScope projectScope = new ProjectScope(project); Preferences contentTypePrefs = projectScope.getNode(ContentTypeManager.CONTENT_TYPE_PREF_NODE); // enable project-specific settings for this project contentTypePrefs.putBoolean("enabled", true); try { contentTypePrefs.flush(); } catch (BackingStoreException e) { fail("2.0", e); } IContentTypeSettings settings = null; settings = text.getSettings(projectScope); settings.setDefaultCharset("BAR"); try { contentTypePrefs.flush(); } catch (BackingStoreException e) { fail("2.1", e); } assertEquals("3.0", "BAR", txtFile.getCharset()); assertEquals("3.1", "UTF-8", xmlFile.getCharset()); settings = xml.getSettings(projectScope); settings.setDefaultCharset(""); try { contentTypePrefs.flush(); } catch (BackingStoreException e) { fail("4.0", e); } assertEquals("4.1", "BAR", txtFile.getCharset()); assertEquals("4.2", "FOO", xmlFile.getCharset()); } public void testProjectSpecificFileAssociations() { IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); IContentType text = contentTypeManager.getContentType("org.eclipse.core.runtime.text"); IContentType xml = contentTypeManager.getContentType("org.eclipse.core.runtime.xml"); assertNotNull("0.1", text); assertNotNull("0.2", xml); IProject project = getWorkspace().getRoot().getProject("proj1"); IFile txtFile = project.getFile(getName() + ".txt"); IFile xmlFile = project.getFile(getName() + ".xml"); IFile unrelatedFile = project.getFile("file." + getName()); ensureExistsInWorkspace(txtFile, ""); ensureExistsInWorkspace(xmlFile, ""); ensureExistsInWorkspace(unrelatedFile, ""); IContentDescription description = null; description = getDescription("0.7a", txtFile); assertNotNull("0.7b", description); assertEquals("0.7c", text, description.getContentType()); description = getDescription("0.8a", xmlFile); assertNotNull("0.8b", description); assertEquals("0.8c", xml, description.getContentType()); assertNull("0.9b", getDescription("0.9a", unrelatedFile)); final ProjectScope projectScope = new ProjectScope(project); Preferences contentTypePrefs = projectScope.getNode(ContentTypeManager.CONTENT_TYPE_PREF_NODE); // enable project-specific settings for this project contentTypePrefs.putBoolean("enabled", true); try { contentTypePrefs.flush(); } catch (BackingStoreException e) { fail("0.99", e); } // there are no local settings yet, everything should be the same description = getDescription("1.0a", txtFile); assertNotNull("1.0b", description); assertEquals("1.0c", text, description.getContentType()); description = getDescription("1.1a", xmlFile); assertNotNull("1.1b", description); assertEquals("1.1c", xml, description.getContentType()); assertNull("1.2b", getDescription("1.2a", unrelatedFile)); IContentTypeSettings settings = null; try { settings = text.getSettings(projectScope); } catch (CoreException e) { fail("2.0", e); } assertNotNull("2.1", settings); assertNotSame("2.2", text, settings); assertTrue("2.3", settings instanceof ContentTypeSettings); try { settings.addFileSpec(getName(), IContentTypeSettings.FILE_EXTENSION_SPEC); } catch (CoreException e) { fail("3.0", e); } try { contentTypePrefs.flush(); } catch (BackingStoreException e) { fail("3.1", e); } description = getDescription("3.2a", unrelatedFile); assertNotNull("3.2b", description); assertEquals("3.2c", text, description.getContentType()); // other content types should still be recognized description = getDescription("3.3a", txtFile); assertNotNull("3.3b", description); assertEquals("3.3c", text, description.getContentType()); description = getDescription("3.4a", xmlFile); assertNotNull("3.4b", description); assertEquals("3.4c", xml, description.getContentType()); // disable project-specific settings for this project contentTypePrefs.putBoolean("enabled", false); try { contentTypePrefs.flush(); } catch (BackingStoreException e) { fail("3.99", e); } // no project settings should be in effect description = getDescription("4.0a", txtFile); assertNotNull("4.0b", description); assertEquals("4.0c", text, description.getContentType()); description = getDescription("4.1a", xmlFile); assertNotNull("4.1b", description); assertEquals("4.1c", xml, description.getContentType()); assertNull("4.2b", getDescription("4.2a", unrelatedFile)); // enable project-specific settings again contentTypePrefs.putBoolean("enabled", true); try { contentTypePrefs.flush(); } catch (BackingStoreException e) { fail("4.99", e); } // now associate the full name of the xml file to the text content type try { settings.addFileSpec(xmlFile.getName(), IContentTypeSettings.FILE_NAME_SPEC); } catch (CoreException e) { fail("5.0", e); } try { contentTypePrefs.flush(); } catch (BackingStoreException e) { fail("5.1", e); } description = getDescription("5.2a", unrelatedFile); assertNotNull("5.2b", description); assertEquals("5.2c", text, description.getContentType()); description = getDescription("5.3a", txtFile); assertNotNull("5.3b", description); assertEquals("5.3c", text, description.getContentType()); description = getDescription("5.4a", xmlFile); assertNotNull("5.4b", description); assertEquals("5.4c", text, description.getContentType()); } }