blob: e3c690e97ef700f4c01a72dfab38bbc490d6d6d0 [file] [log] [blame]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<body>
<h2>Mime Resolver</h2>
<p>
GSF is based on mimetypes. Each GSF language plugin is associated
with a particular "mime type". For example, Ruby files have the
mime type <code>text/x-ruby</code>, JavaScript files have the mime
type <code>text/javascript</code>, and so on.
</p>
<p>
In order for GSF to add its editing services to particular files,
you have to teach the IDE how to recognize the mime type for your
files. You do that using the "mime resolver" support in NetBeans.
This is not particular to GSF, but it's a prerequisite.
</p>
<p>
Basically, all you have to do is write a simple XML file which
tells NetBeans for example that files with the extension <code>.foo</code>
have the mimetype <code>text/foo</code>. Once you've done that,
you can go to the <a href="registration.html">registration</a>
section and register editing services for the <code>text/foo</code>
mime type. GSF will provide DataLoaders, DataObjects etc. for
files of the mimetypes as soon as you do that.
</p>
<h3>Registering a Mime Resolver</h3>
<p>
When you create a new NetBeans plugin, it will typically create
an empty layer.xml file for you. This is an XML file where you
can register implementations of various IDE services.
In particular, to register a mime resolver, you'll need to
add something like this:
<pre style="background: #ffffcc; color: black; border: solid 1px black; padding: 5px">
&lt;filesystem&gt;
<b> &lt;folder name="Services"&gt;
&lt;folder name="MIMEResolver"&gt;
&lt;file name="javascript.xml" url="jsresolver.xml"&gt;
&lt;attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.javascript.editing.Bundle"/&gt;
&lt;attr name="position" intvalue="190"/&gt;
&lt;/file&gt;
&lt;/folder&gt;
&lt;/folder&gt;</b>
&lt;filesystem&gt;
</pre>
Here, the file name <code>javascript.xml</code> should be something unique that no other
mime resolver might have picked. The <code>url</code> attribute points to a filename
in the same directory as the layer.xml file. I'll cover that file next.
Finally, the attributes let you create a properly localized user visible description
of files of this file type.
</p>
<h3>Describing File Types</h3>
<p>
For the example above, you would create a <code>Bundle.properties</code> file in the same
package as the layer file (again, when you create a plugin you usually get one of these
created for you already), and it should contain something like this:
<pre>
Services/MIMEResolver/javascript.xml=JavaScript Files
</pre>
</p>
<h3>Writing a Mime Resolver</h3>
<p>
Finally, you need to go and write the actual mime resolver file, <code>jsresolver.xml</code>
(we could have named it anything, including <code>javascript.xml</code>).
<pre style="background: #ffffcc; color: black; border: solid 1px black; padding: 5px">
&lt;!DOCTYPE MIME-resolver PUBLIC "-//NetBeans//DTD MIME Resolver 1.0//EN" "http://www.netbeans.org/dtds/mime-resolver-1_0.dtd"&gt;
&lt;MIME-resolver&gt;
&lt;file&gt;
&lt;ext name="json"/&gt;
&lt;ext name="js"/&gt;
&lt;resolver mime="text/javascript"/&gt;
&lt;/file&gt;
&lt;/MIME-resolver&gt;
</pre>
Here we're saying that files of extensions <code>json</code> and <code>js</code> should
be treated as JavaScript files. The DTD for mime resolvers allow more complex
analysis, such as analyzing file headers and such. Take a look
at the <a href="http://www.netbeans.org/dtds/mime-resolver-1_0.dtd">DTD</a> for
the full details. You can also write a custom class to do mime resolvers
if you have really specific needs. Avoid doing that if you can, since with a custom
mime resolver the IDE can't figure out what you're doing and do special optimizations.
There is an example of how to do this in the ruby editing module - look for <code>RubyMimeResolver</code> - but
again try to avoid this if you don't strictly have to do it.
</p>
<p>
Finally, note that there is a position attribute on the registration of the
mime resolver above. The position attributes are used to order the mime resolvers.
In case there are overlaps in registrations, order matters. For that reason,
pick some number. NetBeans integration unit tests will check all the layers and make
sure there aren't inconsistencies into folder orderings and will generate unit test
failures if there are.
</p>
<h3>Icons and Actions</h3>
<p>
Once you register your mime type with GSF (described in the
<a href="registration.html">registration document</a>, files shown in the
Files and Projects views will be handled by GSF.
You can also assign a custom icon to file as well as context menu actions.
To do this, you need a few more registration steps. Add something like the
following to your layer:
<pre style="background: #ffffcc; color: black; border: solid 1px black; padding: 5px">
&lt;folder name="Loaders"&gt;
&lt;folder name="text"&gt;
&lt;folder name="javascript"&gt;
<b>&lt;attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/netbeans/modules/javascript/editing/javascript.png"/&gt;
&lt;attr name="iconBase" stringvalue="org/netbeans/modules/javascript/editing/javascript.png"/&gt;</b>
&lt;folder name="Actions"&gt;
&lt;file name="OpenAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.OpenAction"/&gt;
&lt;attr name="position" intvalue="100"/&gt;
&lt;/file&gt;
&lt;file name="Separator1.instance"&gt;
&lt;attr name="instanceClass" stringvalue="javax.swing.JSeparator"/&gt;
&lt;attr name="position" intvalue="200"/&gt;
&lt;/file&gt;
&lt;file name="CutAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.CutAction"/&gt;
&lt;attr name="position" intvalue="300"/&gt;
&lt;/file&gt;
&lt;file name="CopyAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.CopyAction"/&gt;
&lt;attr name="position" intvalue="400"/&gt;
&lt;/file&gt;
&lt;file name="PasteAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.PasteAction"/&gt;
&lt;attr name="position" intvalue="500"/&gt;
&lt;/file&gt;
&lt;file name="Separator2.instance"&gt;
&lt;attr name="instanceClass" stringvalue="javax.swing.JSeparator"/&gt;
&lt;attr name="position" intvalue="600"/&gt;
&lt;/file&gt;
&lt;file name="NewAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.NewAction"/&gt;
&lt;attr name="position" intvalue="700"/&gt;
&lt;/file&gt;
&lt;file name="DeleteAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.DeleteAction"/&gt;
&lt;attr name="position" intvalue="800"/&gt;
&lt;/file&gt;
&lt;file name="RenameAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.RenameAction"/&gt;
&lt;attr name="position" intvalue="900"/&gt;
&lt;/file&gt;
&lt;file name="Separator3.instance"&gt;
&lt;attr name="instanceClass" stringvalue="javax.swing.JSeparator"/&gt;
&lt;attr name="position" intvalue="1000"/&gt;
&lt;/file&gt;
&lt;file name="SaveAsTemplateAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.SaveAsTemplateAction"/&gt;
&lt;attr name="position" intvalue="1100"/&gt;
&lt;/file&gt;
&lt;file name="Separator4.instance"&gt;
&lt;attr name="instanceClass" stringvalue="javax.swing.JSeparator"/&gt;
&lt;attr name="position" intvalue="1200"/&gt;
&lt;/file&gt;
&lt;file name="FileSystemAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.FileSystemAction"/&gt;
&lt;attr name="position" intvalue="1300"/&gt;
&lt;/file&gt;
&lt;file name="Separator5.instance"&gt;
&lt;attr name="instanceClass" stringvalue="javax.swing.JSeparator"/&gt;
&lt;attr name="position" intvalue="1400"/&gt;
&lt;/file&gt;
&lt;file name="ToolsAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.ToolsAction"/&gt;
&lt;attr name="position" intvalue="1500"/&gt;
&lt;/file&gt;
&lt;file name="PropertiesAction.instance"&gt;
&lt;attr name="instanceClass" stringvalue="org.openide.actions.PropertiesAction"/&gt;
&lt;attr name="position" intvalue="1600"/&gt;
&lt;/file&gt;
&lt;/folder&gt;
&lt;/folder&gt;
&lt;/folder&gt;
&lt;/folder&gt;
</pre>
Here, the highlighted section shows how an icon is assigned to this type.
You need to place an icon in the directory shown in the attribute. The rest
of this section registers various common actions you might want on your
files. These are all standard actions defined by NetBeans so you don't
have to write these on your own.
</p>
<br/>
<span style="color: #cccccc">Tor Norbye &lt;tor@netbeans.org&gt;</span>
</body>
</html>