comparing with /home/jarda/src/netbeans/main searching for changes changeset: 95910:1205560caab1 user: Jaroslav Tulach date: Wed Aug 13 17:46:14 2008 +0200 summary: Reenabling and enhancing parts of 80eea651d4d9 to demonstrate the problem with multiple instances diff -r 84c01928718d -r 1205560caab1 openide.loaders/src/org/openide/loaders/InstanceDataObject.java --- a/openide.loaders/src/org/openide/loaders/InstanceDataObject.java Tue Aug 12 16:15:17 2008 -0700 +++ b/openide.loaders/src/org/openide/loaders/InstanceDataObject.java Wed Aug 13 17:46:14 2008 +0200 @@ -1191,6 +1191,7 @@ /** Uses cache to remember list of classes to them this object is * assignable. */ + @Override public Class instanceClass() throws IOException, ClassNotFoundException { return super.instanceClass (customClassLoader); } @@ -1198,6 +1199,7 @@ /** Uses the cache to answer this question without loading the class itself, if the * cache exists. */ + @Override public boolean instanceOf (Class type) { // try the life object if any FileObject fo = entry ().getFile (); diff -r 84c01928718d -r 1205560caab1 openide.loaders/test/unit/src/org/openide/awt/MenuBarTest.java --- a/openide.loaders/test/unit/src/org/openide/awt/MenuBarTest.java Tue Aug 12 16:15:17 2008 -0700 +++ b/openide.loaders/test/unit/src/org/openide/awt/MenuBarTest.java Wed Aug 13 17:46:14 2008 +0200 @@ -41,11 +41,16 @@ package org.openide.awt; +import java.awt.event.ActionEvent; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URL; import java.util.ArrayList; import java.util.logging.Level; +import javax.swing.AbstractAction; import javax.swing.JMenu; import org.netbeans.junit.Log; import org.netbeans.junit.NbTestCase; @@ -56,8 +61,10 @@ import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.filesystems.Repository; +import org.openide.filesystems.XMLFileSystem; import org.openide.nodes.Node; import org.openide.util.HelpCtx; +import org.openide.util.Utilities; import org.openide.util.actions.CallbackSystemAction; /** @@ -75,11 +82,15 @@ super(testName); } + @Override protected Level logLevel() { return Level.FINE; } + @Override protected void setUp() throws Exception { + CreateOnlyOnceAction.instancesCount = 0; + FileObject fo = FileUtil.createFolder( Repository.getDefault().getDefaultFileSystem().getRoot(), "Folder" + getName() @@ -89,6 +100,7 @@ mb.waitFinished(); } + @Override protected void tearDown() throws Exception { } @@ -239,6 +251,37 @@ fail("There were warnings about the use of invalid nodes: " + seq); } } + + public void testActionIsCreatedOnlyOnce_13195() throws Exception { + doActionIsCreatedOnlyOnce_13195("Menu"); + } + + public void testActionIsCreatedOnlyOnceWithNewValue() throws Exception { + doActionIsCreatedOnlyOnce_13195("MenuWithNew"); + } + + private void doActionIsCreatedOnlyOnce_13195(String name) throws Exception { + // crate XML FS from data + String[] stringLayers = new String [] { "/org/openide/awt/data/testActionOnlyOnce.xml" }; + URL[] layers = new URL[stringLayers.length]; + + for (int cntr = 0; cntr < layers.length; cntr++) { + layers[cntr] = Utilities.class.getResource(stringLayers[cntr]); + } + + XMLFileSystem system = new XMLFileSystem(); + system.setXmlUrls(layers); + + // build menu + DataFolder dataFolder = DataFolder.findFolder(system.findResource(name)); + MenuBar menuBar = new MenuBar(dataFolder); + menuBar.waitFinished(); + + if (CreateOnlyOnceAction.instancesCount != 1) { + // ensure that only one instance of action was created + fail("Action created only once, but was: " + CreateOnlyOnceAction.instancesCount + "\n" + CreateOnlyOnceAction.w); + } + } public void componentAdded(ContainerEvent e) { add++; @@ -265,4 +308,27 @@ } + + public static class CreateOnlyOnceAction extends AbstractAction { + + static int instancesCount = 0; + static StringWriter w = new StringWriter(); + private static PrintWriter pw = new PrintWriter(w); + + public static synchronized CreateOnlyOnceAction create() { + new Exception("created for " + (++instancesCount) + " time").printStackTrace(pw); + return new CreateOnlyOnceAction(); + } + + public void actionPerformed(ActionEvent e) { + // no op + } + + private CreateOnlyOnceAction() { + putValue(NAME, "TestAction"); + } + + } + + } diff -r 84c01928718d -r 1205560caab1 openide.loaders/test/unit/src/org/openide/awt/data/testActionOnlyOnce.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.loaders/test/unit/src/org/openide/awt/data/testActionOnlyOnce.xml Wed Aug 13 17:46:14 2008 +0200 @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + changeset: 95911:0c03114d1532 user: Jaroslav Tulach date: Wed Aug 13 18:21:58 2008 +0200 summary: Special handling of "instanceClass" attribute - switches back to instanceCreate, but does not create the instance diff -r 1205560caab1 -r 0c03114d1532 openide.filesystems/src/org/openide/filesystems/XMLMapAttr.java --- a/openide.filesystems/src/org/openide/filesystems/XMLMapAttr.java Wed Aug 13 17:46:14 2008 +0200 +++ b/openide.filesystems/src/org/openide/filesystems/XMLMapAttr.java Wed Aug 13 18:21:58 2008 +0200 @@ -190,12 +190,16 @@ } Object retVal = null; - - try { - retVal = (attr == null) ? attr : attr.get(params); - } catch (Exception e) { - ExternalUtil.annotate(e, "attrName = " + attrName); //NOI18N - throw e; + if (attr == null && "instanceClass".equals(attrName)) { + attr = (Attr) map.get("instanceCreate"); + retVal = attr.getType(params); + } else { + try { + retVal = (attr == null) ? attr : attr.get(params); + } catch (Exception e) { + ExternalUtil.annotate(e, "attrName = " + attrName); //NOI18N + throw e; + } } if (retVal instanceof ModifiedAttribute) { @@ -733,6 +737,48 @@ } } + final Class getType(Object[] params) { + try { + if (obj != null) { + return obj.getClass(); + } + switch (keyIndex) { + case 0: + return Byte.class; + case 1: + return Short.class; + case 2: + return Integer.class; + case 3: + return Long.class; + case 4: + return Float.class; + case 5: + return Double.class; + case 6: + return Boolean.class; + case 7: + return Character.class; + case 8: + return value.getClass(); + case 9: + Method m = (Method) methodValue(value, params, true); + return m == null ? null : m.getReturnType(); + case 10: + return null; // return decodeValue(value); + case 11: + return URL.class; + case 12: + return ExternalUtil.findClass(Utilities.translate(value)); + case 13: + return String.class; + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + return null; + } + /** Returns class name of value object.*/ final String getClassName() { if (obj != null) { @@ -870,7 +916,7 @@ return value; case 9: - return methodValue(value, params); + return methodValue(value, params,false); case 10: return decodeValue(value); @@ -907,7 +953,7 @@ * @param params only 2 parametres will be used * @return Object or null */ - private final Object methodValue(String value, Object[] params) + private final Object methodValue(String value, Object[] params, boolean justMethod) throws Exception { int sepIdx = value.lastIndexOf('.'); @@ -957,6 +1003,9 @@ Method method = cls.getDeclaredMethod(methodName, paramArray[i]); if (method != null) { + if (justMethod) { + return method; + } method.setAccessible(true); return method.invoke(null, objArray); diff -r 1205560caab1 -r 0c03114d1532 openide.filesystems/test/unit/src/org/openide/filesystems/Count.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/Count.java Wed Aug 13 18:21:58 2008 +0200 @@ -0,0 +1,63 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2008 Sun Microsystems, Inc. + */ + +package org.openide.filesystems; + +/** + * + * @author Jaroslav Tulach + */ +public class Count implements Runnable { + static int cnt; + + public Count() { + cnt++; + } + + public static Count create() { + return new Count(); + } + + public static Runnable exec() { + return new Count(); + } + + public void run() { + } +} diff -r 1205560caab1 -r 0c03114d1532 openide.filesystems/test/unit/src/org/openide/filesystems/XMLFileSystemTestHid.java --- a/openide.filesystems/test/unit/src/org/openide/filesystems/XMLFileSystemTestHid.java Wed Aug 13 17:46:14 2008 +0200 +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/XMLFileSystemTestHid.java Wed Aug 13 18:21:58 2008 +0200 @@ -294,6 +294,82 @@ assertEquals(fo2.lastModified().getTime(), f2.lastModified()); assertFalse(fo2.lastModified().equals(fo.lastModified())); + } + + + public void testNoInstanceCreatedWithNewValue() throws Exception { + Count.cnt = 0; + File f = writeFile("layer.xml", + "\n" + + "\n" + + "" + + " " + + "\n" + + "\n" + + "\n" + ); + + xfs = FileSystemFactoryHid.createXMLSystem(getName(), this, f.toURL()); + FileObject fo = xfs.findResource ("TestModule/sample.txt"); + assertNotNull(fo); + + Object clazz = fo.getAttribute("instanceClass"); + assertEquals("No instance of Count created", 0, Count.cnt); + assertEquals("Yet right class guessed", Count.class, clazz); + Object instance = fo.getAttribute("instanceCreate"); + assertEquals("One instance of Count created", 1, Count.cnt); + assertNotNull("Returned", instance); + assertEquals("Right class", Count.class, instance.getClass()); + } + + public void testNoInstanceCreatedWithMethodValue1() throws Exception { + Count.cnt = 0; + File f = writeFile("layer.xml", + "\n" + + "\n" + + "" + + " " + + "\n" + + "\n" + + "\n" + ); + + xfs = FileSystemFactoryHid.createXMLSystem(getName(), this, f.toURL()); + FileObject fo = xfs.findResource ("TestModule/sample.txt"); + assertNotNull(fo); + + Object clazz = fo.getAttribute("instanceClass"); + assertEquals("No instance of Count created", 0, Count.cnt); + assertEquals("Yet right class guessed", Count.class, clazz); + Object instance = fo.getAttribute("instanceCreate"); + assertEquals("One instance of Count created", 1, Count.cnt); + assertNotNull("Returned", instance); + assertEquals("Right class", Count.class, instance.getClass()); + } + + public void testNoInstanceCreatedWithMethodValue2() throws Exception { + Count.cnt = 0; + File f = writeFile("layer.xml", + "\n" + + "\n" + + "" + + " " + + "\n" + + "\n" + + "\n" + ); + + xfs = FileSystemFactoryHid.createXMLSystem(getName(), this, f.toURL()); + FileObject fo = xfs.findResource ("TestModule/sample.txt"); + assertNotNull(fo); + + Object clazz = fo.getAttribute("instanceClass"); + assertEquals("No instance of Count created", 0, Count.cnt); + assertEquals("Only Runnable guessed as that is the return type of the method", Runnable.class, clazz); + Object instance = fo.getAttribute("instanceCreate"); + assertEquals("One instance of Count created", 1, Count.cnt); + assertNotNull("Returned", instance); + assertEquals("Right class", Count.class, instance.getClass()); } changeset: 95912:63a5dc42e285 tag: tip user: Jaroslav Tulach date: Thu Aug 14 10:40:09 2008 +0200 summary: Using prefix 'class:' instead of special handling for one attribute diff -r 0c03114d1532 -r 63a5dc42e285 core.startup/src/org/netbeans/core/startup/layers/BinaryFS.java --- a/core.startup/src/org/netbeans/core/startup/layers/BinaryFS.java Wed Aug 13 18:21:58 2008 +0200 +++ b/core.startup/src/org/netbeans/core/startup/layers/BinaryFS.java Thu Aug 14 10:40:09 2008 +0200 @@ -367,6 +367,11 @@ public Object getAttribute(String attrName) { initialize(); AttrImpl attr = attrs.get(attrName); + if (attr == null && attrName.startsWith("class:")) { + attr = attrs.get(attrName.substring(6)); + return attr == null ? null : attr.getType(this); + } + return (attr != null) ? attr.getValue(this, attrName) : null; } @@ -482,7 +487,7 @@ case 9: // urlvalue return new URL(value); case 10: // methodvalue - return methodValue (value,foProvider,attrName); + return methodValue (value,foProvider,attrName, false); case 11: // newvalue Class cls = findClass (value); // special support for singletons @@ -506,9 +511,40 @@ } return null; // problem getting the value... } + public Object getType( BFSBase foProvider) { + try { + switch(index) { + case 0: return Byte.class; + case 1: return Short.class; + case 2: return Integer.class; + case 3: return Long.class; + case 4: return Float.class; + case 5: return Double.class; + case 6: return Boolean.class; + case 7: return Character.class; + case 8: return String.class; + case 9: return URL.class; + case 10: // methodvalue + Method m = (Method)methodValue (value,foProvider,null, true); + return m == null ? null : m.getReturnType(); + case 11: // newvalue + return findClass (value); + case 12: // serialvalue + return null; + case 13: // bundle value + return String.class; + default: + throw new IllegalStateException("Bad index: " + index); // NOI18N + } + } catch (Exception exc) { + Exceptions.attachMessage(exc, "value = " + value + " from " + foProvider.getPath()); //NOI18N + Logger.getLogger(BinaryFS.class.getName()).log(Level.WARNING, null, exc); + } + return null; // problem getting the value... + } /** Constructs new attribute as Object. Used for dynamic creation: methodvalue. */ - private Object methodValue(String method, BFSBase foProvider, String attr) throws Exception { + private Object methodValue(String method, BFSBase foProvider, String attr, boolean onlyMethod) throws Exception { int i = method.lastIndexOf('.'); if (i != -1) { // Cf. XMLMapAttr.Attr.methodValue: @@ -537,6 +573,10 @@ values[j] = wrapToMap(foProvider.getFileObjectForAttr()); } } + if (onlyMethod) { + return m; + } + m.setAccessible(true); //otherwise cannot invoke private return m.invoke(null, values); } diff -r 0c03114d1532 -r 63a5dc42e285 openide.filesystems/apichanges.xml --- a/openide.filesystems/apichanges.xml Wed Aug 13 18:21:58 2008 +0200 +++ b/openide.filesystems/apichanges.xml Thu Aug 14 10:40:09 2008 +0200 @@ -46,6 +46,30 @@ Filesystems API + + + XMLFileSystem attributes can be queried for instance class + + + + + +

+ If you are interested just in the class of an attribute, but + without creating its instance, use fileObject.getAttribute("class:attrName"). + This instructs the XMLFileSystem + to scan its XML files for definition of attrName + attribute and guess its class. The guessing is + usually easy, just for methodvalue types, the system + needs to use some kind of heuristic: it locates the + appropriate factory method and returns its return type. This may + not be the actual type of the returned object at the end, but + it seems as the best guess without instantiating it. +

+
+ + +
Declarative MIME resolvers now available in standalone mode diff -r 0c03114d1532 -r 63a5dc42e285 openide.filesystems/arch.xml --- a/openide.filesystems/arch.xml Wed Aug 13 18:21:58 2008 +0200 +++ b/openide.filesystems/arch.xml Thu Aug 14 10:40:09 2008 +0200 @@ -357,7 +357,19 @@ --> -No. + + If you are interested just in the class of an + FileObject attribute, but + without creating its instance, use fileObject.getAttribute("class:attrName"). + This instructs the XMLFileSystem + to scan its XML files for definition of attrName + attribute and guess its class. The guessing is + usually easy, just for methodvalue types, the system + needs to use some kind of heuristic: it locates the + appropriate factory method and returns its return type. This may + not be the actual type of the returned object at the end, but + it seems as the best guess without instantiating it. + diff -r 0c03114d1532 -r 63a5dc42e285 openide.filesystems/nbproject/project.properties --- a/openide.filesystems/nbproject/project.properties Wed Aug 13 18:21:58 2008 +0200 +++ b/openide.filesystems/nbproject/project.properties Thu Aug 14 10:40:09 2008 +0200 @@ -43,4 +43,4 @@ javadoc.main.page=org/openide/filesystems/doc-files/api.html javadoc.arch=${basedir}/arch.xml javadoc.apichanges=${basedir}/apichanges.xml -spec.version.base=7.11.0 +spec.version.base=7.12.0 diff -r 0c03114d1532 -r 63a5dc42e285 openide.filesystems/src/org/openide/filesystems/XMLMapAttr.java --- a/openide.filesystems/src/org/openide/filesystems/XMLMapAttr.java Wed Aug 13 18:21:58 2008 +0200 +++ b/openide.filesystems/src/org/openide/filesystems/XMLMapAttr.java Thu Aug 14 10:40:09 2008 +0200 @@ -190,8 +190,8 @@ } Object retVal = null; - if (attr == null && "instanceClass".equals(attrName)) { - attr = (Attr) map.get("instanceCreate"); + if (attr == null && origAttrName.startsWith("class:")) { // NOI18N + attr = (Attr) map.get(origAttrName.substring(6)); retVal = attr.getType(params); } else { try { diff -r 0c03114d1532 -r 63a5dc42e285 openide.filesystems/test/unit/src/org/openide/filesystems/XMLFileSystemTestHid.java --- a/openide.filesystems/test/unit/src/org/openide/filesystems/XMLFileSystemTestHid.java Wed Aug 13 18:21:58 2008 +0200 +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/XMLFileSystemTestHid.java Thu Aug 14 10:40:09 2008 +0200 @@ -313,7 +313,7 @@ FileObject fo = xfs.findResource ("TestModule/sample.txt"); assertNotNull(fo); - Object clazz = fo.getAttribute("instanceClass"); + Object clazz = fo.getAttribute("class:instanceCreate"); assertEquals("No instance of Count created", 0, Count.cnt); assertEquals("Yet right class guessed", Count.class, clazz); Object instance = fo.getAttribute("instanceCreate"); @@ -338,7 +338,7 @@ FileObject fo = xfs.findResource ("TestModule/sample.txt"); assertNotNull(fo); - Object clazz = fo.getAttribute("instanceClass"); + Object clazz = fo.getAttribute("class:instanceCreate"); assertEquals("No instance of Count created", 0, Count.cnt); assertEquals("Yet right class guessed", Count.class, clazz); Object instance = fo.getAttribute("instanceCreate"); @@ -363,7 +363,7 @@ FileObject fo = xfs.findResource ("TestModule/sample.txt"); assertNotNull(fo); - Object clazz = fo.getAttribute("instanceClass"); + Object clazz = fo.getAttribute("class:instanceCreate"); assertEquals("No instance of Count created", 0, Count.cnt); assertEquals("Only Runnable guessed as that is the return type of the method", Runnable.class, clazz); Object instance = fo.getAttribute("instanceCreate"); @@ -372,6 +372,59 @@ assertEquals("Right class", Count.class, instance.getClass()); } + public void testClassBoolean() throws Exception { + doPrimitiveTypeTest("boolvalue='true'", Boolean.class); + } + + public void testClassByte() throws Exception { + doPrimitiveTypeTest("bytevalue='1'", Byte.class); + } + + public void testClassInt() throws Exception { + doPrimitiveTypeTest("intvalue='1'", Integer.class); + } + + public void testClassShort() throws Exception { + doPrimitiveTypeTest("shortvalue='1'", Short.class); + } + + public void testClassLong() throws Exception { + doPrimitiveTypeTest("longvalue='1'", Long.class); + } + public void testClassDouble() throws Exception { + doPrimitiveTypeTest("doublevalue='1.0'", Double.class); + } + public void testClassFloat() throws Exception { + doPrimitiveTypeTest("floatvalue='1.0'", Float.class); + } + public void testClassString() throws Exception { + doPrimitiveTypeTest("stringvalue='1'", String.class); + } + public void testClassURL() throws Exception { + doPrimitiveTypeTest("urlvalue='http://www.netbeans.org'", URL.class); + } + + private void doPrimitiveTypeTest(String value, Class expClass) throws Exception { + File f = writeFile("layer.xml", + "\n" + + "\n" + + "" + + " " + + "\n" + + "\n" + + "\n" + ); + + xfs = FileSystemFactoryHid.createXMLSystem(getName(), this, f.toURL()); + FileObject fo = xfs.findResource ("TestModule/sample.txt"); + assertNotNull(fo); + + Object clazz = fo.getAttribute("class:instanceCreate"); + assertEquals("Only Runnable guessed as that is the return type of the method", expClass, clazz); + Object instance = fo.getAttribute("instanceCreate"); + assertNotNull("Returned", instance); + assertEquals("Right class", expClass, instance.getClass()); + } private File writeFile(String name, String content) throws IOException { diff -r 0c03114d1532 -r 63a5dc42e285 openide.loaders/src/org/openide/loaders/InstanceDataObject.java --- a/openide.loaders/src/org/openide/loaders/InstanceDataObject.java Wed Aug 13 18:21:58 2008 +0200 +++ b/openide.loaders/src/org/openide/loaders/InstanceDataObject.java Thu Aug 14 10:40:09 2008 +0200 @@ -1147,11 +1147,19 @@ private static String getClassName(FileObject fo) { // first of all try "instanceClass" property of the primary file Object attr = fo.getAttribute (EA_INSTANCE_CLASS); + if (attr instanceof Class) { + return ((Class)attr).getName(); + } if (attr instanceof String) { return Utilities.translate((String) attr); } else if (attr != null) { err.warning( "instanceClass was a " + attr.getClass().getName()); // NOI18N + } + + attr = fo.getAttribute ("class:" + EA_INSTANCE_CREATE); + if (attr instanceof Class) { + return ((Class)attr).getName(); } attr = fo.getAttribute (EA_INSTANCE_CREATE); diff -r 0c03114d1532 -r 63a5dc42e285 openide.loaders/test/unit/src/org/openide/awt/MenuBarTest.java --- a/openide.loaders/test/unit/src/org/openide/awt/MenuBarTest.java Wed Aug 13 18:21:58 2008 +0200 +++ b/openide.loaders/test/unit/src/org/openide/awt/MenuBarTest.java Thu Aug 14 10:40:09 2008 +0200 @@ -52,6 +52,7 @@ import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.JMenu; +import javax.swing.SwingUtilities; import org.netbeans.junit.Log; import org.netbeans.junit.NbTestCase; import org.openide.actions.OpenAction; @@ -90,6 +91,8 @@ @Override protected void setUp() throws Exception { CreateOnlyOnceAction.instancesCount = 0; + CreateOnlyOnceAction.w = new StringWriter(); + CreateOnlyOnceAction.pw = new PrintWriter(CreateOnlyOnceAction.w); FileObject fo = FileUtil.createFolder( Repository.getDefault().getDefaultFileSystem().getRoot(), @@ -282,7 +285,7 @@ fail("Action created only once, but was: " + CreateOnlyOnceAction.instancesCount + "\n" + CreateOnlyOnceAction.w); } } - + public void componentAdded(ContainerEvent e) { add++; } @@ -312,11 +315,10 @@ public static class CreateOnlyOnceAction extends AbstractAction { static int instancesCount = 0; - static StringWriter w = new StringWriter(); - private static PrintWriter pw = new PrintWriter(w); + static StringWriter w; + static PrintWriter pw; public static synchronized CreateOnlyOnceAction create() { - new Exception("created for " + (++instancesCount) + " time").printStackTrace(pw); return new CreateOnlyOnceAction(); } @@ -324,7 +326,8 @@ // no op } - private CreateOnlyOnceAction() { + public CreateOnlyOnceAction() { + new Exception("created for " + (++instancesCount) + " time").printStackTrace(pw); putValue(NAME, "TestAction"); }