diff -r 3f9f26a71a28 openide.loaders/src/org/openide/loaders/DataLoaderPool.java --- a/openide.loaders/src/org/openide/loaders/DataLoaderPool.java Mon Jun 02 16:52:06 2008 -0700 +++ b/openide.loaders/src/org/openide/loaders/DataLoaderPool.java Tue Jun 03 20:58:08 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,40 @@ 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 + * @return factory to be registered in Loaders/mime/type/Factories + * in 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 +842,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 3f9f26a71a28 openide.loaders/src/org/openide/loaders/DataNode.java --- a/openide.loaders/src/org/openide/loaders/DataNode.java Mon Jun 02 16:52:06 2008 -0700 +++ b/openide.loaders/src/org/openide/loaders/DataNode.java Tue Jun 03 20:58:08 2008 +0200 @@ -246,6 +246,11 @@ public class DataNode extends AbstractNo } return super.getHtmlDisplayName(); } + + private java.awt.Image getImageFromFactory() { + MimeFactory fact = getLookup().lookup(MimeFactory.class); + return fact != null ? fact.getImage() : 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(); + 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(); + 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 3f9f26a71a28 openide.loaders/src/org/openide/loaders/DataObjectPool.java --- a/openide.loaders/src/org/openide/loaders/DataObjectPool.java Mon Jun 02 16:52:06 2008 -0700 +++ b/openide.loaders/src/org/openide/loaders/DataObjectPool.java Tue Jun 03 20:58:08 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 3f9f26a71a28 openide.loaders/test/unit/src/org/openide/loaders/DataLoaderInLayerTest.java --- a/openide.loaders/test/unit/src/org/openide/loaders/DataLoaderInLayerTest.java Mon Jun 02 16:52:06 2008 -0700 +++ b/openide.loaders/test/unit/src/org/openide/loaders/DataLoaderInLayerTest.java Tue Jun 03 20:58:08 2008 +0200 @@ -42,12 +42,18 @@ package org.openide.loaders; package org.openide.loaders; +import java.awt.Image; +import java.awt.Toolkit; import org.openide.filesystems.*; import java.io.IOException; import java.util.*; import org.netbeans.junit.*; import java.beans.PropertyChangeListener; +import java.net.URL; +import javax.swing.Action; import junit.framework.Test; +import org.openide.actions.EditAction; +import org.openide.nodes.Node; /** Check what can be done when registering loaders in layer. * @author Jaroslav Tulach @@ -93,6 +99,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 +142,37 @@ 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)); + } finally { + addRemove("text/plain", f, false); } }