Archiv für Oktober 2006

netbeans: izpack support

Sonntag, 29. Oktober 2006

I had a look at the IzPack support project I created a while ago. The plan was to make creating Install scripts more comfortable with a wizard, and to create a visual editor in the long run.

There is FileTypeSupport, a template and some XML binding classes I had created with my schema2beans support. Furthermore I had started to create a wizard to do the basic configuration steps. There is a info element, and the dtd states it may have these elements:

appname, appversion, appsubpath?, authors?, url?, javaversion?, uninstaller?, webdir?, summarylogfilepath?

Here’s my first IzPackVisualPanel for setting these properties:

IzPack Wizard

So the plan is to do something like:

1. Wizard is launched: bind values from template file to generated classes
2. Use data from wizard to customize the binding classes
3. unmarshall to install script
4. use script and add ant task for creating the installer to project

Should not be too hard, I’ll try to work on it the next days.

netbeans: schema2beans support (5) – target project configuration

Sonntag, 29. Oktober 2006

*this is a draft*

In the last entry of this series we added support for selecting a target package for generated beans. The process of generating beans is quite comfotable now. But there is still one important feature missing. If you generate beans that depend on the runtime then you need to import the schema2beans library. Until now, you need to do this manually. Again the Java Project Support API will help us to do this automatically:

Add this method to your schema2beans action:

    public void insertBeanJar(FileObject myBeanJarFileObject,Project currentProject){
        Lookup javaProjectLookup;
        ProjectClassPathExtender extender;
        try{
            javaProjectLookup = currentProject.getLookup();
            extender =  (ProjectClassPathExtender)javaProjectLookup.lookup(ProjectClassPathExtender.class);
            extender.addArchiveFile(myBeanJarFileObject);
        } catch(java.io.IOException IOe){
            org.openide.ErrorManager.getDefault().notify(IOe);
        }
    }

Most work is done by ProjectClassPathExtender. It adds the necessary entries to the projects configuration files.

Next add some code to your performAction method:

    protected void performAction(DataObject dataObject) {
        InputOutput io = IOProvider.getDefault().getIO("Schema2Beans", true);
        String path = FileUtil.toFile(dataObject.getPrimaryFile()).getAbsolutePath();
        Sources sources = ProjectUtils.getSources(getProject(dataObject.getPrimaryFile()));
        SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
        WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels(groups));
        // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
        wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
        wizardDescriptor.setTitle("Your wizard dialog title here");
        Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
        dialog.setVisible(true);
        dialog.toFront();
        boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION;
        if (!cancelled) {
            io.getOut().println("generating beans for "+path);
            try {
                io.getOut().println("parameters: "+wizardDescriptor.getProperty(Schema2BeansWizardPanel1.PROP_PARAM));
                String [] parts = ((String)wizardDescriptor.getProperty(Schema2BeansWizardPanel1.PROP_PARAM)).split("\"");
                String dir = parts[1];
                String [] userargs = parts[0].split("\\s+");
                String [] args = new String [userargs.length+3];
                System.arraycopy(userargs, 0,args,0,userargs.length );
                args[args.length-3]=dir;
                args[args.length-2]="-f";
                args[args.length-1]=path;
                OutputStream out = System.out;
                OutputStream err = System.err;
                GenBeans.main(args);
                Project project = getProject(dataObject.getPrimaryFile());
                // copy schema2beanslibrary when necessary
                FileObject dest = project.getProjectDirectory().getFileObject("lib");
                if (dest == null){
                    dest = project.getProjectDirectory().createFolder("lib");
                }
                FileObject destFile = dest.getFileObject("org-netbeans-modules-schema2beans","jar");
                if (destFile == null){
                    io.getOut().println("adding library to project: "+project.getProjectDirectory().getPath());
                    File source = new File("lib/org-netbeans-modules-schema2beans.jar");
                    io.getOut().println("source file  "+source.getAbsolutePath());
                    if (source.exists())
                        destFile = FileUtil.copyFile(FileUtil.toFileObject(source.getCanonicalFile()),dest,"org-netbeans-modules-schema2beans");
                }
                insertBeanJar(destFile,project);

            } catch (Exception ex) {
                ex.printStackTrace(io.getErr());
            }
            io.getOut().println("ready "+path);
        }
    }

