A central content type catalog for Eclipse

Last modified: May 12th, 2004

Plan item description: Content-type-based editor lookup. The choice of editor is currently based on file name pattern. This is not very flexible, and breaks down when fundamentally different types of content are found in files with undistinguished file names or internal formats. For example, many different models with specialized editors get stored in XML format files named *.xml. Eclipse should support a notion of content type for files and resources, and use these to drive decisions like which editor to use. This feature would also be used by team providers when doing comparisons based on file type. The several existing file-type registries in Eclipse should be consolidated. [Platform Core, Platform UI] [Theme: User experience] (bug 37668, 51791, 52784)

This plan item is about two important features:

  1. a single content-type repository to be provided by Eclipse on top of which content-type related features provided by any plugins could be built upon, and
  2. a mechanism for automatically determining the content type given a file name and/or its contents.

Driving forces

On automatic content type detection

Content types determine many properties and actions related to files such as encoding, associated editors, etc. Automatic content type determination allows content type specific actions without requiring the user to manually define the content type for a given file. Content type detection is based on:

Content type determination based on file name/extension ("file selection specs") is the easiest one to compute. Each content type has a set of file selection specs associated to it. Determining the content type corresponding to a file selection spec is done by a simple lookup on the catalog.

Content type determination based on file contents is more complex, and requires examining the contents. Since we are talking about an open set of possible content types, this examination implies in delegation to content type detectors contributed by other plug-ins (content describers).

Solution

The proposed API

The proposed API contains 4 new interfaces in a new package called org.eclipse.core.runtime.content:

Following is a brief description for each of them.

org.eclipse.core.runtime.content.IContentType

Represents a content type in the platform. IContentType instances are provided by the platform, built from extensions to the org.eclipse.core.runtime.contentTypes extension point. Relevant properties for IContentType are:

Also, IContentType provides methods that check whether the given file name is matched by this content type file selection spec, or whether a content type is a subtype of another content type.

org.eclipse.core.runtime.content.IContentTypeManager

Represents the content type registry. Provides methods for obtaining the content type associated to a file name, and for discovering the corresponding content type for a stream of bytes. IContentTypeManager allows clients to:

org.eclipse.core.runtime.content.IContentDescriber

Content-based content type detection and content description rely on specialized content detectors associated to content types. When a content type is contributed to the platform, a content describer class may be provided. Content describers are able to detect if a given stream of bytes is conformant to the content type file format, and may also be able to extract important properties from the contents, such as what charset was used to encode the contents (for text files), and any content type specific information that may be required.

The main method in IContentDescriber is:

int describe(InputStream contents, IContentDescription description, int optionsMask) throws IOException;

The first thing implementations for this method must do is to check if the contents represent a valid sample for their corresponding content type file format. If not (or if cannot be determined), this method should exit immediately, returning IContentDescription.INVALID or IContentDescription.INDETERMINATE, depending on how strict the file format is. Otherwise, this method should return IContentDescription.VALID, but only after trying to provide all required information (according to the specified options, if any) by reading the contents and filling the content description provided.

Note: it is essential that for this mechanism to work in a suitable manner, the execution of content describers by the platform should not cause the activation of the plugins providing them. In the Eclipse 3.0 runtime, plug-ins that have built-in bundle manifests will be able to selectively enable/disable auto-activation on a per-package basis (for more information, see bug 52393). Although this will not be enforced by the platform, content describers must be self-contained and not trigger auto-activation.

org.eclipse.core.runtime.content.IContentDescription

Content descriptions are obtained by calling IContentTypeManager#getDescriptionFor method. A content description contains interesting information (such as encoding) about an arbitrary stream of bytes. These information are filled partially by the platform and partially by the content describer elected (if any).

Conflict resolution

Content types are managed by the platform but plug-ins are in charge of contributing content types. While this provides good flexibility, it also opens oportunities for conflicts. There are a few scenarios where conflicts may arise:

  1. two content types provided by independently developed plug-ins intended for the same file selection specification - this may happen for popular file types that are not provided by the platform. In this case, one of the content types will be automatically made into an alias for the other. The intended effect is that content types/code depending on the content type transformed into an alias should still work, acting on the alias target instead. Content type priorities help deciding which content type should be preserved, and which ones made into aliases. If a plug-in provider feels it should be the official provider of a content type, a high priority should be assigned to it. Usually, "normal" priorities (the default value) should be used, meaning that if a similar high priority content type is available, it should be picked instead.
  2. two related (but different) content types that share a same file name/extension specification - think of general XML documents and Ant build scripts (a sub-type of XML document, inheriting its file selection specifications). This is different than the previous case here at most one content type will be contributing file specs (the more basic type). In this scenario, for APIs that return content-types based exclusively on file name, the ancestor will be appear first in the returned array, since it is more general. Note that when a general type specifies a file extension for it to be associated with, and a subtype specifies a file name that has the same file extension, the more specific type will appear before the general one. For APIs that do content-based analysis, if both content type describers deem the contents as valid, the more specific content type will also appear first. For two sibling content types that deem a same set of bytes as valid, no ordering between them will be enforced (aliasing is not done since those types do not explicitly specify file specs - they inherit them instead).
  3. two completely unrelated content types that share a same file name/extension specification - this is the more unlikely scenario (imagine an image file format and a word-processor file format sharing the same file extension). In this case, aliasing is not desirable (since the content types are fundamentally different). User intervention is required (by disabling one of the content types, for instance, and manually associating any editors, etc to the other content type) to avoid incorrect aliasing.

