blob: 7d33b5d2d9f0e5dbf0aac33504a0c88023c90d83 [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.
*/
package org.openide.loaders;
import org.openide.filesystems.*;
import java.io.*;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.logging.Level;
import org.netbeans.junit.Log;
import org.netbeans.junit.RandomlyFails;
import org.netbeans.modules.openide.util.NbMutexEventProvider;
import org.openide.cookies.*;
import org.openide.nodes.Node;
import org.openide.util.RequestProcessor;
import org.openide.xml.XMLUtil;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
/**
*
* @author Jaroslav Tulach
*/
public class XMLDataObjectTest extends org.netbeans.junit.NbTestCase {
private FileObject data;
private CharSequence log;
public XMLDataObjectTest (String name) {
super (name);
}
@Override
protected void setUp () throws Exception {
clearWorkDir();
log = Log.enable("org.openide.loaders", Level.WARNING);
super.setUp ();
System.setProperty ("org.openide.util.Lookup", "org.openide.loaders.XMLDataObjectTest$Lkp");
String fsstruct [] = new String [] {
};
FileSystem fs = TestUtilHid.createLocalFileSystem (getWorkDir(), fsstruct);
data = FileUtil.createData (
fs.getRoot (),
"kuk/test/my.xml"
);
FileLock lock = data.lock ();
OutputStream os = data.getOutputStream (lock);
PrintStream p = new PrintStream (os);
p.println ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
p.println ("<root>");
p.println ("</root>");
p.close ();
lock.releaseLock ();
// initialize the document before we start to measure the access
assertNotNull("Constructor ready", XMLDataObject.cnstr);
assertParse(false, false);
assertParse(false, true);
assertParse(true, false);
assertParse(true, true);
}
private static void assertParse(boolean validate, boolean namespace) throws Exception {
try {
XMLUtil.parse(new InputSource(new ByteArrayInputStream(new byte[0])), validate, namespace, null, null);
} catch (SAXParseException ex) {
}
}
@Override
protected void tearDown () throws Exception {
super.tearDown ();
TestUtilHid.destroyLocalFileSystem (getName());
if (log.length() > 0) {
fail("There should be no warnings:\n" + log);
}
}
public void testGetStatusBehaviour () throws Exception {
DataObject obj = DataObject.find (data);
assertEquals ("Is xml", XMLDataObject.class, obj.getClass ());
XMLDataObject xml = (XMLDataObject)obj;
assertEquals ("not parsed yet", XMLDataObject.STATUS_NOT, xml.getStatus ());
org.w3c.dom.Document doc = xml.getDocument ();
assertEquals ("still not parsed as we have lazy document", XMLDataObject.STATUS_NOT, xml.getStatus ());
String id = doc.getDoctype ().getPublicId ();
assertEquals ("still not parsed as we have special support for publilc id", XMLDataObject.STATUS_NOT, xml.getStatus ());
org.w3c.dom.Element e = doc.getDocumentElement ();
assertNotNull ("Document parsed", doc);
assertEquals ("status is ok", XMLDataObject.STATUS_OK, xml.getStatus ());
assertNotNull("Has open cookie", xml.getCookie(OpenCookie.class));
assertNotNull("Has open cookie in lookup", xml.getLookup().lookup(OpenCookie.class));
Reference<Object> ref = new WeakReference<Object>(xml);
xml = null;
obj = null;
doc = null;
e = null;
assertGC("Data object has to be garbage collectable", ref);
}
public void testCookieIsUpdatedWhenContentChanges () throws Exception {
FileLock lck;
DataObject obj;
lck = data.lock();
PCL pcl = new PCL ();
// this next line causes the test to fail on 2004/03/03
obj = DataObject.find (data);
obj.addPropertyChangeListener (pcl);
assertNull ("No instance cookie", obj.getCookie (org.openide.cookies.InstanceCookie.class));
assertEquals (0, pcl.cnt);
try {
OutputStream ostm = data.getOutputStream(lck);
PrintWriter pw = new PrintWriter(new OutputStreamWriter(ostm, "UTF8")); //NOI18N
pw.println("<?xml version='1.0'?>"); //NOI18N
pw.println("<!DOCTYPE driver PUBLIC '-//NetBeans//DTD JDBC Driver 1.0//EN' 'http://www.netbeans.org/dtds/jdbc-driver-1_0.dtd'>"); //NOI18N
pw.println("<driver>"); //NOI18N
pw.println(" <name value='somename'/>"); //NOI18N
pw.println(" <class value='java.lang.String'/>"); //NOI18N
pw.println(" <urls>"); //NOI18N
pw.println(" </urls>"); //NOI18N
pw.println("</driver>"); //NOI18N
pw.flush();
pw.close();
ostm.close();
} finally {
lck.releaseLock();
}
assertEquals ("One change fired when the file was written", 1, pcl.cnt);
assertNotNull ("There is an cookie", obj.getCookie (org.openide.cookies.InstanceCookie.class));
}
@RandomlyFails // NB-Core-Build #1691
public void testToolbarsAreBrokenAsTheLookupIsClearedTooOftenIssue41360 () throws Exception {
FileLock lck;
DataObject obj;
lck = data.lock();
String id = "-//NetBeans//DTD Fake Toolbar 1.0//EN";
XMLDataObject.Info info = new XMLDataObject.Info ();
info.addProcessorClass (ToolbarProcessor.class);
try {
XMLDataObject.registerInfo (id, info);
OutputStream ostm = data.getOutputStream(lck);
PrintWriter pw = new PrintWriter(new OutputStreamWriter(ostm, "UTF8")); //NOI18N
pw.println("<?xml version='1.0'?>"); //NOI18N
pw.println("<!DOCTYPE toolbar PUBLIC '" + id + "' 'http://www.netbeans.org/dtds/jdbc-driver-1_0.dtd'>"); //NOI18N
pw.println("<toolbar>"); //NOI18N
pw.println(" <name value='somename'/>"); //NOI18N
pw.println(" <class value='java.lang.String'/>"); //NOI18N
pw.println(" <urls>"); //NOI18N
pw.println(" </urls>"); //NOI18N
pw.println("</toolbar>"); //NOI18N
pw.flush();
pw.close();
ostm.close();
obj = DataObject.find (data);
PCL pcl = new PCL ();
obj.addPropertyChangeListener (pcl);
InstanceCookie cookie = (InstanceCookie)obj.getCookie (InstanceCookie.class);
assertNotNull (cookie);
assertEquals ("No changes yet", 0, pcl.cnt);
assertNotNull("Data object in lkp", obj.getLookup().lookup(DataObject.class));
assertNotNull("Data object in lkp", obj.getLookup().lookup(FileObject.class));
assertNotNull("Data object in cookie", obj.getCookie(DataObject.class));
checkLookup(obj, 4);
pcl.cnt = 0;
ostm = data.getOutputStream(lck);
pw = new java.io.PrintWriter(new OutputStreamWriter(ostm, "UTF8")); //NOI18N
pw.println("<?xml version='1.0'?>"); //NOI18N
pw.println("<!DOCTYPE toolbar PUBLIC '" + id + "' 'http://www.netbeans.org/dtds/jdbc-driver-1_0.dtd'>"); //NOI18N
pw.println("<toolbar>"); //NOI18N
pw.println(" <name value='somename'/>"); //NOI18N
pw.println(" <class value='java.lang.String'/>"); //NOI18N
pw.println(" <urls>"); //NOI18N
pw.println(" </urls>"); //NOI18N
pw.println("</toolbar>"); //NOI18N
pw.flush();
pw.close();
ostm.close();
InstanceCookie newCookie = (InstanceCookie)obj.getCookie (InstanceCookie.class);
assertNotNull (newCookie);
assertEquals ("One change in document", 1, pcl.docChange);
assertEquals ("The cookie is still the same", cookie, newCookie);
assertEquals ("No cookie change", 0, pcl.cnt);
} finally {
XMLDataObject.registerInfo (id, null);
lck.releaseLock ();
}
}
public void testWrongUTFCharacer() throws Exception {
FileLock lck;
DataObject obj;
FileObject d = data.getParent().createData("wrongutfchar.xml");
lck = d.lock();
OutputStream os = d.getOutputStream(lck);
os.write(0xc5); // multibyte
os.write(0x00); // wrong char after multibyte
os.close();
obj = DataObject.find(d);
XMLDataObject xml = (XMLDataObject)obj;
String id = xml.getDocument().getDoctype().getPublicId();
assertEquals("No ID", null, id);
assertEquals("No warnings\n" + log, 0, log.length());
}
public void testCheckLookupContent() throws DataObjectNotFoundException {
DataObject obj = DataObject.find(data);
checkLookup(obj, 12);
}
private static void checkLookup(DataObject obj, int expected) throws DataObjectNotFoundException {
Collection<? extends Object> all = obj.getLookup().lookupAll(Object.class);
int cnt = 0;
for (Object object : all) {
assertEquals("Is in lkp", object, obj.getLookup().lookup(object.getClass()));
Class c = object.getClass();
if (object instanceof EditorCookie) {
c = EditorCookie.class;
}
if (object instanceof Node.Cookie) {
assertEquals("Is in cookie: " + c.getSuperclass(), object, obj.getCookie(c));
}
cnt++;
}
assertEquals("There are some items:\n" + all, expected, cnt);
}
public static final class Lkp extends org.openide.util.lookup.AbstractLookup
implements org.openide.loaders.Environment.Provider {
public Lkp () {
this (new org.openide.util.lookup.InstanceContent ());
}
private Lkp (org.openide.util.lookup.InstanceContent ic) {
super (ic);
ic.add (this); // Environment.Provider
ic.add (new NbMutexEventProvider());
}
public org.openide.util.Lookup getEnvironment (org.openide.loaders.DataObject obj) {
if (obj instanceof XMLDataObject) {
try {
XMLDataObject xml = (XMLDataObject)obj;
final String id = xml.getDocument ().getDoctype ().getPublicId ();
if (id != null) {
return org.openide.util.lookup.Lookups.singleton (new org.openide.cookies.InstanceCookie () {
public Object instanceCreate () {
return id;
}
public Class instanceClass () {
return String.class;
}
public String instanceName () {
return instanceClass ().getName ();
}
});
}
} catch (Exception ex) {
fail (ex.getMessage ());
}
}
return null;
}
} // end of Lkp
/** Processor.
*/
public static class ToolbarProcessor
implements XMLDataObject.Processor, InstanceCookie.Of {
public void attachTo (org.openide.loaders.XMLDataObject xmlDO) {
}
public Class instanceClass () throws java.io.IOException, ClassNotFoundException {
return getClass ();
}
public Object instanceCreate () throws java.io.IOException, ClassNotFoundException {
return this;
}
public String instanceName () {
return getClass ().getName ();
}
public boolean instanceOf (Class type) {
return type.isAssignableFrom (getClass());
}
} // end of ToolbarProcessor
public void testGetCookieCannotBeReentrantFromMoreThreads () throws Exception {
FileLock lck;
DataObject obj;
lck = data.lock();
String id = "-//NetBeans//DTD X Prcs 1.0//EN";
XMLDataObject.Info info = new XMLDataObject.Info ();
info.addProcessorClass (XProcessor.class);
try {
XMLDataObject.registerInfo (id, info);
OutputStream ostm = data.getOutputStream(lck);
PrintWriter pw = new PrintWriter(new OutputStreamWriter(ostm, "UTF8")); //NOI18N
pw.println("<?xml version='1.0'?>"); //NOI18N
pw.println("<!DOCTYPE toolbar PUBLIC '" + id + "' 'http://www.netbeans.org/dtds/jdbc-driver-1_0.dtd'>"); //NOI18N
pw.println("<toolbar>"); //NOI18N
pw.println(" <name value='somename'/>"); //NOI18N
pw.println(" <class value='java.lang.String'/>"); //NOI18N
pw.println(" <urls>"); //NOI18N
pw.println(" </urls>"); //NOI18N
pw.println("</toolbar>"); //NOI18N
pw.flush();
pw.close();
ostm.close();
obj = DataObject.find (data);
Object ic = obj.getCookie(InstanceCookie.class);
assertNotNull("There is a cookie", ic);
assertEquals("The right class", XProcessor.class, ic.getClass());
XProcessor xp = (XProcessor)ic;
// now it can finish
xp.task.waitFinished();
assertNotNull("Cookie created", xp.cookie);
assertEquals("It is the same as me", xp.cookie, xp);
} finally {
XMLDataObject.registerInfo (id, null);
lck.releaseLock ();
}
}
/** Processor.
*/
public static class XProcessor
implements XMLDataObject.Processor, InstanceCookie.Of, Runnable {
private XMLDataObject obj;
private Node.Cookie cookie;
private RequestProcessor.Task task;
public void attachTo (org.openide.loaders.XMLDataObject xmlDO) {
obj = xmlDO;
task = RequestProcessor.getDefault().post(this);
try {
assertFalse("This is going to time out", task.waitFinished(500));
} catch (InterruptedException ex) {
ex.printStackTrace();
fail("No exceptions please");
}
assertNull("Cookie is still null", cookie);
}
public void run () {
cookie = obj.getCookie(InstanceCookie.class);
}
public Class instanceClass () throws java.io.IOException, ClassNotFoundException {
return getClass ();
}
public Object instanceCreate () throws java.io.IOException, ClassNotFoundException {
return this;
}
public String instanceName () {
return getClass ().getName ();
}
public boolean instanceOf (Class type) {
return type.isAssignableFrom (getClass());
}
} // end of XProcessor
private static class PCL implements java.beans.PropertyChangeListener {
int cnt;
int docChange;
public void propertyChange (java.beans.PropertyChangeEvent ev) {
if (DataObject.PROP_COOKIE.equals (ev.getPropertyName ())) {
cnt++;
}
if (XMLDataObject.PROP_DOCUMENT.equals (ev.getPropertyName ())) {
docChange++;
}
}
} // end of PCL
}