Now the project is configured to use the copied library.

netbeans: IzPack

Samstag, 28. Oktober 2006

IzPack is an installers generator for the Java platform. It produces lightweight installers that can be run on any operating system where a Java virtual machine is available. I was discussing the integration of IzPack to into netbeans with Geertjan at the NUG in munich . I think it would be great to have some support for an installer builder in netbeans, and I found out eclipse already has it. Shouldn’t be too hard to have some basic support, as everythings defined in XML. And the whole stuff is written in java, maybe we can also port the GUI?

I found this thread in an IzPack mailing list, and I posted there too, to find out whether this guy has made any progress:

http://comments.gmane.org/gmane.comp.java.izpack.user/230

If not, I guess I’ll give it a try…

netbeans: Nice feature

Samstag, 28. Oktober 2006

I found something very interesting today, when I was working on the schema2beans module. I had a typo in the parameters that causes GenBeans to halt. GenBeans seems to use System.exit(0);

Now guess what happens?

org.netbeans.ExitSecurityException: Illegal attempt to exit early

Ain’t that nice? Netbeans protects your application from dangerous third party code (and my missing data validation :) ).

netbeans: schema2beans support (4) – target directory and package

Samstag, 28. Oktober 2006

In the last part of this tutorial we have added a configuration wizard to the schema2beanssupport. So now we can set the parameters via a GUI. I had planned to add some info on how to copy the files and configure the target project for the fourth part, but I changed my mind ’cause I received an email by Jesse Glick today. He told me how I could get hold of the projects source dir and the available package names and I had to try this immediately. Here is what Jesse wrote:

> ClassPath.getClassPath(d.getPrimaryFile(), ClassPath.SOURCE)

> will give you the root of the source folder (if applicable); from there you can use FileUtil.getRelativePath or whatever, after some robustness checks.

This could remedy the problem that until now the generated classes are placed in the directory where the schema is. I wrote my first tests and wanted to import the module. So I typed “ClassPath” in the library manager and found some libraries. The first in the list was the Java Support API. That’s the one I was looking for. But I also found the Java Project Support API and the description told me, that the wizard for the new files uses this for package management. I tried to find some documentation, but wasn’t too lucky so I decided to browse the sources. The first Intersting thing I found is PackageView. It has a createListView(SourceGroup group) method which returns a ComboBoxModel. It is used to create the PackageChooserComboBox of the JavaTargetChooserPanelGUI. Yet I had no idea how to get hold of a SourceGroup, but after some “findUsages” I found this:

Sources sources = ProjectUtils.getSources(project);
SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);

Nice, so all we need is a project, and we get the package view for free. Bring up your schema2beans action class and add this method:

     private Project getProject(FileObject file){
        Project p = FileOwnerQuery.getOwner(file);
        return p;
    }

This returns the project. In the actionperformed change the WizardDescriptor generation like this:

         Sources sources = ProjectUtils.getSources(getProject(dataObject.getPrimaryFile()));
        SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
        WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels(groups));