Frequently Asked Questions

  1. How will plugin providers benefit from a central content type catalog?

    Generally by using the same content type registry and sharing the same concept of content/file type. Other examples are:

  2. Why are content types hierarchical?

    To allow important properties to be inherited by new specialized content types:

  3. What happens if the base type for a new content type is not present in the platform (the plug-in that provides it is not available)?

    The content type (and consequently any descendants) will be deemed invalid and ignored.

  4. Do Eclipse's content types have anything to do with IANA's MIME Media Types?

    Not so far.

  5. How can users customize the way content types are chosen?

    By:

  6. Can plug-ins override the content type describer for an existing content type?

    Not so far. It is up to the plugin provider to determine whether a content type describer will be provided.

  7. Can two completely unrelated content types be associated with the same file spec?

    What happens is that only one of the content types (arbitrarily selected) will be enabled. If only one of them is declared as high priority, it will be picked. Otherwise, one will be arbitrarily chosen by the platform. In either case, the others will be made into aliases for the elected content type.

  8. What if a given file name is matched by two different file specs provided by two completely unrelated content types?

    As seem above, the only way this can happen is when two different file specs (for instance, a file name and a file extension) accept the same file name (for instance, one content type is associated with a "xml" file extension, other is associated with a "plugin.xml" file name. ) File name specs have priority over file extension specs (so plugin.xml is a plugin manifest before being a XML document). The normal case is that the content type that defines a file name spec is based on the file type that defines a file extension spec (a plugin manifest is a kind of XML document). This ensures that actions applicable to general XML documents will be applicable to a plugin manifest.

  9. What are content type aliases?

    When a content type is marked as an alias for another content type (due to a file spec conflict), all of its properties are ignored, and any associations with it will actually be made on the target type.

  10. What are aliases for?

    It is a mechanism to prevent conflicts. When multiple plugins contribute content types associated with the same file specs, we have a conflict. Conflicts are bad because introduce ambiguity (which one is the right content type?). Most of times when such conflicts arise, it is a case of independently developed plugins trying to contribute the same content type (semantically speaking). Aliasing between conflicting content types will be automatically created when necessary.

  11. How do I prevent my specialized content-type to be disabled even if its parent is not available?

    Sometimes a plugin A does not depend on plugin B, but declares a content type which is intended to be a specialization of another content type declared by B. To prevent the content type declared by A to be disabled:

    1. declare a low priority content type associated with the same file specs the intended parent is usually associated with (a placeholder);
    2. make your specialized content type have this placeholder as its base type;

    If the originally intended base type is available, your base type will be marked as just an alias, and your specialized content type will be properly attached to the official content type. Otherwise, the placeholder will be elected, and although things might not be as great as intended (actions associated to the original content type will not be available), your content type will still be enabled.

  12. When should a file-association be contributed instead of declaring a new (derived) content type?

    New content types should be created only if there is no existing content type with the semantics required. Otherwise, when only additional file specs must be provided, file associations are the way to go.

  13. Are file specs inherited?

    Only if none is specified in the sub type.

  14. How does a client figure out whether a given file is a text file or not?

    The proposed approach is to check if the file's content type is a kind of the "org.eclipse.core.runtime.text" content type, which is intended to be the ancestor for all text oriented content types. If it turns out to be a very frequent idiom, we might consider proving a convenience API to do that.

  15. Do content types have to contribute content describers?

    No, although if the file has a identifiable signature/format, it is recommended, because improves the overall quality of content-based content type lookups.

Note: comments are encouraged. Any questions/concerns not addressed here should be discussed in the platform-core-dev list, or bug 37668.

Addendum: issues to be addressed in the 3.1 cycle

Last modified: October 15th, 2004

The solution described above was implemented and relatively succesful. Some components took advantage of the new content type infrastructure, but still in many cases file-association is being done in an ad-hoc manner. Also, no UI was provided for customizing content types (such as changing the default encoding, adding associations with files) so the user has no control on how the content type detection mechanism works. Thus, the main issues to be addressed in the 3.1 cycle are:

Support more use cases

Ensure the Content Type works for the SDK plug-ins and for products built on top of Eclipse.

TBD

Platform/UI - file/editor association

TBD

Platform/Team - binary vs ascii files

TBD

Give users more power

Ensure users have means to customize how the content type detection works for them.

TBD

Improve conflict handling

Ensure content type detection works (or can be made to work) appropriately when incompatible products are deployed together.

TBD