Package share.folder.tree

Source Code of share.folder.tree.ThreadedTreeManager$UpdaterThread

package share.folder.tree;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import common.util.NonNullObjectInputStream;

import share.folder.Folder;
import share.folder.tree.node.AbstractFolderTreeNode;

import main.settings.Settings;


public class ThreadedTreeManager
{
  private FolderTree folderTree;

  private ConcurrentHashMap<Folder, Thread> threadMap;
  private Thread updaterThread;

  private ReentrantReadWriteLock lock;

  public ThreadedTreeManager()
  {
    folderTree = new FolderTree();

    threadMap = new ConcurrentHashMap<Folder, Thread>();
    updaterThread = null;

    lock = new ReentrantReadWriteLock();
  }

  public Vector<AbstractFolderTreeNode> getTreeRoots()
  {
    return folderTree.getRoots();
  }

  public boolean readTreeFromFile()
  {
    FileInputStream fis;
    try
    {
      fis = new FileInputStream(Settings.application.files.shared);
    }
    catch (FileNotFoundException e)
    {
      return false;
    }

    try
    {
      NonNullObjectInputStream ois = new NonNullObjectInputStream(fis);
      folderTree = (FolderTree) ois.readObject();
    }
    catch (IOException e)
    {
      return false;
    }
    catch (ClassNotFoundException e)
    {
      return false;
    }
    catch (ClassCastException e)
    {
      return false;
    }

    return true;
  }

  private boolean writeTreeToFile()
  {
    try
    {
      FileOutputStream fos = new FileOutputStream(Settings.application.files.shared);
      new ObjectOutputStream(fos).writeObject(folderTree);
    }
    catch (FileNotFoundException e)
    {
      return false;
    }
    catch (IOException e)
    {
      return false;
    }

    return true;
  }

  public synchronized void addFolder(Folder folder, boolean subfolders)
  {
    Thread thread = new Thread(new AdderThread(folder, subfolders),
        "FolderTreeManager: add " + folder.getName());
    startFolderThread(folder, thread);
  }

  public synchronized void removeFolder(Folder folder)
  {
    Thread thread = new Thread(new RemoverThread(folder), "FolderTreeManager: del "
        + folder.getName());
    startFolderThread(folder, thread);
  }

  public synchronized void changeFolderMode(Folder folder, boolean subfolders)
  {
    Thread thread = new Thread(new ChangerThread(folder, subfolders),
        "FolderTreeManager: change " + folder.getName());
    startFolderThread(folder, thread);
  }

  public synchronized void updateFolders()
  {
    if ((updaterThread == null) || !updaterThread.isAlive())
    {
      updaterThread = new Thread(new UpdaterThread(), "FolderTreeManager: update");
      updaterThread.start();
    }
  }

  // TODO: avendo una join deve andare su un thread separato?
  private void startFolderThread(Folder folder, Thread thread)
  {
    if (threadMap.containsKey(folder))
    {
      Thread oldThread = threadMap.get(folder);
      if (oldThread.isAlive())
      {
        oldThread.interrupt();
        try
        {
          oldThread.join();
        }
        catch (InterruptedException e)
        {
          // che devo fare in questo caso? e' stato interrotto il
          // thread
          // principale...
        }
      }
    }

    threadMap.put(folder, thread);
    thread.start();
  }

  private abstract class AbstractThread implements Runnable
  {
    protected Folder folder;

    protected AbstractThread(Folder folder)
    {
      this.folder = folder;
    }

    public void run()
    {
      Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

      lock.readLock().lock();

      try
      {
        doJob();
      }
      catch (InterruptedException e)
      {
        // niente write se il thread e' interrotto
        return;
      }
      finally
      {
        lock.readLock().unlock();
      }

      lock.writeLock().lock();
      writeTreeToFile();
      lock.writeLock().unlock();

      // per supportare anche l'updater
      if (folder != null)
      {
        synchronized (threadMap)
        {
          threadMap.remove(folder);
        }
      }

    }

    protected abstract void doJob() throws InterruptedException;

  }

  private class AdderThread extends AbstractThread
  {
    private boolean subfolders;

    public AdderThread(Folder folder, boolean subfolders)
    {
      super(folder);
      this.subfolders = subfolders;
    }

    protected void doJob() throws InterruptedException
    {
      folderTree.add(folder, subfolders);
    }

  }

  private class RemoverThread extends AbstractThread
  {
    public RemoverThread(Folder folder)
    {
      super(folder);
    }

    protected void doJob() throws InterruptedException
    {
      folderTree.remove(folder);
    }

  }

  private class ChangerThread extends AbstractThread
  {
    private boolean subfolders;

    public ChangerThread(Folder folder, boolean subfolders)
    {
      super(folder);
      this.subfolders = subfolders;
    }

    protected void doJob() throws InterruptedException
    {
      folderTree.change(folder, subfolders);
    }

  }

  private class UpdaterThread extends AbstractThread
  {
    public UpdaterThread()
    {
      super(null);
    }

    protected void doJob() throws InterruptedException
    {
      folderTree.update();
    }

  }

}
TOP

Related Classes of share.folder.tree.ThreadedTreeManager$UpdaterThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.