Now change the start of the getPanels() method to this:

   private WizardDescriptor.Panel[] getPanels(SourceGroup [] sourceGroups) {
        if (panels == null) {
            panels = new WizardDescriptor.Panel[] {
                new Schema2BeansWizardPanel1(sourceGroups)
            }
            ...

Add a constructors to Schema2BeansWizardPanel1:

SourceGroup [] sourceGroups;

    public Schema2BeansWizardPanel1 (SourceGroup [] sourceGroups){
        super();
        this.sourceGroups = sourceGroups;
    }

and change the getComponent method:

    public Component getComponent() {
        if (component == null) {
            component = new Schema2BeansVisualPanel1(sourceGroups);
        }
        return component;
    }

Now change the contructor of Schema2BeansVisualPanel1:

     private ComboBoxModel comboBoxModel;
    /** Creates new form Schema2BeansVisualPanel1 */
    public Schema2BeansVisualPanel1(SourceGroup [] sourceGroups) {
        comboBoxModel = PackageView.createListView(sourceGroups[0]);
        initComponents();
    }

add a line to the getParameters method:

String parameters = "";
parameters+=" -p "+packageComboBox.getEditor().getItem().toString(); //<-add this line
...

Go to the visual editor, select the combobox and switch to the “code” tab in the properties panel, add some post-initialization code:

 packageComboBox.setRenderer(PackageView.listRenderer());
 packageComboBox.setModel(comboBoxModel);

That part also adds a nice icon to the dropdown list. So now we can also add a package via a GUI component.

schema2beanswizard

Now we still have the problem, that the dir variabledoesn’t hold the source rootfolder, so you need to copy the generated classes there manually. You can fix this by adding a parameter to Schema2BeansVisualPanel1

    SourceGroup sourceGroup;
    /** Creates new form Schema2BeansVisualPanel1 */
    public Schema2BeansVisualPanel1(SourceGroup [] sourceGroups) {
        sourceGroup = sourceGroups[0];
        comboBoxModel = PackageView.createListView(sourceGroups[0]);
        initComponents();
    }

and another line to the getParameters method:

        parameters+=" -r\""+sourceGroup.getRootFolder().getPath()+"\""; // path must be last parameter due to the way it's split
        return parameters.trim();

Now you can throw out the default parameters in your Actions actionPerformed method and use this instead:

                String [] parts = ((String)wizardDescriptor.getProperty(Schema2BeansWizardPanel1.PROP_PARAM)).split("\"");
                String dir = parts[1];
                System.out.println("dir "+dir);
                String [] userargs = parts[0].split("\\s+");
                String [] args = new String [userargs.length+3];
                System.arraycopy(userargs, 0,args,0,userargs.length );
                args[args.length-3]=dir;
                args[args.length-2]="-f";
                args[args.length-1]=path;
                GenBeans.main(args);

I learned a lot about the API doing this. Maybe I will reuse some other parts to create a wizard for the “New File” section instead of just a context menu action. Well, in the next part of this blog series I will probably be showing how to configure target projects :) .

netbeans: XMLMultiView API is my friend!

Freitag, 27. Oktober 2006

A few weeks ago I started playing around with the netbeans visual library. At first I thought it was just another graph library, and planned to use it for a network component, but while experimenting I found out that there is way more. The library started as a graph library that had been extracted from the netbeans visual mobile designer in version 1.0, but it is currently being enhanced to be a full visual library, with very nice features like baseline support, zooming, resizing and many more features for free.

So I decided to give it a try and enhance my jasperreports module for netbeans with a visual editor. Until then, there was basic support for editing, previewing and generating reports, but what I want is more like IReport. This is how it looks like now:

Nothing spectacular going on yet, but I managed to do basic synchronization this week after I spent some time to find out that the schema2beans.jar playing tricks on me. The editor is based on XML MultiView API, and I’m doing the synchronization very similar to Geertjan’s bookview sample .

My jaspereditor module will be a friend module of XML MultiView API, so I don’t need to use the implementation version anymore. Thanks Erno!

netbeans: schema2beans support (3) – adding parameters

Freitag, 27. Oktober 2006

In the last schema2beans support blog , I showed how to add the action to an additional filetype. The support is very basic so far, and we should at least add some support for additional “commandline” parameters. The wizard API will be great for this:

Launch the wizard wizard (File->New File->Netbeans module development->Wizard). Set the “Number of Wizard Panels” to 1. In the next step add a prefix (“Schema2Beans”) and click finish. Three classes will be generated:

Schema2BeansVisualPanel1, Schema2BeansWizardAction and Schema2BeansWizardPanel

Now we will steal some code from Schema2BeansWizardAction:

Copy the “panels” variable and the getPanels() method to your own Schema2BeansAction and change these three parameters to FALSE:

                    // Turn on subtitle creation on each step
                    jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.FALSE);
                    // Show steps on the left side with the image on the background
                    jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.FALSE);
                    // Turn on numbering of all steps
                    jc.putClientProperty("WizardPanel_contentNumbered", Boolean.FALSE);

