alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.openide.loaders;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.io.IOException;
import java.util.*;

import org.openide.*;
import org.openide.filesystems.*;
import org.openide.cookies.InstanceCookie;
import org.openide.util.Task;
import org.openide.util.TaskListener;
import org.openide.util.RequestProcessor;

/** Support class for creation of an object from the content
* of a {@link DataObject.Container}. It implements
* {@link InstanceCookie}, so it
* can be used as a cookie for a node or data object.
* 

* When created on a container and started by invoking run method, * it scans its content (in a separate * thread) and creates a list of instances from which the new * instance of this object should be composed. The object * automatically listens to changes of components * in the container, and if some change occurs, it allows the subclass to create * a new object. *

* *

Subclasses shall override the following methods:

* *
    *
  1. {@link #createInstance(InstanceCookie[])} (required): this method is * called whenever the content has been changed. Its implementation * shall build up the data structures and perform the actions required * by this implementation.
  2. *
  3. The filter methods {@link #acceptDataObject(DataObject)}, {@link * #acceptCookie(InstanceCookie)}, * {@link #acceptFolder(DataFolder)} and * {@link #acceptContainer(DataObject.Container)} (optional): the standard * way is to override one or several of the latter methods. Overriding * {@link #acceptDataObject(DataObject)} more deeply * modifies the default behavior, because the default implementation of * {@link #acceptDataObject(DataObject)} calls the * other 3 filter methods. See the method documentation for details.
  4. *
  5. The {@link InstanceCookie} methods * {@link #instanceClass()} (optional but recommended) * to inform about the class implemented by the return value of * {@link #instanceCreate()}.
  6. *
  7. Advanced subclasses may need to override {@link #postCreationTask} * and/or {@link #instanceForCookie}, but it is not common to need these.
  8. *
* * @author Jaroslav Tulach */ public abstract class FolderInstance extends Task implements InstanceCookie { /* -------------------------------------------------------------------- */ /* -- Constants ------------------------------------------------------- */ /* -------------------------------------------------------------------- */ /** a queue to run requests in */ private static final RequestProcessor PROCESSOR = new RequestProcessor ( "Folder Instance Processor" // NOI18N ); /** static variable to hold current value for callbacks to tasks * Also used to synchronize access to map field on. */ private static final ThreadLocal CURRENT = new ThreadLocal (); /** The last finished folder instance in this thread. Works together * with CURRENT, because sometimes more than one FolderInstance.instanceCreate * can be called on the same thread. */ private static final ThreadLocal LAST_CURRENT = new ThreadLocal (); /* -------------------------------------------------------------------- */ /* -- Instance attributes --------------------------------------------- */ /* -------------------------------------------------------------------- */ /** Folder to work with. Non null only if a constructor with DataFolder * is used to construct this object. */ protected DataFolder folder; /** container to work with */ private DataObject.Container container; /** map of primary file to their cookies (FileObject, HoldInstance) */ private HashMap map = new HashMap (17); /** Array of tasks that we have to check before we are ok. These are the tasks * associated with children of the current folder. */ private Task[] waitFor; /** object for this cookie. Either the right instance of object or * an instance of IOException or ClassNotFoundException. By default * it is assigned to some private object in this class to signal that * it is uninitialized. */ private Object object = CURRENT; /** Listener and runner for this object */ private Listener listener; /** Error manager for this instance */ private ErrorManager err; /** Task that computes the children list of the folder */ private Task recognizingTask; /** A task that gets objects from InstanceCookie's and calls createInstance. * Started immediately after the recognizingTask is finished. */ private Task creationTask; /* -------------------------------------------------------------------- */ /* -- Constructor(s) -------------------------------------------------- */ /* -------------------------------------------------------------------- */ /** Create new folder instance. * @param df data folder to create instances from */ public FolderInstance (DataFolder df) { this ((DataObject.Container)df); } /** A new object that listens on changes in a container. * @param container the object to associate with * @since 1.11 */ public FolderInstance (DataObject.Container container) { this (container, null); } /** Constructs everything. * @param container container * @param logName the name to use for logging purposes */ private FolderInstance (DataObject.Container container, String logName) { if (container instanceof DataFolder) { folder = (DataFolder)container; if (logName == null) { logName = folder.getPrimaryFile().getPath().replace('/','.'); } container = FolderList.find (folder.getPrimaryFile (), true); } listener = new Listener (); if (logName == null) { logName = "org.openide.loaders.FolderInstance"; // NOI18N } else { logName = "org.openide.loaders.FolderInstance" + '.' + logName; // NOI18N } err = ErrorManager.getDefault ().getInstance (logName); this.container = container; container.addPropertyChangeListener ( org.openide.util.WeakListeners.propertyChange (listener, container) ); if (err.isLoggable (err.INFORMATIONAL)) { err.log ("new " + this); // NOI18N } } /* -------------------------------------------------------------------- */ /* -- Implementation of org.openide.Cookies.InstanceCookie ------------ */ /* -------------------------------------------------------------------- */ /** The name of the class that we create. * @return the name */ public String instanceName () { try { return instanceClass ().getName (); } catch (java.io.IOException ex) { return "java.lang.Object"; // NOI18N } catch (ClassNotFoundException ex) { return "java.lang.Object"; // NOI18N } } /** Returns the root class of all objects. * Supposed to be overriden in subclasses. * * @return Object.class * @exception IOException an I/O error occured * @exception ClassNotFoundException the class has not been found */ public Class instanceClass () throws java.io.IOException, ClassNotFoundException { Object object = this.object; if (object != null) { if (object instanceof java.io.IOException) { throw (java.io.IOException)object; } if (object instanceof ClassNotFoundException) { throw (ClassNotFoundException)object; } return object.getClass (); } return Object.class; } /** Creates instance. * @return an object to work with * @exception IOException an I/O error occured * @exception ClassNotFoundException the class has not been found */ public Object instanceCreate () throws java.io.IOException, ClassNotFoundException { Object object = CURRENT.get (); if (object == null || LAST_CURRENT.get () != this) { waitFinished (); object = FolderInstance.this.object; } // err.log ("instanceCreate: " + object); if (object instanceof java.io.IOException) { throw (java.io.IOException)object; } if (object instanceof ClassNotFoundException) { throw (ClassNotFoundException)object; } if (object == CURRENT) { // uninitialized throw new IOException ("Cyclic reference. Somebody is trying to get value from FolderInstance (" + getClass ().getName () + ") from the same thread that is processing the instance"); // NOI18N } return object; } /* -------------------------------------------------------------------- */ /* -- Wait ------------------------------------------------------------ */ /* -------------------------------------------------------------------- */ /** Wait for instance initialization to finish. */ public final void instanceFinished () { waitFinished (); } /* -------------------------------------------------------------------- */ /* -- Extends org.openide.util.Task ----------------------------------- */ /* -------------------------------------------------------------------- */ /** Overrides the instance finished to deal with * internal state correctly. */ public void waitFinished () { for (;;) { waitProcessingFinished (container); Task originalRecognizing = checkRecognizingStarted (); originalRecognizing.waitFinished (); Task t = creationTask; if (t != null) { t.waitFinished (); } Task[] toWait = waitFor; if (toWait != null) { for (int i = 0; i < toWait.length; i++) { toWait[i].waitFinished (); } } // loop if there was yet another task started to compute the // children list if (originalRecognizing == checkRecognizingStarted ()) { break; } // // otherwise go on an try it once more // } } /** Synchronously starts the creation of the instance. */ public void run () { recreate (); instanceFinished (); } /* -------------------------------------------------------------------- */ /* -- Filter methods (protected, may be overridden by sub-classes) ---- */ /* -------------------------------------------------------------------- */ /** Allows subclasses to decide whether they want to work with the specified * DataObject or not. * *

The default implementation roughly performs the following steps:

* *
    *
  1. if dob has an InstanceCookie * {@link #acceptCookie(InstanceCookie)} is called on that cookie
  2. *
  3. if dob has a DataFolder cookie, * {@link #acceptFolder(DataFolder)} is called on that folder
  4. *
  5. if dob has a DataObject.Container cookie, * {@link #acceptContainer(DataObject.Container)} is called on that * container
  6. *
* *

The first of the aforementioned steps which returns a non-null * cookie and does not throw an exception determines the return value. If * none of the steps succeeds, null is returned.

* * @param dob a DataObject to test * @return the cookie for the DataObject or null * if it should not be used */ protected InstanceCookie acceptDataObject(DataObject dob) { int acceptType = -1; InstanceCookie cookie; //Order of checking reversed first check cookie and then folder // test if we accept the instance cookie = (InstanceCookie)dob.getCookie (InstanceCookie.class); try { cookie = cookie == null ? null : acceptCookie (cookie); acceptType = 1; } catch (IOException ex) { // an error during a call to acceptCookie ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); cookie = null; } catch (ClassNotFoundException ex) { // an error during a call to acceptCookie ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); cookie = null; } if (cookie == null) { DataFolder folder = (DataFolder) dob.getCookie (DataFolder.class); if (folder != null) { HoldInstance previous = (HoldInstance)map.get (folder.getPrimaryFile ()); if (previous != null && previous.cookie != null) { // the old cookie will be returned if the folder is already registered cookie = previous; acceptType = 2; } else { cookie = acceptFolder (folder); acceptType = 3; } } } if (cookie == null) { // try also the container DataObject.Container c = (DataObject.Container)dob.getCookie (DataObject.Container.class); if (c != null) { cookie = acceptContainer (c); acceptType = 4; } } if (err.isLoggable (ErrorManager.INFORMATIONAL)) { err.log (ErrorManager.INFORMATIONAL, "acceptDataObject: " + dob + " cookie: " + cookie + " acceptType: " + acceptType); // NOI18N } return cookie; } /** Allows subclasses to decide whether they want to work with * the specified InstanceCookie or not. *

The default implementation simply * returns the same cookie, but subclasses may * decide to return null or a different cookie. *

*

Compare {@link #acceptDataObject(DataObject)} to learn when this method * is called.

* * @param cookie the instance cookie to test * @return the cookie to use or null if this cookie should not * be used * @exception IOException if an I/O error occurred calling a cookie method * @exception ClassNotFoundException if a class is not found in a call to a cookie method */ protected InstanceCookie acceptCookie (InstanceCookie cookie) throws java.io.IOException, ClassNotFoundException { return cookie; } /** Allows subclasses to decide how they want to work with a * provided folder. * *

The default implementation simply calls {@link #acceptContainer(DataObject.Container)}.

* *

A common override of this method is to return a new * FolderInstance based on the subfolder, permitting * recursion.

* *

Compare {@link #acceptDataObject(DataObject)} to learn when this method * is called.

* * @param df data folder to create cookie for * @return the cookie for this folder or null if this folder should not * be used */ protected InstanceCookie acceptFolder (DataFolder df) { return acceptContainer (df); } /** Allows subclasses to decide how they want to work with an object * that implements a DataObject.Container. * *

By default this returns null to indicated that subfolders * (as well as {@link DataShadow}s, etc.) should be ignored.

* *

A common override of this method is to return a new * FolderInstance based on the subfolder, permitting * recursion.

* *

Compare {@link #acceptDataObject(DataObject)} to learn when this method * is called.

* * @param container the container to accept or not * @return cookie for this container or null if this object should * be ignored * * @since 1.11 */ protected InstanceCookie acceptContainer (DataObject.Container container) { return null; } /* ----------------------------------------------------------------------------- */ /* -- Instances creation method (protected, must be overridden by sub-classes) - */ /* ----------------------------------------------------------------------------- */ /** Notifies subclasses that the set of cookies for this folder * has changed. * A new object representing the folder should * be created (or the old one updated). * Called both upon initialization of the class, and change of its cookies. * *

It may be poor style for this method to have side-effects. A * common way to use FolderInstance is to have this * method set some global state which is then used as the resulting * instance. Better is to treat the FolderInstance as * pure SPI and assign it to a variable of type * InstanceCookie. Then use the {@link * #instanceCreate} method to get the final result. However in some * cases there is a singleton live object which must be updated * in-place, and it only makes sense to do so here (in which case * the InstanceCookie methods are unused).

* * @param cookies updated array of instance cookies for the folder * @return object to represent these cookies * * @exception IOException an I/O error occured * @exception ClassNotFoundException a class has not been found */ protected abstract Object createInstance (InstanceCookie[] cookies) throws java.io.IOException, ClassNotFoundException; /* ----------------------------------------------------------------------------- */ /* -- Instances creation method (protected, may be overridden by sub-classes) - */ /* ----------------------------------------------------------------------------- */ /** Method that is called when a the folder instance really wants to * create an object from provided cookie. * It allows subclasses to overwrite the default behaviour (which is * to call {@link InstanceCookie#instanceCreate}). * * @param obj the data object that is the source of the cookie * @param cookie the instance cookie to read the instance from * @exception IOException when there I/O error * @exception ClassNotFoundException if the class cannot be found */ protected Object instanceForCookie (DataObject obj, InstanceCookie cookie) throws IOException, ClassNotFoundException { return cookie.instanceCreate (); } /* ----------------------------------------------------------------------------- */ /* -- Recreation --------------------------------------------------------------- */ /* ----------------------------------------------------------------------------- */ /** Starts recreation of the instance in special thread. */ public synchronized void recreate () { // this method should be synchronized so the recognizingTask is created // together with notification that we are running. // Fix of #16136 => sometimes it happened that the thread started in // the recognizer task was finished sooner then notifyRunning called. // In such case notifyFinished could be called before notifyRunning // and everything was completely broken err.log ("recreate"); recognizingTask = computeChildrenList (container, listener); notifyRunning (); } /** Checks whether recreation of this instance is running already * and in that case does nothing, otherwise calls * {@link #recreate() recreate} method. * This prevents from redundant recreation tasks of this instance caused by * first creation of underlying items which are also of {@link org.openide.util.Task Task} * type (e.g. sub-FolderInstances, sub-FolderLookups etc.). */ final void checkRecreate() { if(isFinished()) { recreate(); } } /** Checks whether recreation has already started and starts it if if was * was not yet started during the live of this FolderInstance. * @return the latest started task for children computation */ private final Task checkRecognizingStarted () { if(recognizingTask == null) { recreate(); } return recognizingTask; } /* ----------------------------------------------------------------------------- */ /* -- Static helper methods (abstract away the differences between different --- */ /* ------------------------- DataObject.Container types) ----------------------- */ /* ----------------------------------------------------------------------------- */ /** Waits until the task to compute the children of the currents folder is * finished. This methods provides a unified interface which allows to * treat FolderLists and general DataObject.Containers * is a uniform way. */ private static void waitProcessingFinished ( DataObject.Container c ) { if (c instanceof FolderList) { ((FolderList)c).waitProcessingFinished (); } } /** Starts and returns the task to compute the children of the current * folder. This methods provides a unified interface which allows to * treat FolderLists and general DataObject.Containers * is a uniform way. * *

The task returned uses the {@link #listener} to process the children.

*/ private static Task computeChildrenList ( final DataObject.Container container, final FolderListListener listener ) { if (container instanceof FolderList) { FolderList list = (FolderList)container; return list.computeChildrenList (listener); } // otherwise we have to simulate the listener by container methods // itself return PROCESSOR.post (new Runnable () { public void run () { DataObject[] arr = container.getChildren (); ArrayList list = new ArrayList (arr.length); for (int i = 0; i < arr.length; i++) { listener.process (arr[i], list); } listener.finished (list); } }); } /* ----------------------------------------------------------------------------- */ /* -- Processing --------------------------------------------------------------- */ /* ----------------------------------------------------------------------------- */ /** A method that starts creationTask, the task which really * creates the instances from given objects. The task is started by a * call to {@link #postCreationTask(Runnable)}. * * @param arr collection of DataObjects */ final void processObjects (final Collection arr) { creationTask = postCreationTask (new Runnable () { public void run () { defaultProcessObjects (arr); } }); } /** Default processing of objects. * @param arr array of objects to process */ private final void defaultProcessObjects (Collection arr) { err.log ("defaultProcessObjects"); HashSet toRemove; ArrayList cookies = new ArrayList (); // synchronized for safe access to map field synchronized (CURRENT) { toRemove = new HashSet (map.keySet ()); } Iterator dataObjects = arr.iterator (); while (dataObjects.hasNext ()) { DataObject obj = (DataObject)dataObjects.next (); if (! obj.isValid()) { // #12960: skip over it, probably invalidated while we were // waiting for this task to be run... continue; } // testing InstanceCookie cookie = acceptDataObject(obj); if (cookie != null) { // cookie accepted FileObject fo = obj.getPrimaryFile (); HoldInstance prevCookie = null; if (toRemove.remove (fo)) { // if the fo is in the map than try to find its cookie prevCookie = (HoldInstance)map.get (fo); if (prevCookie != null && (prevCookie.cookie == null || !prevCookie.cookie.equals (cookie))) { prevCookie = null; } } if (prevCookie == null) { // such cookie is not there yet HoldInstance hold; if (cookie instanceof HoldInstance) { hold = (HoldInstance)cookie; } else { hold = new HoldInstance(obj, cookie); } // synchronized for safe access to map field synchronized (CURRENT) { map.put (fo, hold); } // register for changes of PROP_COOKIE property obj.addPropertyChangeListener ( org.openide.util.WeakListeners.propertyChange (listener, obj) ); cookies.add (hold); } else { // old cookie, already there => only add it to the list of cookies cookies.add (prevCookie); } } else { // empty instance placeholder synchronized (CURRENT) { FileObject fo = obj.getPrimaryFile (); toRemove.remove (fo); HoldInstance hold = (HoldInstance)map.get (fo); if (hold != null && hold.cookie == null) { // already registered do not do any changes continue; } // not yet registered, add new hold = new HoldInstance (obj, null); map.put (fo, hold); } // register for changes of PROP_COOKIE property obj.addPropertyChangeListener ( org.openide.util.WeakListeners.propertyChange (listener, obj) ); } } // synchronized for safe access to map field synchronized (CURRENT) { // now remove the cookies that are no longer in the folder map.keySet ().removeAll (toRemove); } // create the list of cookies HoldInstance[] all = new HoldInstance[cookies.size ()]; cookies.toArray (all); updateWaitFor (all); Object result = null; try { result = createInstance (all); } catch (IOException ex) { result = ex; } catch (ClassNotFoundException ex) { result = ex; } finally { if (err.isLoggable (err.INFORMATIONAL)) { err.log ("notifying finished"); // NOI18N for (int log = 0; log < all.length; log++) { err.log (" #" + log + ": " + all[log]); // NOI18N } } object = result; Object prevResult = CURRENT.get (); CURRENT.set (result); Object prevLast = LAST_CURRENT.get (); LAST_CURRENT.set (this); try { notifyFinished (); } finally { CURRENT.set (prevResult); LAST_CURRENT.set (prevLast); } } } /** Recomputes the list of tasks we should wait for (i.e. the tasks associated * with the children of the folder). */ private void updateWaitFor (HoldInstance[] arr) { ArrayList out = new ArrayList (arr.length); for (int i = 0; i < arr.length; i++) { Task t = arr[i].getTask (); if (t != null) { out.add (t); } } waitFor = (Task[])out.toArray (new Task[out.size ()]); } /* ----------------------------------------------------------------------------- */ /* -- Processing: Start the creation task (protected, may be overridden) ------- */ /* ----------------------------------------------------------------------------- */ /** Invokes the creation of objects in a "safe" thread. This method is * for expert subclasses that want to control the thread that the * instance is created in. * *

The default implementation invokes the creation logic in the * request processor in non-blocking mode (no other tasks will * block on this).

* * @param run runnable to run * @return task to control the execution of the runnable or null if * the runnable is run immediatelly * @since 1.5 */ protected Task postCreationTask (Runnable run) { return PROCESSOR.post (run); } /* ----------------------------------------------------------------------------- */ /* -- Getters ------------------------------------------------------------------ */ /* ----------------------------------------------------------------------------- */ /** Access to error manager for FolderLookup. */ final ErrorManager err () { return err; } public String toString () { return getClass ().getName () + "@" + Integer.toHexString (System.identityHashCode (this)) + "(" + this.container + ")"; // NOI18N } /* -------------------------------------------------------------------- */ /* -- Inner class Listener -------------------------------------------- */ /* -------------------------------------------------------------------- */ /** Listener on change of folder's children and a starter for the task. * *

Each instance of {@link FolderInstance} has one instance of this class * associated with it. The latter serves for three purposes:

* *
    *
  1. to listen for property changes of the {@link DataObject.Container} * this {@link FolderInstance} was created for (by implementing * {@link java.beans.PropertyChangeListener})
  2. *
  3. to listen for changes of the cookies of the children of this folder
  4. *
  5. to process the results of the computation of a child list * (by implementing {@link FolderListListener#finished(java.util.List)}) *
  6. *
*/ private class Listener implements PropertyChangeListener, FolderListListener { Listener() {} /** Recreates the {@link FolderInstance} if the children list of * its container was changed. * *

Additionally ...

*/ public void propertyChange (PropertyChangeEvent ev) { Object s = ev.getSource (); if (s == container) { if (DataObject.Container.PROP_CHILDREN.equals(ev.getPropertyName ())) { err.log ("PROP_CHILDREN"); recreate(); } return; } if (DataObject.PROP_NAME.equals(ev.getPropertyName())) { if (s instanceof DataObject) { err.log("PROP_NAME"); recreate(); } } // change of cookie in one of children of the container if (DataObject.PROP_COOKIE.equals(ev.getPropertyName ())) { if (s instanceof DataObject) { DataObject source = (DataObject)s; InstanceCookie ic = acceptDataObject (source); HoldInstance hi; FileObject fo = source.getPrimaryFile(); synchronized (CURRENT) { hi = (HoldInstance)map.get(fo); } if (hi != null) { /* Recreate if the new instance cookie is null or differs * from the previous one. * When the default implementation of acceptDataObject is * used ic == hi is the case if source is a folder. * [XXX] Why not: * if ((ic == null && hi.cookie != null) || (ic != hi && !ic.equals (hi.cookie))) { */ if (ic == null || (ic != hi && !ic.equals (hi.cookie))) { hi = new HoldInstance(source, ic); // synchronized for safe access to map field synchronized (CURRENT) { map.put (fo, hi); } recreate (); } } } } } /** Callback for object processing after all children are computed. * This implementation starts a new task for the creation of the * child objects. * @param arr list of DataObjects */ public void finished(java.util.List arr) { processObjects (arr); } /** Default implementation without filtering. * @param obj the object recognized * @param arr array where the implementation should add the * object */ public void process(DataObject obj, java.util.List arr) { arr.add (obj); } } /* -------------------------------------------------------------------- */ /* -- Inner class HoldInstance ---------------------------------------- */ /* -------------------------------------------------------------------- */ /** A instance cookie that holds the result of first * invocation of the provided cookie. * */ private class HoldInstance extends Object implements InstanceCookie.Of, TaskListener { /** the data object -> source of this instance */ private final DataObject source; /** the cookie to delegate to */ protected final InstanceCookie cookie; public HoldInstance (DataObject source, InstanceCookie cookie) { this.cookie = cookie; this.source = source; if (cookie instanceof Task) { // for example FolderInstance ;-) attach itself for changes // in the cookie Task t = (Task)cookie; t.addTaskListener ( (TaskListener)org.openide.util.WeakListeners.create (TaskListener.class, this, t) ); } } /** Full name of the data folder's primary file separated by dots. * @return the name */ public String instanceName () { return cookie.instanceName (); } /** Query to find out if the object created by this cookie is * instance of given type. The same code as: *
         *   Class actualClass = instanceClass ();
         *   result = type.isAsignableFrom (actualClass);
         * 
* But this can prevent the class actualClass to be * loaded into the JavaVM. * * @param type the class type we want to check * @return true if this cookie can produce object of given type */ public boolean instanceOf(Class type) { if (cookie instanceof InstanceCookie.Of) { InstanceCookie.Of of = (InstanceCookie.Of)cookie; return of.instanceOf (type); } // delegate try { Class clazz = cookie.instanceClass (); return type.isAssignableFrom (clazz); } catch (IOException ex) { return false; } catch (ClassNotFoundException ex) { return false; } } /** Returns the root class of all objects. * Supposed to be overriden in subclasses. * * @return Object.class * @exception IOException an I/O error occured * @exception ClassNotFoundException the class has not been found */ public Class instanceClass () throws java.io.IOException, ClassNotFoundException { return cookie.instanceClass (); } /** * @return an object to work with * @exception IOException an I/O error occured * @exception ClassNotFoundException the class has not been found */ public Object instanceCreate () throws java.io.IOException, ClassNotFoundException { return instanceForCookie (source, cookie); } /** Called when a task finishes running. * @param task the finished task */ public void taskFinished(Task task) { checkRecreate(); } /** Waits till the instance is ready. */ public Task getTask () { if (cookie instanceof Task) { // for example FolderInstance ;-) attach itself for changes // in the cookie return (Task)cookie; } else { return null; } } public String toString () { return super.toString () + " from " + source + " tocookie: " + cookie; // NOI18N } } // end of HoldInstance }
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.