This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 205336 - ClassCastException: org.netbeans.modules.xml.XMLDataObject cannot be cast to org.openide.loaders.InstanceDataObject
Summary: ClassCastException: org.netbeans.modules.xml.XMLDataObject cannot be cast to ...
Status: RESOLVED FIXED
Alias: None
Product: platform
Classification: Unclassified
Component: Data Systems (show other bugs)
Version: 7.1
Hardware: All All
: P4 normal (vote)
Assignee: Jaroslav Tulach
URL:
Keywords:
Depends on:
Blocks: 179047
  Show dependency tree
 
Reported: 2011-11-21 07:16 UTC by Exceptions Reporter
Modified: 2012-04-27 10:01 UTC (History)
8 users (show)

See Also:
Issue Type: DEFECT
Exception Reporter: 182666


Attachments
stacktrace (1.69 KB, text/plain)
2011-11-21 07:16 UTC, Exceptions Reporter
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Exceptions Reporter 2011-11-21 07:16:02 UTC
Build: NetBeans IDE Dev (Build 201111200600)
VM: Java HotSpot(TM) 64-Bit Server VM, 19.1-b02, Java(TM) SE Runtime Environment, 1.6.0_24-b07
OS: Linux

User Comments:
aaronmahan: Starting Netbeans

tomjnsn: Starting up netbeans

aaronmahan: Importing plugins upon first startup of Netbeans install.

tomjnsn: Just starting up netbeans

tomjnsn: Starting up netbeans

tomjnsn: Just started up netbeans.  Some plugins don't work now (such as jVi)  I've tried reinstalling plugins to see if that would fix the problem but the exception persists.




Stacktrace: 
java.lang.ClassCastException: org.netbeans.modules.xml.XMLDataObject cannot be cast to org.openide.loaders.InstanceDataObject
   at org.openide.loaders.InstanceDataObject.storeSettings(InstanceDataObject.java:376)
   at org.openide.loaders.InstanceDataObject.access$900(InstanceDataObject.java:91)
   at org.openide.loaders.InstanceDataObject$Creator.run(InstanceDataObject.java:1540)
   at org.openide.filesystems.EventControl.runAtomicAction(EventControl.java:127)
   at org.openide.filesystems.FileSystem.runAtomicAction(FileSystem.java:566)
   at org.openide.loaders.DataObjectPool.runAtomicActionSimple(DataObjectPool.java:229)
Comment 1 Exceptions Reporter 2011-11-21 07:16:05 UTC
Created attachment 113355 [details]
stacktrace
Comment 2 err 2011-11-21 16:23:16 UTC
I've bumped the priority to P2 since this kills jVi.

I'll download latest and sources and see what I can find out.
Comment 3 err 2011-11-21 16:29:19 UTC
Looking at the exception reports it interesting that they started showing up on Mac-OSX on Nov 7. But didn't show up on Linux until Nov 21
Comment 4 err 2011-11-21 19:33:44 UTC
jVi puts over 60 items in "Editors/Actions". Last march I started doing it programatically instead of with layer.xml.

During the execution of statement
                InstanceDataObject.create(df, name + ".instance",
                                              action, null);
in the following code the exception occurs.


@ServiceProvider (service=FileSystem.class)
public class KeyActionsFS extends MultiFileSystem
{
    private static final String MY_ROOT = "Editors/Actions";

    private static KeyActionsFS INSTANCE;

    @SuppressWarnings("LeakingThisInConstructor")
    public KeyActionsFS() {
        //will be created on startup, exactly once
        assert INSTANCE == null;
        INSTANCE = this;
        // setPropagateMasks(true); // in case you want to use *_hidden masks
    }

