# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: C:\Users\Jonathan\proj\wl-latest\wonderland\modules\world\avatarbase
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: src/classes/org/jdesktop/wonderland/modules/avatarbase/client/imi/ImiAvatarConfigManager.java
--- src/classes/org/jdesktop/wonderland/modules/avatarbase/client/imi/ImiAvatarConfigManager.java Base (BASE)
+++ src/classes/org/jdesktop/wonderland/modules/avatarbase/client/imi/ImiAvatarConfigManager.java Locally Modified (Based On LOCAL)
@@ -26,6 +26,11 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.Semaphore;
 import java.util.logging.Level;
@@ -174,8 +179,14 @@
         synchronized (avatarConfigServers) {
             t = avatarConfigServers.get(session);
         }
+
+        try {
         return t.getAvatarServerURL(avatar);
+        } catch (ExecutionException ee) {
+            logger.log(Level.WARNING, "Error syncing avatar", ee);
+            return null;
     }
+    }
 
     /**
      * Returns true if the given server is managed and at least the initial
@@ -235,6 +246,10 @@
                 logger.log(Level.WARNING, "Unable to create sync thread for " +
                         "server " + session.getServerURL(), excp);
                 return;
+            } catch (ExecutionException ee) {
+                logger.log(Level.WARNING, "Unable to create sync thread for " +
+                        "server " + session.getServerURL(), ee);
+                return;
             }
 
             // Finally, add this server to the list of servers indicating that
@@ -302,6 +317,11 @@
                                     " avatar " + avatar.getName() + " from " +
                                     "the server " + c.toString() + " was " +
                                     "interrupted.", excp);
+                        } catch (ExecutionException ee) {
+                            logger.log(Level.WARNING, "Attempt to delete the" +
+                                    " avatar " + avatar.getName() + " from " +
+                                    "the server " + c.toString() + " threw " +
+                                    ee, ee);
                         }
                     }
                 }
@@ -362,12 +382,16 @@
                         logger.info("Schedule delete of existing avatar " +
                                 "named " + avatarName + " from server.");
                         t.scheduleDelete(existingAvatar, true);
-                    }
-                    catch (InterruptedException excp) {
+                    } catch (InterruptedException excp) {
                         logger.log(Level.WARNING, "Attempt to delete the" +
                                 " avatar " + avatar.getName() + " from " +
                                 "the server " + t.toString() + " was " +
                                 "interrupted.", excp);
+                    } catch (ExecutionException ee) {
+                        logger.log(Level.WARNING, "Attempt to delete the" +
+                                " avatar " + avatar.getName() + " from " +
+                                "the server " + t.toString() + " threw " +
+                                ee, ee);
                     }
                 }
             }
@@ -433,6 +457,10 @@
                     logger.log(Level.WARNING, "Attempt to upload the avatar " +
                             avatar.getName() + " to the server " + t.toString() +
                             " was interrupted.", excp);
+                } catch (ExecutionException ee) {
+                    logger.log(Level.WARNING, "Attempt to upload the avatar " +
+                            avatar.getName() + " to the server " + t.toString() +
+                            " threw " + ee, ee);
                 }
             }
         }
@@ -450,36 +478,31 @@
      * a particular server session. It runs its own thread to serialize updates
      * with the server (sync, add, remove, etc).
      */