Copy the code body of the performAction() method and merge it with your Schema2BeansAction’s performAction method like this:

  protected void performAction(DataObject dataObject) {
        InputOutput io = IOProvider.getDefault().getIO("Schema2Beans", true);
        String path = FileUtil.toFile(dataObject.getPrimaryFile()).getAbsolutePath();
        String dir = FileUtil.toFile(dataObject.getPrimaryFile().getParent()).getAbsolutePath();
        WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels());
        // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
        wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
        wizardDescriptor.setTitle("Your wizard dialog title here");
        Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
        dialog.setVisible(true);
        dialog.toFront();
        boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION;
        if (!cancelled) {
            io.getOut().println("generating beans for "+path);
            try {
                String [] args = new String []{
                    "-f",path,"-r",dir
                };
                GenBeans.main(args);
                Project project = getProject(dataObject.getPrimaryFile());
                // copy schema2beanslibrary when necessary

                FileObject dest = project.getProjectDirectory().getFileObject("lib");
                if (dest == null){
                    dest = project.getProjectDirectory().createFolder("lib");
                }
                FileObject destFile = dest.getFileObject("org-netbeans-modules-schema2beans","jar");
                if (destFile == null){
                    io.getOut().println("project: "+project.getProjectDirectory().getPath());
                    File source = new File("lib/org-netbeans-modules-schema2beans.jar");
                    io.getOut().println("source file  "+source.getAbsolutePath());
                    if (source.exists())
                        destFile = FileUtil.copyFile(FileUtil.toFileObject(source.getCanonicalFile()),dest,"org-netbeans-modules-schema2beans");
                }
                insertBeanJar(destFile,project);

            } catch (Exception ex) {
                ex.printStackTrace(io.getErr());

            }
            io.getOut().println("ready "+path);
        }

    }

After you fix the imports (Alt Shift F), you can run your module, and your wizard will be launched when you use our action. All it does right now is letting you cancel bean creation, so we need to add something useful.

First change the getName method of Schema2BeansVisualPanel1:

    public String getName() {
        return "Schema2Beans Parameter Dialog";
    }

Then use Matisse to design the Schema2BeansVisualPanel1. Create something like this:

We will only use the parameter part right now. So I disabled the package and schema location. We’ll activate these later on. My checkboxes are named after the commandline parameters they represent (so don’t blame me for the “defaultsAccessableCheckBox” and the irregular use of camelCode). You can have a look here for the mapping.

Now add a method to Schema2BeansVisualPanel1 that returns the parameters as a String:

 public String  getParameters(){
        String parameters = "";
        parameters+=attrpropCheckBox.isSelected()?" -attrprop":"";
        parameters+=commentsCheckBox.isSelected()?" -comments":"";
        parameters+=commoninterfaceCheckBox.isSelected()?" -commoninterface":"";
        parameters+=defaultsAccessableCheckBox.isSelected()?" -defaultsAccessable":"";
        parameters+=delegatorCheckBox.isSelected()?" -delegator":"";
        parameters+=genInterfacesCheckBox.isSelected()?" -genInterfaces":"";
        parameters+=javabeansCheckBox.isSelected()?" -javabeans":"";
        parameters+=keepElementPositionsCheckBox.isSelected()?" -keepElementPositions":"";
        parameters+=propertyeventsCheckBox.isSelected()?" -propertyevents":"";
        parameters+=stCheckBox.isSelected()?" -st":"";
        parameters+=throwCheckBox.isSelected()?" -throw":"";
        parameters+=useInterfacesCheckBox.isSelected()?" -useInterfaces":"";
        parameters+=validateCheckBox.isSelected()?" -validate":"";
        parameters+=vetoCheckBox.isSelected()?" -veto":"";
        parameters+= " "+aditionalParametersTextField.getText();
        return parameters.trim();
    }

To save the settings and meake them accessible to the action change the storeSettings method of your Schema2BeansWizardPanel1:

public void storeSettings(Object settings) {
        System.out.println("store settings "+((Schema2BeansVisualPanel1) component).getParameters());
        WizardDescriptor wiz = (WizardDescriptor) settings;
        wiz.putProperty(PROP_PARAM, ((Schema2BeansVisualPanel1) component).getParameters());
    }

