How do I add support for an XML type with a different extension?
I want to add some special
functionality to the initial handling of xml files with a xul extension, but
then allow users to use the existing NB functionality for editing,
validation etc.
>
Did you solve this without patching?
In 5.0, it can be done without a patch. It does, however, require an impl dependency on xml-core. I’d really like this to be simpler, and a supported API.
See below for issues with pre-release 6.0
Anyway, here’s how I do it for an xml flavor called SCXML:
-
Register the loader for text/xml mimetype
-
The loader:
import java.io.IOException;
import org.netbeans.modules.xml.core.XMLDataLoader;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObjectExistsException;
import org.openide.loaders.MultiDataObject;
import org.openide.loaders.UniFileLoader;
import org.openide.util.NbBundle;
public class ScxmlDataLoader extends UniFileLoader
{
public static final String REQUIRED_MIME = "application/scxml+xml";
private static final long serialVersionUID = 1L;
public ScxmlDataLoader()
{
super("com.nuance.tools.xhmi.ScxmlDataObject");
}
protected String defaultDisplayName()
{
return NbBundle.getMessage(ScxmlDataLoader.class, "LBL_Scxml_loader_name");
}
protected void initialize()
{
super.initialize();
getExtensions().addMimeType(REQUIRED_MIME);
}
protected MultiDataObject createMultiObject(FileObject primaryFile) throws DataObjectExistsException, IOException
{
return new ScxmlDataObject(primaryFile, this);
}
protected MultiDataObject.Entry createPrimaryEntry (MultiDataObject obj, FileObject primaryFile) {
return new XMLDataLoader.XMLFileEntry (obj, primaryFile); //adds smart templating
}
protected String actionsContext()
{
return "Loaders/" + REQUIRED_MIME + "/Actions";
}
}
-
The data object:
import java.io.IOException;
import org.netbeans.modules.xml.core.XMLDataObjectLook;
import org.netbeans.modules.xml.core.cookies.DataObjectCookieManager;
import org.netbeans.modules.xml.core.sync.DataObjectSyncSupport;
import org.netbeans.modules.xml.core.sync.Synchronizator;
import org.netbeans.modules.xml.core.text.TextEditorSupport;
import org.netbeans.spi.xml.cookies.CheckXMLSupport;
import org.netbeans.spi.xml.cookies.DataObjectAdapters;
import org.netbeans.spi.xml.cookies.ValidateXMLSupport;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObjectExistsException;
import org.openide.loaders.MultiDataObject;
import org.openide.nodes.CookieSet;
import org.openide.nodes.Node;
import org.openide.text.DataEditorSupport;
import org.xml.sax.InputSource;
public class ScxmlDataObject extends MultiDataObject implements
XMLDataObjectLook
{
private transient final DataObjectCookieManager cookieManager;
private transient Synchronizator synchronizator;
public ScxmlDataObject(FileObject pf, ScxmlDataLoader loader) throws DataObjectExistsException, IOException {
super(pf, loader);
CookieSet cookies = getCookieSet();
cookieManager = new DataObjectCookieManager (this, cookies);
cookies.add((Node.Cookie) DataEditorSupport.create(this, getPrimaryEntry(), cookies));
InputSource is = DataObjectAdapters.inputSource(this);
cookies.add(new CheckXMLSupport(is));
cookies.add(new ValidateXMLSupport(is));
// editor support defines MIME type understood by EditorKits registry
TextEditorSupport.TextEditorSupportFactory editorFactory =
new TextEditorSupport.TextEditorSupportFactory (this, org.netbeans.modules.xml.core.XMLDataObject.MIME_TYPE);
editorFactory.registerCookies (cookies);
}
protected Node createNodeDelegate() {
return new ScxmlDataNode(this);
}
////////// XMLDataObjectLook interface /////////////////
public DataObjectCookieManager getCookieManager() {
return cookieManager;
}
public synchronized Synchronizator getSyncInterface() {
if (synchronizator == null) {
synchronizator = new DataObjectSyncSupport (ScxmlDataObject.this);
}
return synchronizator;
}
}
-
The layer file:
<filesystem>
<folder name="Loaders">
<folder name="application">
<folder name="scxml+xml">
<folder name="Actions">
<file name="org-openide-actions-OpenAction.instance"/>
<attr name="org-openide-actions-OpenAction.instance/org-openide-actions-FileSystemAction.instance" boolvalue="true"/>
<file name="org-openide-actions-FileSystemAction.instance"/>
<attr name="org-openide-actions-FileSystemAction.instance/sep-1.instance" boolvalue="true"/>
<file name="sep-1.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
</file>
<attr name="sep-1.instance/org-openide-actions-CutAction.instance" boolvalue="true"/>
<file name="org-openide-actions-CutAction.instance"/>
<attr name="org-openide-actions-CutAction.instance/org-openide-actions-CopyAction.instance" boolvalue="true"/>
<file name="org-openide-actions-CopyAction.instance"/>
<attr name="org-openide-actions-CopyAction.instance/sep-2.instance" boolvalue="true"/>
<file name="sep-2.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
</file>
<attr name="sep-2.instance/org-openide-actions-DeleteAction.instance" boolvalue="true"/>
<file name="org-openide-actions-DeleteAction.instance"/>
<attr name="org-openide-actions-DeleteAction.instance/org-openide-actions-RenameAction.instance" boolvalue="true"/>
<file name="org-openide-actions-RenameAction.instance"/>
<attr name="org-openide-actions-RenameAction.instance/sep-3.instance" boolvalue="true"/>
<file name="sep-3.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
</file>
<attr name="sep-3.instance/org-openide-actions-SaveAsTemplateAction.instance" boolvalue="true"/>
<file name="org-openide-actions-SaveAsTemplateAction.instance"/>
<attr name="org-openide-actions-SaveAsTemplateAction.instance/sep-4.instance" boolvalue="true"/>
<file name="sep-4.instance">
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
</file>
<attr name="sep-4.instance/org-openide-actions-ToolsAction.instance" boolvalue="true"/>
<file name="org-openide-actions-ToolsAction.instance"/>
<attr name="org-openide-actions-ToolsAction.instance/org-openide-actions-PropertiesAction.instance" boolvalue="true"/>
<file name="org-openide-actions-PropertiesAction.instance"/>
</folder>
</folder>
</folder>
</folder>
<folder name="Services">
<folder name="MIMEResolver">
<file name="ScxmlResolver.xml" url="resources/ScxmlResolver.xml">
<attr name="SystemFileSystem.localizingBundle" stringvalue="com.nuance.tools.xhmi.Bundle"/>
</file>
</folder>
</folder>
<folder name="Templates">
<folder name="Other">
<file name="ScxmlTemplate.scxml" url="resources/ScxmlTemplate.scxml">
<attr name="SystemFileSystem.localizingBundle" stringvalue="com.nuance.tools.xhmi.Bundle"/>
<attr name="template" boolvalue="true"/>
</file>
</folder>
</folder>
-
the MIME resolver:
<MIME-resolver>
<file>
<ext name="scxml"/>
<resolver mime="application/scxml+xml"/>
</file>
</MIME-resolver>