    public static void injectKeyActionsLayer() {
        if (INSTANCE.getDelegates().length == 0) {
            try {
                FileSystem fs = FileUtil.createMemoryFileSystem();
                FileObject dir = FileUtil.createFolder(fs.getRoot(), MY_ROOT);
                DataFolder df = DataFolder.findFolder(dir);

                for(Action action : KeyBinding.getActionsList()) {
                    String name = (String)action.getValue(Action.NAME);
                    InstanceDataObject.create(df, name + ".instance",
                                              action, null);
                }

                INSTANCE.setDelegates(fs);
            } catch(IOException ex) {
                Logger.getLogger(KeyActionsFS.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
        }
    }
}
Comment 5 Theofanis Oikonomou 2011-11-23 10:28:07 UTC
Jesse should this be assigned to Data Systems?
Thank you
Comment 6 Jesse Glick 2011-11-23 15:24:47 UTC
Immediate bug - robustness - is clearly in openide.loaders. Is there a minimal self-contained test case?

I think the real problem here is in faulty module code; InstanceDataObject.create may only be called on a folder in the system filesystem (it ought to immediately throw an IllegalArgumentException if this is not true), since a *.xml file on any other filesystem is going to be treated as a plain old XML file by org.netbeans.modules.xml.XMLDataLoader.

Anyway the quoted module code would behave badly even in the absence of XMLDataLoader - you would not want to serialize an Action and then deserialize it! InstanceDataObject.create is useless for this purpose. On a memory filesystem you can simply use dir.createData("whatever.instance").setAttribute("instanceCreate", theActualInstance) and that object reference will be held as is.

Only applies to a single module not in the standard distro, root cause is badly written module code, NB bug is just in failing to throw a more informative exception earlier => P4.
Comment 7 err 2011-11-23 16:23:40 UTC
(In reply to comment #6)

> I think the real problem here is in faulty module code;

Could be. Though the code's been working since March and started failing a few days ago on linux.

I will do:
    dir.createData(name + ".instance")
       .setAttribute("instanceCreate", action)
in the loop and see how it goes

> NB bug is just in failing to throw a more informative
> exception earlier => P4.

About 8 months "earlier" would have been good ;-)



> Immediate bug - robustness - is clearly in openide.loaders. Is there a minimal
> self-contained test case?

If someone can point to a unit test in the right test directory that could serve as a template, I could do one, but I'm not sure I see the usefulness since:

    > InstanceDataObject.create may only be called on a folder in the
    > system filesystem (it ought to immediately throw an 
    > IllegalArgumentException if this is not true)

But, assuming I get something that works, I wouldn't mind submitting a unit test with the new code so it doesn't break again.
Comment 8 Jesse Glick 2011-11-23 17:54:50 UTC
(In reply to comment #7)
> the code's been working since March and started failing a few
> days ago on linux.

Sorry, no clue what would have changed recently.

Note that IDO.create would work on any filesystem if the result is a *.instance file - i.e. a SharedClassObject; or if the result is a *.settings file - anything else, possibly needing serialization. Here it seems it is creating a *.xml file. I am not sure what would trigger that; InstanceDataObject.Creator does not seem to ever create *.xml. Or perhaps a *.settings is being created but XMLDataLoader recognizes it for some reason TBD. Yarda probably knows this code better and could say.

> About 8 months "earlier" would have been good

Sure; possibly you are the first person to try doing this, so no one thought to defend against it. (I am just guessing that running IDO.create on a non-system filesystem cannot work, but it may depend on the real explanation of this exception.)
Comment 9 err 2011-11-24 03:22:20 UTC
(In reply to comment #8)
> (I am just guessing that running IDO.create on a non-system
> filesystem cannot work,

Isn't that what jVi's been doing sucessfully?

Anyway...

As indicated, I did
    dir.createData(name + ".instance")
       .setAttribute("instanceCreate", action)
and jVi seems to start up now. But...

Now I get 60+ like following, any idea how to get rid of? Would something like
    xxx.setAttribute("instanceOf", "javax.swing.Action")
work, or use a Class object? or...

WARNING [org.openide.loaders.InstanceDataObject]: Instance file MultiFileObject@1de993a[Editors/Actions/ViCtrl-TKey.instance] uses instanceCreate attribute, but doesn't define instanceOf attribute. Please add instanceOf attr to avoid multiple instances creation,see details at http://www.netbeans.org/issues/show_bug.cgi?id=131951
Comment 10 Jaroslav Tulach 2011-11-24 06:50:04 UTC
The .settings loader is preferred on system file system. On other systems, it is one of the last ones. Imho, there had to be some change in XML module that started to recognize .settings files during last few months.
Comment 11 Svata Dedic 2011-11-24 07:32:56 UTC
I've added fix for issue #206346 (changeset jet-main #9c0ebcc2eecb), adding a fallback MIME resolver for XML files, based on "magic" <?xml header.
Comment 12 err 2011-11-24 16:17:12 UTC
(In reply to comment #11)
> I've added fix for issue #206346 (changeset jet-main #9c0ebcc2eecb), adding a
> fallback MIME resolver for XML files, based on "magic" <?xml header.

Actually that's issue #191544
Comment 13 Svata Dedic 2011-11-24 16:19:01 UTC
Sorry :-/ wrong clipboard content during copy/paste ... thanks for correction
Comment 14 err 2011-11-24 20:44:37 UTC
Thanks Jesse, the code
        FileObject fo = dir.createData(name + ".instance");
        fo.setAttribute("instanceCreate", action);
seems to work.

The check in InstanceDataObject::getClassName that produces the WARNING may be flawed when the FileObject is set up programatically. Doing
        fo.setAttribute("instanceOf", "javax.swing.Action");
does not get rid of the warning. 

But doing
        fo.setAttribute("instanceClass", action.getClass());
or
        fo.setAttribute("instanceClass", Action.class);
does get rid of the warning.

After a quick look at the code, I was lost as to what's going on in InstanceDataObject.java in this case to actually pick up the object.
Comment 15 Jesse Glick 2011-11-30 13:39:30 UTC
(In reply to comment #11)
> jet-main #9c0ebcc2eecb [adds] a
> fallback MIME resolver for XML files, based on "magic" <?xml header

Possibly this should be limited so it does not accidentally match *.settings files. (Not sure if the DTD is capable of expressing that, unfortunately; depend on bug #18910 if not.)

That would explain the apparent regression: XMLDataLoader always ignored files on the SFS, but accepted files on other FSs even if injected into the SFS (reporter's situation); but previously *.settings was not matched by anything, whereas now xml-fallback-resolver.xml treats it as text/xml so XMLDL recognizes it. The following fails with the reported CCE:

package org.netbeans.modules.xml;
import java.util.ArrayList;
import junit.framework.Test;
import org.netbeans.junit.NbModuleSuite;
import org.netbeans.junit.NbTestCase;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataFolder;
import org.openide.loaders.InstanceDataObject;
public class InstanceDataObjectInXmlTest extends NbTestCase {
    public InstanceDataObjectInXmlTest(String name) {
        super(name);
    }
    public static Test suite() {
        return NbModuleSuite.createConfiguration(InstanceDataObjectInXmlTest.class).gui(false).suite();
    }
    public void testInstanceDataObjectCreate() throws Exception {
        InstanceDataObject.create(DataFolder.findFolder(FileUtil.createMemoryFileSystem().getRoot()), null, new ArrayList<Object>(), null);
    }
}

(In reply to comment #14)
> The check in InstanceDataObject::getClassName that produces the WARNING may be
> flawed when the FileObject is set up programatically.

Quite possible, since probably you are the first to try it.

> Doing
>         fo.setAttribute("instanceOf", "javax.swing.Action");
> does not get rid of the warning. 

Did you try setting this attribute _before_ instanceCreate? Might be a race condition.

>         fo.setAttribute("instanceClass", action.getClass());
> or
>         fo.setAttribute("instanceClass", Action.class);
> does get rid of the warning.

Properly it would be Action.class.getName() (the attr is of type String) but anyway this is wrong; instanceClass is only for cases where instanceCreate is not set.

> I was lost as to what's going on in InstanceDataObject.java

I think the warning is wrong and should be removed. See bug #131951 comment #43 for some background. There is no purpose for instanceOf on an eager memory filesystem, nor (acc. to #44) for XMLFS-defined files (layers), only on some hypothetical injectable filesystem that supports laziness yet is not based on XMLFS. This seems sufficiently unlikely that the warning is more likely to be misleading, as here.

Anyway it is not clear that 2de8bea801db was right; it changed the warning text but not the surrounding logic in getClassName, which continues to check for instanceClass, not instanceOf.
Comment 16 err 2011-11-30 22:17:51 UTC
> (In reply to comment #14)
> > Doing
> >         fo.setAttribute("instanceOf", "javax.swing.Action");
> > does not get rid of the warning. 
> 
> Did you try setting this attribute _before_ instanceCreate? Might be a race
> condition.

Doh! Exception *was* when doing 'setAttribute("instanceCreate"' But doing
            fo.setAttribute("instanceOf", "javax.swing.Action");
            fo.setAttribute("instanceCreate", action);
still produces the warning

I'll leave it as
            fo.setAttribute("instanceCreate", action);
            fo.setAttribute("instanceClass", action.getClass().getName());
Since this doesn't produce a warning (they're all same class). And it avoids that messy serialized .setting thing that gets persisted (Ugh). 

If the warning gets removed as Jesse suggests. Then only
            fo.setAttribute("instanceCreate", action);
is needed? I saw the warning last March; avoiding it might be how I ended up inadvertantly creating a .setting, but I don't remember.
Comment 17 Jaroslav Tulach 2011-12-05 12:23:11 UTC
OK. Any remaining complain? Can I get a unit test, if so?
Comment 18 Jesse Glick 2011-12-05 15:42:26 UTC
(In reply to comment #17)
> Any remaining complain[ts]?

Yes. The test I gave in comment #15 fails whereas I think it should either pass, or (if this scenario is intentionally not supported) throw a meaningful exception earlier. Also as I described in comment #15 the warning is wrong and should be removed.
Comment 19 Jesse Glick 2011-12-05 15:42:38 UTC
...so reopening.
Comment 20 Jaroslav Tulach 2012-04-25 15:51:00 UTC
ergonomics#3bcf706b3b7b
Comment 21 Quality Engineering 2012-04-27 10:01:32 UTC
Integrated into 'main-golden', will be available in build *201204270400* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress)
Changeset: http://hg.netbeans.org/main-golden/rev/3bcf706b3b7b
User: Jaroslav Tulach <jtulach@netbeans.org>
Log: #205336: InstanceDataObject.create should work on non-systemfilesystem filesystems as well. Using setPreferredLoader.