Overview

Back to Filesystems API

# HOW TO: Declarative MIME Type Resolvers

## Overview

A MIME type resolver's responsibility is to return on request a given `FileObject`'s MIME content type.

A MIME type resolver can be any object implementing `MIMEResolver`. All MIME resolvers in the system are consulted; they are found by searching in lookup and conventionally should be registered in the folder `Services/MIMEResolver/` in a module's layer.

A MIME resolver would typically try to guess MIME type from characteristics of the file such as extension or first few lines of content. In the case that there is a MIME resolver recognizing Ant project files and another recognizing EJB deployment descriptors, then files with the `*.xml` extension would be parsed twice, at least for their root element.

### Problems

- This introduces a performance problem as the number of MIME type resolvers grows. The MIME resolver manager may cache literal file headers for speed, but invoking an XML parser (for example) still incurs a penalty.
- It is also error-prone to write such a resolver.

## Declarative MIME Type Resolvers

To solve both of the above problems a developer can use a declarative MIME type resolver. The semantics of the MIME resolution may be specified in a simple manner and an implementation is available that will interpret the declaration as efficiently as possible.

The semantics is described in an XML document following a documented DTD. The DTD documentation provides details of the permitted syntax.

## How to Create a Resolver XML File

Create a valid XML document according to the MIME resolver DTD grammar and place it in a lookup-registration area (such as `Services/MIMEResolver/`).

A simple example follows which might be used to recognize Ant project files.

General resolver description file `org/nb/modules/ant/mime-resolver.xml`:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE MIME-resolver PUBLIC
              "-//NetBeans//DTD MIME Resolver 1.0//EN"
              "http://www.netbeans.org/dtds/mime-resolver-1_0.dtd">
    <MIME-resolver>
        <!-- Skip anything marked as definitely not ours. -->
        <file>
            <fattr name="known-ant-project-file" text="false"/>
            <exit/>
        </file>
        <!-- Accept immediately anything known as definitely ours. -->
        <file>
            <fattr name="known-ant-project-file" text="true"/>
            <resolver mime="text/x-ant+xml"/>
        </file>
        <!-- For other XML, look for <project default="..."/> -->
        <file>
            <ext name="xml"/>
            <resolver mime="text/x-ant+xml">
                <xml-rule>
                    <element name="project">
                        <attr name="default"/>
                    </element>
                </xml-rule>
            </resolver>
        </file>
    </MIME-resolver>

First, the DOCTYPE ensures that the XML file will be recognized as a resolver (by its public ID). The first `<file/>` block is a negative template - if it matches the resolver terminates and returns `null` (meaning it made no decision about the file). The second block automatically returns the Ant MIME type (here an XML subtype) for files tagged as being definitely Ant scripts (regardless of content and extension). The last block matches any XML file (that is, `*.xml`) whose root element is `<project/>` and contains at least the attribute `default` (value unspecified).

Registration in the module XML layer `org/nb/modules/ant/layer.xml`:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE filesystem PUBLIC
              "-//NetBeans//DTD Filesystem 1.0//EN"
              "http://www.netbeans.org/dtds/filesystem-1_0.dtd">
    <filesystem>
        <folder name="Services">
            <folder name="MIMEResolver">
                <file name="org-nb-modules-ant-mime-resolver.xml"
                      url="mime-resolver.xml">
                    <attr name="SystemFileSystem.localizingBundle"
                          stringvalue="org.nb.modules.ant.Bundle"/>
                    <attr name="SystemFileSystem.icon"
                          urlvalue="nbresloc:/org/nb/modules/ant/resolver-icon.gif"/>
                </file>
            </folder>
        </folder>
    </filesystem>

The resolver is registered as `Services/MIMEResolver/org-nb-modules-ant-mime-resolver.xml`. It is given a pleasant display name and icon since the user may see the resolver presented in the IDE's settings. The bundle file `org/nb/modules/ant/Bundle.properties` would contain a matching key:

    Services/MIMEResolver/org-nb-modules-ant-mime-resolver.xml=Ant project files

and `org/nb/modules/ant/resolver-icon.gif` should hold a suitable icon.

## Using the MIME Resolver

In order to ensure that the current API implementation is capable of processing the resolver you should declare the manifest dependency:

    OpenIDE-Module-IDE-Dependencies: IDE/1 > 1.31

Now whenever matching files are encountered, they will be treated as having the MIME type `text/x-ant+xml` (in this example). The data loader should be made to be sensitive to the resolved MIME type; this is most easily accomplished when subclassing `UniFileLoader`:

    protected void initialize() {
        super.initialize();
        getExtensions().addMimeType("text/x-ant+xml");
    }

Note that in this case `JEditorPane` will probably not recognize such files as being a variant of `text/xml` (the `text/*+xml` syntax is a pending standard), so you should remember when using a `DataEditorSupport` or similar to explicitly set the editor MIME type to `text/xml` (the default is taken from the file MIME type). In the future it is planned for editor supports to check an OpenIDE-specific type registry which would automatically associate a general XML editor kit with MIME types matching `text/*+xml` unless an exact match was found.

## Links

RFC 3023: XML Media Types

@FOOTER@