-    private class ServerSyncThread extends Thread {
+    private class ServerSyncThread {
 
         // The server we are currently collected to
-        private ServerSessionManager manager = null;
+        private final ServerSessionManager manager;
 
-        // A queue of jobs to execute on the thread.
-        private LinkedBlockingQueue<Job> jobQueue = new LinkedBlockingQueue();
-
         // The collection where all IMI avatar information is kept on the server
-        private ContentCollection serverCollection = null;
+        private final ContentCollection serverCollection;
 
         // A map of avatar names to pointers to their configuration files on the
         // server
-        private Map<String, ImiServerAvatar> serverAvatars = new HashMap();
+        private final Map<String, ImiServerAvatar> serverAvatars =
+                new HashMap<String, ImiServerAvatar>();
         
-        // True if we are connected to the server, false if we have disconnected
-        private boolean isConnected = true;
+        // an executor to execute the tasks
+        private final ExecutorService executor =
+                Executors.newSingleThreadExecutor();
 
         public ServerSyncThread(final ServerSessionManager manager)
-                throws ContentRepositoryException {
-
-            super(ThreadManager.getThreadGroup(), "AvatarServerSyncThread");
+                throws ContentRepositoryException
+        {
             this.manager = manager;
 
             // Fetch the base directory in which all IMI avatar configuration info
             // is found on the server.
             serverCollection = getBaseServerCollection(manager);
-
-            // Finally, start the thread off
-            this.start();
         }
 
         /**
@@ -490,8 +513,10 @@
          * @param isConnected True if the session is connected, false if not.
          */
         public void setConnected(boolean isConnected) {
-            this.isConnected = isConnected;
+            if (!isConnected) {
+                executor.shutdownNow();
         }
+        }
 
         /**
          * Returns the URL corresponding to the configuration file on the server
@@ -501,13 +526,19 @@
          * @return The URL of the avatar configuration file on the server
          * @throw InterruptedException If the job has been interrupted
          */
-        public URL getAvatarServerURL(ImiAvatar avatar) throws InterruptedException {
-            Job job = Job.newGetURLJob(avatar);
-            jobQueue.add(job);
-            job.waitForJob();
-            return job.url;
+        public URL getAvatarServerURL(final ImiAvatar avatar)
+                throws InterruptedException, ExecutionException
+        {
+            Callable<URL> job = new Callable<URL>() {
+                public URL call() throws Exception {
+                    return getURLImpl(avatar);
         }
+            };
 
+            Future<URL> f = executor.submit(job);
+            return f.get();
+        }
+
         /**
          * Schedules an asynchronous job to synchronous the IMI avatar
          * configuration between the client and server. The caller may block
@@ -516,11 +547,18 @@
          * @param isWait True to block until the job has completed
          * @throw InterruptedException If the job has been interrupted
          */
-        public void scheduleSync(boolean isWait) throws InterruptedException {
-            Job job = Job.newSyncJob();
-            jobQueue.add(job);
+        public void scheduleSync(boolean isWait) 
+                throws InterruptedException, ExecutionException
+        {
+            Runnable job = new Runnable() {
+                public void run() {
+                    syncImpl();
+                }
+            };
+
+            Future f = executor.submit(job);
             if (isWait == true) {
-                job.waitForJob();
+                f.get();
             }
         }
 
@@ -532,11 +570,18 @@
          * @param isWait True to block until the job has completed
          * @throw InterruptedException If the job has been interrupted
          */
-        public void scheduleDelete(ImiAvatar avatar, boolean isWait) throws InterruptedException {
-            Job job = Job.newDeleteJob(avatar);
-            jobQueue.add(job);
+        public void scheduleDelete(final ImiAvatar avatar, boolean isWait)
+                throws InterruptedException, ExecutionException
+        {
+            Runnable job = new Runnable() {
+                public void run() {
+                    deleteImpl(avatar);
+                }
+            };
+
+            Future f = executor.submit(job);
             if (isWait == true) {
-                job.waitForJob();
+                f.get();
             }
         }
 
@@ -548,11 +593,18 @@
          * @param isWait True to block until the job has completed
          * @throw InterruptedException If the job has been interrupted
          */
-        public void scheduleUpload(ImiAvatar avatar, boolean isWait) throws InterruptedException {
-            Job job = Job.newUploadJob(avatar);
-            jobQueue.add(job);
+        public void scheduleUpload(final ImiAvatar avatar, boolean isWait)
+                throws InterruptedException, ExecutionException
+        {
+            Runnable job = new Runnable() {
+                public void run() {
+                    uploadFileImpl(avatar);
+                }
+            };
+            
+            Future f = executor.submit(job);
             if (isWait == true) {
-                job.waitForJob();
+                f.get();
             }
         }
 
@@ -576,44 +628,6 @@
         }
 
         /**
-         * {@inheritDoc}
-         */
-        @Override
-        public void run() {
-            while (isConnected == true) {
-                // Fetch the next job. If we are interrupted in doing so, then
-                // simply log an error and continue.
-                Job job = null;
-                try {
-                    job = jobQueue.take();
-                } catch (InterruptedException excp) {
-                    logger.log(Level.WARNING, "Attempt to fetch the next job" +
-                            " in queue was interrupted for server " +
-                            manager.getServerURL(), excp);
-                    continue;
-                }
-
-                // Dispatch to the implementation based upon the job type. When
-                // done indicate we are done.
-                switch (job.jobType) {
-                    case SYNC:
-                        syncImpl();
-                        break;
-                    case DELETE:
-                        deleteImpl(job.avatar);
-                        break;
-                    case UPLOAD:
-                        uploadFileImpl(job.avatar);
-                        break;
-                    case GETURL:
-                        job.url = getURLImpl(job.avatar);
-                        break;
-                }
-                job.setJobDone();
-            }
-        }
-
-        /**
          * Synchronous implementation of removing an avatar from the server
          * given the avatar to remove.
          *
@@ -949,60 +963,5 @@
             }
         }
     }
-
-    /**
-     * A static inner class that represents a 'job' submitted to the 'server
-     * sync' thread. Threads may block on the completion of a thread by
-     * invoking waitForJob().
-     */
-    private static class Job {
-
-        public enum JobType {
-            SYNC, DELETE, UPLOAD, GETURL
-        };
-
-        public JobType jobType;
-        public ImiAvatar avatar = null;
-        public Semaphore jobDone = null;
-        public URL url = null;
-
-        private Job(JobType jobType, ImiAvatar avatar) {
-            this.jobType = jobType;
-            this.avatar = avatar;
-            this.jobDone = new Semaphore(0);
-            this.url = null;
         }
 
-        public static Job newSyncJob() {
-            return new Job(JobType.SYNC, null);
-        }
-
-        public static Job newDeleteJob(ImiAvatar avatar) {
-            return new Job(JobType.DELETE, avatar);
-        }
-
-        public static Job newUploadJob(ImiAvatar avatar) {
-            return new Job(JobType.UPLOAD, avatar);
-        }
-
-        public static Job newGetURLJob(ImiAvatar avatar) {
-            return new Job(JobType.GETURL, avatar);
-        }
-
-        /**
-         * Waits for this job to be done.
-         * @throw InterruptedException If the job has been interrupted
-         */
-        public void waitForJob() throws InterruptedException {
-            jobDone.acquire();
-        }
-
-        /**
-         * Used by jobs to indicate they have completed.
-         */
-        public void setJobDone() {
-            jobDone.release();
-        }
-    }
-}
-