Now you have access to them in your action via the WizardDescriptor. Change your actions performAction method to contain this:

                 String [] userargs = ((String)wizardDescriptor.getProperty(Schema2BeansWizardPanel1.PROP_PARAM)).split("\\s+");
                String [] defaultArgs = new String []{
                    "-f",path,"-r",dir
                };
                String [] args = new String[userargs.length+defaultArgs.length];
                System.out.println("userargs "+userargs.length+" defaultArgs "+defaultArgs.length+" args "+args.length);
                System.arraycopy(userargs, 0,args,0,userargs.length );
                System.arraycopy(defaultArgs, 0,args,userargs.length,defaultArgs.length );
                GenBeans.main(args);

Now everything is wired, most of the GenBeans parameters can be used via the checkboxes, all others via the parameter. In the next part of this tutorial we will add some configuration to target projects, so you don’t have to do this manually anymore.

netbeans: schema2beans bug

Donnerstag, 26. Oktober 2006

I just found out, that the schema2beans.jar (Version 4.20) that I have used for my JasperVisualReportDesigner doesn’t work. I used the latest version of schema2beans from the official project site, because I needed the schema2beansdev.jar that is not part of netbeans (at least I didn’t find it). I created some binding classes with my new schema2beans action for the jasperreports DTD. The marshalling/unmarshalling went fine. Then I used the generated classes as the datamodel in my two-way editor and used the merge-function to update the model from the XML-editor. But I didn’t get any PropertyChangeEvents from the merge. It took me a whole day of writing tests and reading BaseBean source code to realize that the bug wasn’t in my code. I switched to the schema2beans runtime jar that comes with netbeans and it worked. Fortunately the jar seems to be compatible with the generated classes.

As the synchronization works now, I can start adding features to my JasperReportsVisualEditor, so stay tuned…

netbeans: schema2beans support (2) – share an Action between two file-types

Donnerstag, 26. Oktober 2006

In my last blog entry I showed how to add a new action to the context menu of XML schema files. With this action you can generate XML-binding classes for files that conform to your schema. The schema2beans library we used for this can also do the same thing for DTD files. So our action would work for DTDs as well. Unfortunately you can only select one file-type and one editor in the Action wizard. But we can add the configuration manually:

Go to the layer.xml and add some new entries for your action (the path will look different depending on your package):

First find the entry in the Loaders section in the folder named “text”:

           <folder name="x-schema+xml">
                <folder name="Actions">
                    <attr name="org-openide-actions-ToolsAction.instance/de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow" boolvalue="true"/>
                    <file name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow">
                        <attr name="originalFile" stringvalue="Actions/XML/de-yourcompany-modules-schema2beans-Schema2BeansAction.instance"/>
                    </file>
                    <attr name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow/org-openide-actions-PropertiesAction.instance" boolvalue="true"/>
                </folder>
            </folder>

Make a copy of it right after the original entry but change “x-schema+xml” to “x-dtd”. The whole section should look like this now:

     <folder name="Loaders">
        <folder name="text">
            <folder name="x-schema+xml">
                <folder name="Actions">
                    <attr name="org-openide-actions-ToolsAction.instance/de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow" boolvalue="true"/>
                    <file name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow">
                        <attr name="originalFile" stringvalue="Actions/XML/de-yourcompany-modules-schema2beans-Schema2BeansAction.instance"/>
                    </file>
                    <attr name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow/org-openide-actions-PropertiesAction.instance" boolvalue="true"/>
                </folder>
            </folder>
            <folder name="x-dtd">
                <folder name="Actions">
                    <attr name="org-openide-actions-ToolsAction.instance/de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow" boolvalue="true"/>
                    <file name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow">
                        <attr name="originalFile" stringvalue="Actions/XML/de-yourcompany-modules-schema2beans-Schema2BeansAction.instance"/>
                    </file>
                    <attr name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow/org-openide-actions-PropertiesAction.instance" boolvalue="true"/>
                </folder>
            </folder>
        </folder>
    </folder>

Now try out your module. The context menu of DTD files should also contain your schema2beans action now.

