diff -r 54f623a0e6e1 -r 049d4cfc8b19 apisupport.project/src/org/netbeans/modules/apisupport/project/ui/resources/layer.xml --- a/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/resources/layer.xml Tue Jun 03 15:47:50 2008 -0700 +++ b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/resources/layer.xml Fri Jun 06 17:19:40 2008 +0200 @@ -200,6 +200,7 @@ made subject to such option by the copyr + diff -r 54f623a0e6e1 -r 049d4cfc8b19 apisupport.project/src/org/netbeans/modules/apisupport/project/ui/wizard/loader/NewLoaderIterator.java --- a/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/wizard/loader/NewLoaderIterator.java Tue Jun 03 15:47:50 2008 -0700 +++ b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/wizard/loader/NewLoaderIterator.java Fri Jun 06 17:19:40 2008 +0200 @@ -44,6 +44,8 @@ import java.io.CharConversionException; import java.io.CharConversionException; import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -65,6 +67,7 @@ import org.openide.loaders.DataFolder; import org.openide.loaders.DataFolder; import org.openide.loaders.DataObject; import org.openide.modules.SpecificationVersion; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.xml.XMLUtil; @@ -178,6 +181,18 @@ final class NewLoaderIterator extends Ba public static void generateFileChanges(DataModel model) { CreatedModifiedFiles fileChanges = new CreatedModifiedFiles(model.getProject()); + + boolean loaderlessObject; + boolean lookupReadyObject; + try { + SpecificationVersion current = model.getModuleInfo().getDependencyVersion("org.openide.loaders"); + loaderlessObject = current.compareTo(new SpecificationVersion("7.1")) >= 0; // NOI18N + lookupReadyObject = current.compareTo(new SpecificationVersion("6.0")) >= 0; // NOI18N + } catch (IOException ex) { + Logger.getLogger(NewLoaderIterator.class.getName()).log(Level.INFO, null, ex); + loaderlessObject = false; + lookupReadyObject = false; + } String namePrefix = model.getPrefix(); String packageName = model.getPackageName(); @@ -191,26 +206,30 @@ final class NewLoaderIterator extends Ba // Copy action icon String origIconPath = model.getIconPath(); + String relativeIconPath; if (origIconPath != null && new File(origIconPath).exists()) { - String relativeIconPath = model.addCreateIconOperation(fileChanges, origIconPath); + relativeIconPath = model.addCreateIconOperation(fileChanges, origIconPath); replaceTokens.put("IMAGESNIPPET", formatImageSnippet(relativeIconPath));//NOI18N replaceTokens.put("ICONPATH", relativeIconPath);//NOI18N replaceTokens.put("COMMENTICON", "");//NOI18N - } else { replaceTokens.put("IMAGESNIPPET", formatImageSnippet(null)); //NOI18N replaceTokens.put("ICONPATH", "SET/PATH/TO/ICON/HERE"); //NOI18N replaceTokens.put("COMMENTICON", "//");//NOI18N + relativeIconPath = null; } - // 1. create dataloader file - String loaderName = model.getDefaultPackagePath(namePrefix + "DataLoader.java", false); // NOI18N - // XXX use nbresloc URL protocol rather than NewLoaderIterator.class.getResource(...): - FileObject template = CreatedModifiedFiles.getTemplate("templateDataLoader.java");//NOI18N - fileChanges.add(fileChanges.createFileWithSubstitutions(loaderName, template, replaceTokens)); - String loaderInfoName = model.getDefaultPackagePath(namePrefix + "DataLoaderBeanInfo.java", false); // NOI18N - template = CreatedModifiedFiles.getTemplate("templateDataLoaderBeanInfo.java");//NOI18N - fileChanges.add(fileChanges.createFileWithSubstitutions(loaderInfoName, template, replaceTokens)); + FileObject template; + if (!loaderlessObject) { + // 1. create dataloader file + String loaderName = model.getDefaultPackagePath(namePrefix + "DataLoader.java", false); // NOI18N + // XXX use nbresloc URL protocol rather than NewLoaderIterator.class.getResource(...): + template = CreatedModifiedFiles.getTemplate("templateDataLoader.java");//NOI18N + fileChanges.add(fileChanges.createFileWithSubstitutions(loaderName, template, replaceTokens)); + String loaderInfoName = model.getDefaultPackagePath(namePrefix + "DataLoaderBeanInfo.java", false); // NOI18N + template = CreatedModifiedFiles.getTemplate("templateDataLoaderBeanInfo.java");//NOI18N + fileChanges.add(fileChanges.createFileWithSubstitutions(loaderInfoName, template, replaceTokens)); + } // 2. dataobject file final boolean isEditable = Pattern.matches("(application/([a-zA-Z0-9_.-])*\\+xml|text/([a-zA-Z0-9_.+-])*)", //NOI18N @@ -229,24 +248,24 @@ final class NewLoaderIterator extends Ba String doName = model.getDefaultPackagePath(namePrefix + "DataObject.java", false); // NOI18N template = null; - try { - SpecificationVersion current = model.getModuleInfo().getDependencyVersion("org.openide.loaders"); - SpecificationVersion desired = new SpecificationVersion("6.0"); // NOI18N - if (current.compareTo(desired) >= 0) { + if (loaderlessObject) { + template = CreatedModifiedFiles.getTemplate("templateDataObjectInLayer.java");//NOI18N + } else { + if (lookupReadyObject) { template = CreatedModifiedFiles.getTemplate("templateDataObjectWithLookup.java");//NOI18N } - } catch (IOException ex) { - Logger.getLogger(NewLoaderIterator.class.getName()).log(Level.INFO, null, ex); } if (template == null) { template = CreatedModifiedFiles.getTemplate("templateDataObject.java");//NOI18N } fileChanges.add(fileChanges.createFileWithSubstitutions(doName, template, replaceTokens)); - // 3. node file - String nodeName = model.getDefaultPackagePath(namePrefix + "DataNode.java", false); // NOI18N - template = CreatedModifiedFiles.getTemplate("templateDataNode.java");//NOI18N - fileChanges.add(fileChanges.createFileWithSubstitutions(nodeName, template, replaceTokens)); + if (!loaderlessObject) { + // 3. node file + String nodeName = model.getDefaultPackagePath(namePrefix + "DataNode.java", false); // NOI18N + template = CreatedModifiedFiles.getTemplate("templateDataNode.java");//NOI18N + fileChanges.add(fileChanges.createFileWithSubstitutions(nodeName, template, replaceTokens)); + } // 4. mimetyperesolver file template = CreatedModifiedFiles.getTemplate("templateresolver.xml");//NOI18N @@ -273,18 +292,38 @@ final class NewLoaderIterator extends Ba fileChanges.add(fileChanges.bundleKey(bundlePath, "LBL_" + namePrefix + "_loader_name", // NOI18N NbBundle.getMessage(NewLoaderIterator.class, "LBL_LoaderName", namePrefix))); //NOI18N - // 7. register manifest entry - boolean isXml = Pattern.matches("(application/([a-zA-Z0-9_.-])*\\+xml|text/([a-zA-Z0-9_.-])*\\+xml)", //NOI18N - mime); - String installBefore = null; - if (isXml) { - installBefore = "org.openide.loaders.XMLDataObject, org.netbeans.modules.xml.XMLDataObject"; //NOI18N + if (loaderlessObject) { + // 7. register in layer + String path = "Loaders/" + mime + "/Factories/" + namePrefix + "DataLoader.instance"; + Map attrs = new HashMap(); + attrs.put("instanceCreate", "methodvalue:org.openide.loaders.DataLoaderPool.factory"); //NOI18N + attrs.put("dataObjectClass", packageName + "." + namePrefix + "DataObject"); //NOI18N + attrs.put("mimeType", mime); //NOI18N + if (relativeIconPath != null) { + try { + URL url = new URL("nbresloc:/" + relativeIconPath); //NOI18N + attrs.put("SystemFileSystem.icon", url); //NOI18N + } catch (MalformedURLException ex) { + throw new IllegalStateException(ex); + } + } + fileChanges.add( + fileChanges.createLayerEntry(path, null, null, null, attrs) + ); + } else { + // 7. register manifest entry + boolean isXml = Pattern.matches("(application/([a-zA-Z0-9_.-])*\\+xml|text/([a-zA-Z0-9_.-])*\\+xml)", //NOI18N + mime); + String installBefore = null; + if (isXml) { + installBefore = "org.openide.loaders.XMLDataObject, org.netbeans.modules.xml.XMLDataObject"; //NOI18N + } + + fileChanges.add(fileChanges.addLoaderSection(packageName.replace('.', '/') + "/" + namePrefix + "DataLoader", installBefore)); // NOI18N + + // 7a. create matching test registration for convenience (#73202) + fileChanges.add(fileChanges.addLookupRegistration("org.openide.loaders.DataLoader", packageName + '.' + namePrefix + "DataLoader", true)); // NOI18N } - - fileChanges.add(fileChanges.addLoaderSection(packageName.replace('.', '/') + "/" + namePrefix + "DataLoader", installBefore)); // NOI18N - - // 7a. create matching test registration for convenience (#73202) - fileChanges.add(fileChanges.addLookupRegistration("org.openide.loaders.DataLoader", packageName + '.' + namePrefix + "DataLoader", true)); // NOI18N //8. create layerfile actions subsection diff -r 54f623a0e6e1 -r 049d4cfc8b19 apisupport.project/src/org/netbeans/modules/apisupport/project/ui/wizard/loader/templateDataObjectInLayer.javx --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apisupport.project/src/org/netbeans/modules/apisupport/project/ui/wizard/loader/templateDataObjectInLayer.javx Fri Jun 06 17:19:40 2008 +0200 @@ -0,0 +1,36 @@ +<#assign licenseFirst = "/*"> +<#assign licensePrefix = " * "> +<#assign licenseLast = " */"> +<#include "../Licenses/license-${project.license}.txt"> + +package ${PACKAGENAME}; + +import java.io.IOException; +import org.openide.filesystems.FileObject; +import org.openide.loaders.DataNode; +import org.openide.loaders.DataObjectExistsException; +import org.openide.loaders.MultiDataObject; +import org.openide.loaders.MultiFileLoader; +import org.openide.nodes.CookieSet; +import org.openide.nodes.Node; +import org.openide.nodes.Children; +import org.openide.util.Lookup; +${EDITOR_SUPPORT_IMPORT} + +public class ${PREFIX}DataObject extends MultiDataObject { + + public ${PREFIX}DataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException { + super(pf, loader); +${EDITOR_SUPPORT_SNIPPET} + } + + @Override + protected Node createNodeDelegate() { + return new DataNode(this, Children.LEAF, getLookup()); + } + + @Override + public Lookup getLookup() { + return getCookieSet().getLookup(); + } +} diff -r 54f623a0e6e1 -r 049d4cfc8b19 openide.loaders/apichanges.xml --- a/openide.loaders/apichanges.xml Tue Jun 03 15:47:50 2008 -0700 +++ b/openide.loaders/apichanges.xml Fri Jun 06 17:19:40 2008 +0200 @@ -106,6 +106,24 @@ is the proper place. + + + DataObjects without DataLoaders + + + + + +

+ There is new method to register new DataObject types without + the need to write own DataLoader. Use + + DataLoaderPool.factory method. +

+
+ + +
Loaders are registered in layer files diff -r 54f623a0e6e1 -r 049d4cfc8b19 openide.loaders/manifest.mf --- a/openide.loaders/manifest.mf Tue Jun 03 15:47:50 2008 -0700 +++ b/openide.loaders/manifest.mf Fri Jun 06 17:19:40 2008 +0200 @@ -1,6 +1,6 @@ Manifest-Version: 1.0 Manifest-Version: 1.0 OpenIDE-Module: org.openide.loaders -OpenIDE-Module-Specification-Version: 7.0 +OpenIDE-Module-Specification-Version: 7.1 OpenIDE-Module-Localizing-Bundle: org/openide/loaders/Bundle.properties OpenIDE-Module-Recommends: org.netbeans.modules.templates.v1_0 AutoUpdate-Essential-Module: true diff -r 54f623a0e6e1 -r 049d4cfc8b19 openide.loaders/src/org/openide/loaders/DataLoaderPool.java --- a/openide.loaders/src/org/openide/loaders/DataLoaderPool.java Tue Jun 03 15:47:50 2008 -0700 +++ b/openide.loaders/src/org/openide/loaders/DataLoaderPool.java Fri Jun 06 17:19:40 2008 +0200 @@ -41,7 +41,10 @@ package org.openide.loaders; +import java.awt.Image; import java.io.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -476,7 +479,12 @@ implements java.io.Serializable { Enumeration en = allLoaders (fo); while (en.hasMoreElements ()) { DataObject.Factory l = en.nextElement (); - DataObject obj = l.findDataObject (fo, recognized); + DataObject obj; + if (l instanceof DataLoader) { + obj = l.findDataObject (fo, recognized); + } else { + obj = DataObjectPool.handleFindDataObject(l, fo, recognized); + } if (!recognized.isEmpty()) { for (FileObject f : recognized) { r.markRecognized(f); @@ -575,7 +583,42 @@ implements java.io.Serializable { } return null; } - + + /** Factory method to create default implementation of a factory for + * data objects. It takes the class of the DataObject and + * is ready to call its constructor. The constructor needs to take two + * arguments: FileObject and MultiDataLoader. It can throw IOException as + * is usual among DataObject constructors. + *

+ * You can also invoke this method from a layer by following definition: + *

+     * <file name="nameofyourfile.instance">
+     *   <attr name="instanceCreate" methodvalue="org.openide.loaders.DataLoaderPool.factory"/>
+     *   <attr name="dataObjectClass" stringvalue="org.your.pkg.YourDataObject"/>
+     *   <attr name="mimeType" stringvalue="yourmime/type"/>
+     *   <attr name="SystemFileSystem.localizingIcon" stringvalue="org/your/pkg/YourDataObject.png"/>
+     * </file>
+     * 
+ * @param clazz the class of the data object to create. Must have appropriate + * constructor. + * @param mimeType the mime type associated with the object, used for + * example to create the right actions for the object's node + * @param image icon to use by default for nodes representing data objects + * created with this factory + * @return factory to be registered in Loaders/mime/type/Factories + * in some module layer file + * @since 7.1 + */ + public static DataObject.Factory factory( + Class dataObjectClass, String mimeType, Image image + ) { + return new MimeFactory(dataObjectClass, mimeType, image, null); + } + static DataObject.Factory factory( + FileObject fo + ) throws ClassNotFoundException { + return MimeFactory.layer(fo); + } /** Lazy getter for system loaders. */ @@ -801,11 +844,7 @@ private static class InstanceLoader exte }; } } // end of InstanceLoader - - - - /** Loader for file objects not recognized by any other loader */ private static final class DefaultLoader extends MultiFileLoader { static final long serialVersionUID =-6761887227412396555L; diff -r 54f623a0e6e1 -r 049d4cfc8b19 openide.loaders/src/org/openide/loaders/DataNode.java --- a/openide.loaders/src/org/openide/loaders/DataNode.java Tue Jun 03 15:47:50 2008 -0700 +++ b/openide.loaders/src/org/openide/loaders/DataNode.java Fri Jun 06 17:19:40 2008 +0200 @@ -246,6 +246,11 @@ public class DataNode extends AbstractNo } return super.getHtmlDisplayName(); } + + private java.awt.Image getImageFromFactory(int type) { + MimeFactory fact = getLookup().lookup(MimeFactory.class); + return fact != null ? fact.getImage(type) : null; + } /** Get the displayed icon for this node. * A filesystem may {@link org.openide.filesystems.FileSystem#getStatus specially alter} this. @@ -254,8 +259,12 @@ public class DataNode extends AbstractNo * @param type the icon type from {@link java.beans.BeanInfo} * @return the desired icon */ + @Override public java.awt.Image getIcon (int type) { - java.awt.Image img = super.getIcon (type); + java.awt.Image img = getImageFromFactory(type); + if (img == null) { + img = super.getIcon (type); + } try { img = obj.getPrimaryFile ().getFileSystem ().getStatus ().annotateIcon (img, type, new LazyFilesSet()); @@ -273,8 +282,12 @@ public class DataNode extends AbstractNo * @param type the icon type from {@link java.beans.BeanInfo} * @return the desired icon */ + @Override public java.awt.Image getOpenedIcon (int type) { - java.awt.Image img = super.getOpenedIcon(type); + java.awt.Image img = getImageFromFactory(type); + if (img == null) { + img = super.getOpenedIcon(type); + } try { img = obj.getPrimaryFile ().getFileSystem ().getStatus ().annotateIcon (img, type, new LazyFilesSet()); @@ -351,6 +364,11 @@ public class DataNode extends AbstractNo if (systemActions != null) { return systemActions; + } + + MimeFactory mime = getLookup().lookup(MimeFactory.class); + if (mime != null) { + return mime.getActions(); } return obj.getLoader ().getSwingActions (); diff -r 54f623a0e6e1 -r 049d4cfc8b19 openide.loaders/src/org/openide/loaders/DataObjectPool.java --- a/openide.loaders/src/org/openide/loaders/DataObjectPool.java Tue Jun 03 15:47:50 2008 -0700 +++ b/openide.loaders/src/org/openide/loaders/DataObjectPool.java Fri Jun 06 17:19:40 2008 +0200 @@ -156,6 +156,26 @@ implements ChangeListener { getPOOL ().enterRecognition(fo); ret = loader.handleFindDataObject (fo, rec); + } finally { + exitAllowConstructor (prev); + } + + return ret; + } + + /** Calls into one loader. Setups security condition to allow DataObject ocnstructor + * to succeed. + */ + public static DataObject handleFindDataObject (DataObject.Factory factory, FileObject fo, Set rec) + throws java.io.IOException { + DataObject ret; + + Collection prev = enterAllowContructor(); + try { + // make sure this thread is allowed to recognize + getPOOL ().enterRecognition(fo); + + ret = factory.findDataObject (fo, rec); } finally { exitAllowConstructor (prev); } diff -r 54f623a0e6e1 -r 049d4cfc8b19 openide.loaders/src/org/openide/loaders/MimeFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.loaders/src/org/openide/loaders/MimeFactory.java Fri Jun 06 17:19:40 2008 +0200 @@ -0,0 +1,156 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 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]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * 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. + */ +package org.openide.loaders; + +import java.awt.Image; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.Set; +import javax.swing.Action; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileStateInvalidException; +import org.openide.filesystems.Repository; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; +import org.openide.util.Utilities; + +/** Default DataObject.Factory implementation. + * + * @author Jaroslav Tulach + * @param type of DataObject to create + */ +class MimeFactory implements DataObject.Factory { + final Class clazz; + final Constructor factory; + final String mimeType; + Image img; + final FileObject fo; + + public MimeFactory(Class clazz, String mimeType, Image img, FileObject fo) { + super(); + this.clazz = clazz; + this.mimeType = mimeType; + this.img = img; + try { + this.factory = clazz.getConstructor(FileObject.class, MultiFileLoader.class); + this.factory.setAccessible(true); + } catch (NoSuchMethodException ex) { + throw (IllegalStateException) new IllegalStateException(ex.getMessage()).initCause(ex); + } + this.fo = fo; + } + + public static MimeFactory layer(FileObject fo) throws ClassNotFoundException { + String className = (String) fo.getAttribute("dataObjectClass"); // NOI18N + if (className == null) { + throw new IllegalStateException("No attribute dataObjectClass for " + fo); + } + String mimeType = (String)fo.getAttribute("mimeType"); // NOI18N + + ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class); + if (l == null) { + l = Thread.currentThread().getContextClassLoader(); + } + if (l == null) { + l = MimeFactory.class.getClassLoader(); + } + Class clazz = l.loadClass(className).asSubclass(DataObject.class); + return new MimeFactory(clazz, mimeType, null, fo); + } + + public DataObject findDataObject(FileObject fo, Set recognized) throws IOException { + DataObject obj = null; + Exception e = null; + try { + obj = factory.newInstance(fo, DataLoaderPool.getDefaultFileLoader()); + } catch (InstantiationException ex) { + e = ex; + } catch (IllegalAccessException ex) { + e = ex; + } catch (IllegalArgumentException ex) { + e = ex; + } catch (InvocationTargetException ex) { + if (ex.getTargetException() instanceof IOException) { + throw (IOException)ex.getTargetException(); + } + e = ex; + } + if (obj == null) { + throw (IOException) new IOException(e.getMessage()).initCause(e); + } + if (obj instanceof MultiDataObject) { + MultiDataObject mdo = (MultiDataObject) obj; + mdo.getCookieSet().assign(DataObject.Factory.class, this); + } + return obj; + } + + final Image getImage(int type) { + if (img == null && fo != null) { + img = Utilities.loadImage("org/openide/loaders/empty.gif", true); // NOI18N + try { + img = fo.getFileSystem().getStatus().annotateIcon(img, type, Collections.singleton(fo)); + } catch (FileStateInvalidException ex) { + Exceptions.printStackTrace(ex); + } + } + return img; + } + + final Action[] getActions() { + FileObject actions = Repository.getDefault().getDefaultFileSystem().findResource( + "Loaders/" + mimeType + "/Actions" + ); + if (actions != null) { + DataFolder folder = DataFolder.findFolder(actions); + try { + return (Action[]) new DataLdrActions(folder, null).instanceCreate(); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } catch (ClassNotFoundException ex) { + Exceptions.printStackTrace(ex); + } + } + return DataLoaderPool.getDefaultFileLoader().getSwingActions(); + } +} diff -r 54f623a0e6e1 -r 049d4cfc8b19 openide.loaders/test/unit/src/org/openide/loaders/DataLoaderInLayerTest.java --- a/openide.loaders/test/unit/src/org/openide/loaders/DataLoaderInLayerTest.java Tue Jun 03 15:47:50 2008 -0700 +++ b/openide.loaders/test/unit/src/org/openide/loaders/DataLoaderInLayerTest.java Fri Jun 06 17:19:40 2008 +0200 @@ -42,12 +42,22 @@ package org.openide.loaders; package org.openide.loaders; +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.image.ImageObserver; import org.openide.filesystems.*; import java.io.IOException; import java.util.*; import org.netbeans.junit.*; import java.beans.PropertyChangeListener; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.net.URL; +import javax.swing.Action; import junit.framework.Test; +import org.openide.actions.EditAction; +import org.openide.nodes.Node; +import org.openide.util.Utilities; /** Check what can be done when registering loaders in layer. * @author Jaroslav Tulach @@ -93,6 +103,20 @@ public class DataLoaderInLayerTest exten } } } + private static void addRemove(String mime, F factory, boolean add) throws IOException { + String res = "Loaders/" + mime + "/Factories/" + factory.getClass().getSimpleName().replace('.', '-') + ".instance"; + FileObject root = Repository.getDefault().getDefaultFileSystem().getRoot(); + if (add) { + FileObject fo = FileUtil.createData(root, res); + fo.setAttribute("instanceCreate", factory); + assertSame("No serialization, just memory fs is used", factory, fo.getAttribute("instanceCreate")); + } else { + FileObject fo = root.getFileObject(res); + if (fo != null) { + fo.delete(); + } + } + } public void testSimpleGetChildren() throws Exception { DataLoader l = DataLoader.getLoader(SimpleUniFileLoader.class); @@ -122,6 +146,92 @@ public class DataLoaderInLayerTest exten assertEquals(SimpleDataObject.class, dob.getClass()); } finally { addRemove("text/plain", SimpleFactory.class, false); + } + } + + public void testFactoryInstanceRegistrationWorksAsWell() throws Exception { + URL u = DataLoaderInLayerTest.class.getResource("/org/openide/loaders/saveAll.gif"); + Image img = Toolkit.getDefaultToolkit().createImage(u); + + DataObject.Factory f = DataLoaderPool.factory(SimpleDataObject.class, "text/simplefactory", img); + + addRemove("text/plain", f, true); + try { + FileSystem lfs = createFS("folderF/file.simple"); + FileObject fo = lfs.findResource("folderF"); + DataFolder df = DataFolder.findFolder(fo); + DataObject[] arr = df.getChildren(); + assertEquals("One object", 1, arr.length); + DataObject dob = arr[0]; + assertEquals(SimpleDataObject.class, dob.getClass()); + + FileObject root = Repository.getDefault().getDefaultFileSystem().getRoot(); + FileObject edit = FileUtil.createData(root, "/Loaders/text/simplefactory/Actions/org-openide-actions-EditAction.instance"); + + Node node = dob.getNodeDelegate(); + Action[] actions = node.getActions(true); + assertEquals("One action is present: " + Arrays.asList(actions), 1, actions.length); + assertEquals("It is the edit one", EditAction.class, actions[0].getClass()); + + assertSame("Icon is propagated for open", img, node.getOpenedIcon(0)); + assertSame("Icon is propagated", img, node.getIcon(0)); + + Reference ref = new WeakReference(df); + df = null; + assertGC("Folder can go away", ref); + + df = DataFolder.findFolder(fo); + arr = df.getChildren(); + assertEquals("One object", 1, arr.length); + assertEquals("Object is the same", dob, arr[0]); + } finally { + addRemove("text/plain", f, false); + } + } + + public void testFactoryInstanceRegistrationWorksAsWellNowFromLayer() throws Exception { + URL u = DataLoaderInLayerTest.class.getResource("/org/openide/loaders/saveAll.gif"); + FileObject root = Repository.getDefault().getDefaultFileSystem().getRoot(); + FileObject instance = FileUtil.createData(root, "TestLoaders/text/L.instance"); + instance.setAttribute("dataObjectClass", SimpleDataObject.class.getName()); + instance.setAttribute("mimeType", "text/simplefactory"); + instance.setAttribute("SystemFileSystem.icon", u); + + + Image img = Utilities.loadImage("org/openide/loaders/saveAll.gif"); + + DataObject.Factory f = DataLoaderPool.factory(instance); + + addRemove("text/plain", f, true); + try { + FileSystem lfs = createFS("folderQ/file.simple"); + FileObject fo = lfs.findResource("folderQ"); + DataFolder df = DataFolder.findFolder(fo); + DataObject[] arr = df.getChildren(); + assertEquals("One object", 1, arr.length); + DataObject dob = arr[0]; + assertEquals(SimpleDataObject.class, dob.getClass()); + + FileObject edit = FileUtil.createData(root, "/Loaders/text/simplefactory/Actions/org-openide-actions-EditAction.instance"); + + Node node = dob.getNodeDelegate(); + Action[] actions = node.getActions(true); + assertEquals("One action is present: " + Arrays.asList(actions), 1, actions.length); + assertEquals("It is the edit one", EditAction.class, actions[0].getClass()); + + assertImage("Icon is propagated for open", img, node.getOpenedIcon(0)); + assertImage("Icon is propagated", img, node.getIcon(0)); + + Reference ref = new WeakReference(df); + df = null; + assertGC("Folder can go away", ref); + + df = DataFolder.findFolder(fo); + arr = df.getChildren(); + assertEquals("One object", 1, arr.length); + assertEquals("Object is the same", dob, arr[0]); + } finally { + addRemove("text/plain", f, false); } } @@ -311,5 +421,25 @@ public class DataLoaderInLayerTest exten supp.remove (l); } } - + + private static void assertImage(String msg, Image img1, Image img2) { + ImageObserver obs = new ImageObserver() { + public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { + fail("Already updated, hopefully"); + return true; + } + }; + + int h, w; + assertEquals("Width: " + msg, w = img1.getWidth(obs), img2.getWidth(obs)); + assertEquals("Height: " + msg, h = img1.getHeight(obs), img2.getHeight(obs)); + + + for (int i = 0; i < w; i++) { + for (int j = 0; j < h; j++) { + //assertEquals("Pixel " + i + ", " + j + " same: " + msg, img1.get) + } + } + + } }