You can do the same thing for the Editors context menu (the popup menu that apperars when you rightclick the editor tab)

Locate the entry in the Editors (filesystems/editors/application) section:

          <folder name="x-schema+xml">
                <folder name="Popup">
                    <file name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow">
                        <attr name="originalFile" stringvalue="Actions/XML/de-yourcompany-modules-schema2beans-Schema2BeansAction.instance"/>
                    </file>
                    <attr name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow/org-netbeans-modules-xml-core-actions-CollectDTDAction.instance" boolvalue="true"/>
                </folder>
            </folder>

make a copy of this entry and place it after the original. Change the name Attribute of your outer folder from “x-schema+xml” to “xml-dtd”:

<folder name="Editors">
        <folder name="application">
            <folder name="x-schema+xml">
                <folder name="Popup">
                    <file name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow">
                        <attr name="originalFile" stringvalue="Actions/XML/de-yourcompany-modules-schema2beans-Schema2BeansAction.instance"/>
                    </file>
                    <attr name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow/org-netbeans-modules-xml-core-actions-CollectDTDAction.instance" boolvalue="true"/>
                </folder>
            </folder>
            <folder name="xml-dtd">
                <folder name="Popup">
                    <file name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow">
                        <attr name="originalFile" stringvalue="Actions/XML/de-yourcompany-modules-schema2beans-Schema2BeansAction.instance"/>
                    </file>
                    <attr name="de-yourcompany-modules-schema2beans-Schema2BeansAction.shadow/org-netbeans-modules-xml-core-actions-CollectDTDAction.instance" boolvalue="true"/>
                </folder>
            </folder>
        </folder>
    </folder>

Now your editor tabs context menu should also contain this entry.

In my next blog entry we will add some support for setting parameters.

netbeans: schema2beans support for netbeans

Mittwoch, 25. Oktober 2006

I recently started my project to create a visual jasper report designer for netbeans. When I explored the jasperreports API I first thought JasperDesign was perfect for that. But  soon I found out, there is no (sensible) way to get informed of changes in the model.

I threw out JasperDesign and decided to go with schema2beans. schema2beans is a great XML marshalling framework because it’s simple to use and you can create classes that do not depend on the library.  For a dedicated Netbeans user using a commandline tool is like admitting defeat, so I had to include some basic support for schema2beans:

1. Create a new module project “schema2beanssupport”;

2. Download the schema2beans jars (org-netbeans-modules-schema2beans.jar , schema2beansdev.jar) and add them to the project (as described here ).

3. launch the Action wizard from the file menu (File->New File->Netbeans Module Development->Action ); Select “Conditionally enabled”  for DataObject, click next ; uncheck the global menuitem and select Filetype and editor context instead. As filetypes select “text/x-schema-xml” and “application/x-schema-xml”; give your action a nice name and display name (“Generate classes from schema” for example). The generated class will be opened in the editor.

4. Find the performAction method and add a few lines of code:

 protected void performAction(Node[] activatedNodes) {
        DataObject c = (DataObject) activatedNodes[0].getCookie(DataObject.class);
        performAction(c);
    }

5. add this method:

 protected void performAction(DataObject dataObject) {
    InputOutput io = IOProvider.getDefault().getIO ("Schema2Beans", true);
    String path = FileUtil.toFile(dataObject.getPrimaryFile()).getAbsolutePath();
    String dir = FileUtil.toFile(dataObject.getPrimaryFile().getParent()).getAbsolutePath();
    io.getOut().println("generating beans for "+path);
    try {
        String [] args = new String []{
            "-f",path,"-r",dir,"-javabeans","-st"
    };
    GenBeans.main(args);
    } catch (Exception ex) {
            ex.printStackTrace(io.getErr());
    }
 }

6. add the missing getProject method:

private Project getProject(FileObject file){         Project p = FileOwnerQuery.getOwner(file);        return p;    }

7. Get the missing APIs (I/O APIs,…) via the properties menu of your project and fix the imports (Alt – Shift – F). Now you should be able to use your new Action from the context menu of any schema file. Generated classes will be placed in the same directory as your schema.

In my next post I will show how to add the same support for dtd files.