Package freenet.clients.http.bookmark

Source Code of freenet.clients.http.bookmark.BookmarkManager$USKUpdatedCallback

/* This code is part of Freenet. It is distributed under the GNU General
* Public License, version 2 (or at your option any later version). See
* http://www.gnu.org/ for further details of the GPL. */
package freenet.clients.http.bookmark;

import static java.util.concurrent.TimeUnit.MINUTES;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import freenet.client.async.ClientContext;
import freenet.client.async.USKCallback;
import freenet.clients.http.FProxyToadlet;
import freenet.keys.FreenetURI;
import freenet.keys.USK;
import freenet.l10n.NodeL10n;
import freenet.node.FSParseException;
import freenet.node.NodeClientCore;
import freenet.node.RequestClient;
import freenet.node.RequestStarter;
import freenet.support.LogThresholdCallback;
import freenet.support.Logger;
import freenet.support.Logger.LogLevel;
import freenet.support.SimpleFieldSet;
import freenet.support.io.Closer;
import freenet.support.io.FileUtil;

public class BookmarkManager implements RequestClient {

  public static final SimpleFieldSet DEFAULT_BOOKMARKS;
  private final NodeClientCore node;
  private final USKUpdatedCallback uskCB = new USKUpdatedCallback();
  public static final BookmarkCategory MAIN_CATEGORY = new BookmarkCategory("/");
  public static final BookmarkCategory DEFAULT_CATEGORY = new BookmarkCategory("\\");
  private final HashMap<String, Bookmark> bookmarks = new HashMap<String, Bookmark>();
  private final File bookmarksFile;
  private final File backupBookmarksFile;
  private boolean isSavingBookmarks = false;
  private boolean isSavingBookmarksLazy = false;
  static {
    String name = "freenet/clients/http/staticfiles/defaultbookmarks.dat";
    SimpleFieldSet defaultBookmarks = null;
    InputStream in = null;
    try {
      ClassLoader loader = BookmarkManager.class.getClassLoader();

      // Returns null on lookup failures:
      in = loader.getResourceAsStream(name);
      if(in != null)
        defaultBookmarks = SimpleFieldSet.readFrom(in, false, false);
    } catch(Exception e) {
      Logger.error(BookmarkManager.class, "Error while loading the default bookmark file from " + name + " :" + e.getMessage(), e);
    } finally {
      Closer.close(in);
      DEFAULT_BOOKMARKS = defaultBookmarks;
    }
  }

        private static volatile boolean logMINOR;
  static {
    Logger.registerLogThresholdCallback(new LogThresholdCallback(){
      @Override
      public void shouldUpdate(){
        logMINOR = Logger.shouldLog(LogLevel.MINOR, this);
      }
    });
  }

  public BookmarkManager(NodeClientCore n, boolean publicGateway) {
    putPaths("/", MAIN_CATEGORY);
    this.node = n;
    this.bookmarksFile = n.node.userDir().file("bookmarks.dat");
    this.backupBookmarksFile = n.node.userDir().file("bookmarks.dat.bak");

    try {
      // Read the backup file if necessary
      if(!bookmarksFile.exists() || bookmarksFile.length() == 0)
        throw new IOException();
      Logger.normal(this, "Attempting to read the bookmark file from " + bookmarksFile.toString());
      SimpleFieldSet sfs = SimpleFieldSet.readFrom(bookmarksFile, false, true);
      readBookmarks(MAIN_CATEGORY, sfs);
    } catch(MalformedURLException mue) {
    } catch(IOException ioe) {
      Logger.error(this, "Error reading the bookmark file (" + bookmarksFile.toString() + "):" + ioe.getMessage(), ioe);

      try {
        if(backupBookmarksFile.exists() && backupBookmarksFile.canRead() && backupBookmarksFile.length() > 0) {
          Logger.normal(this, "Attempting to read the backup bookmark file from " + backupBookmarksFile.toString());
          SimpleFieldSet sfs = SimpleFieldSet.readFrom(backupBookmarksFile, false, true);
          readBookmarks(MAIN_CATEGORY, sfs);
        } else {
          Logger.normal(this, "We couldn't find the backup either! - " + FileUtil.getCanonicalFile(backupBookmarksFile));
          // restore the default bookmark set
          readBookmarks(MAIN_CATEGORY, DEFAULT_BOOKMARKS);
        }
      } catch(IOException e) {
        Logger.error(this, "Error reading the backup bookmark file !" + e.getMessage(), e);
      }
    }
    //populate defaults for hosts without full access permissions if we're in gateway mode.
    if (publicGateway) {
      putPaths("\\", DEFAULT_CATEGORY);
      readBookmarks(DEFAULT_CATEGORY, DEFAULT_BOOKMARKS);
    }
  }

  public void reAddDefaultBookmarks() {
    BookmarkCategory bc = new BookmarkCategory(l10n("defaultBookmarks") + " - " + new Date());
    addBookmark("/", bc);
    _innerReadBookmarks("/", bc, DEFAULT_BOOKMARKS);
  }

  private class USKUpdatedCallback implements USKCallback {

    @Override
    public void onFoundEdition(long edition, USK key, ClientContext context, boolean wasMetadata, short codec, byte[] data, boolean newKnownGood, boolean newSlotToo) {
      if(!newKnownGood) {
        FreenetURI uri = key.copy(edition).getURI();
        node.makeClient(PRIORITY_PROGRESS, false, false).prefetch(uri, MINUTES.toMillis(60), FProxyToadlet.MAX_LENGTH_WITH_PROGRESS, null, PRIORITY_PROGRESS);
        return;
      }
      List<BookmarkItem> items = MAIN_CATEGORY.getAllItems();
      boolean matched = false;
      boolean updated = false;
      for(int i = 0; i < items.size(); i++) {
        if(!"USK".equals(items.get(i).getKeyType()))
          continue;

        try {
          FreenetURI furi = new FreenetURI(items.get(i).getKey());
          USK usk = USK.create(furi);

          if(usk.equals(key, false)) {
            if(logMINOR) Logger.minor(this, "Updating bookmark for "+furi+" to edition "+edition);
            matched = true;
            BookmarkItem item = items.get(i);
            updated |= item.setEdition(edition, node);
            // We may have bookmarked the same site twice, so continue the search.
          }
        } catch(MalformedURLException mue) {
        }
      }
      if(updated) {
        storeBookmarksLazy();
      } else if(!matched) {
        Logger.error(this, "No match for bookmark "+key+" edition "+edition);
      }
    }

    @Override
    public short getPollingPriorityNormal() {
      return PRIORITY;
    }

    @Override
    public short getPollingPriorityProgress() {
      return PRIORITY_PROGRESS;
    }
  }

  public String l10n(String key) {
    return NodeL10n.getBase().getString("BookmarkManager." + key);
  }

  public String parentPath(String path) {
    if(path.equals("/"))
      return "/";

    return path.substring(0, path.substring(0, path.length() - 1).lastIndexOf('/')) + "/";
  }

  public Bookmark getBookmarkByPath(String path) {
    synchronized(bookmarks) {
      return bookmarks.get(path);
    }
  }

  public BookmarkCategory getCategoryByPath(String path) {
    Bookmark cat = getBookmarkByPath(path);
    if(cat instanceof BookmarkCategory)
      return (BookmarkCategory) cat;

    return null;
  }

  public BookmarkItem getItemByPath(String path) {
    if(getBookmarkByPath(path) instanceof BookmarkItem)
      return (BookmarkItem) getBookmarkByPath(path);

    return null;
  }

  public void addBookmark(String parentPath, Bookmark bookmark) {
    if(logMINOR)
      Logger.minor(this, "Adding bookmark " + bookmark + " to " + parentPath);
    BookmarkCategory parent = getCategoryByPath(parentPath);
    parent.addBookmark(bookmark);
    putPaths(parentPath + bookmark.getName() + ((bookmark instanceof BookmarkCategory) ? "/" : ""),
      bookmark);

    if(bookmark instanceof BookmarkItem)
      subscribeToUSK((BookmarkItem)bookmark);
  }

  public void renameBookmark(String path, String newName) {
    Bookmark bookmark = getBookmarkByPath(path);
    String oldName = bookmark.getName();
    String oldPath = '/' + oldName;
    String newPath = path.substring(0, path.indexOf(oldPath)) + '/' + newName + (bookmark instanceof BookmarkCategory ? "/" : "");

    bookmark.setName(newName);
    synchronized(bookmarks) {
      Iterator<String> it = bookmarks.keySet().iterator();
      while(it.hasNext()) {
        String s = it.next();
        if(s.startsWith(path)) {
          it.remove();
        }
      }
      putPaths(newPath, bookmark);
    }
    storeBookmarks();
  }

  public void moveBookmark(String bookmarkPath, String newParentPath) {
    Bookmark b = getBookmarkByPath(bookmarkPath);
    addBookmark(newParentPath, b);

    getCategoryByPath(parentPath(bookmarkPath)).removeBookmark(b);
    removePaths(bookmarkPath);
  }

  public void removeBookmark(String path) {
    Bookmark bookmark = getBookmarkByPath(path);
    if(bookmark == null)
      return;

    if(bookmark instanceof BookmarkCategory) {
      BookmarkCategory cat = (BookmarkCategory) bookmark;
      for(int i = 0; i < cat.size(); i++)
        removeBookmark(path + cat.get(i).getName() + ((cat.get(i) instanceof BookmarkCategory) ? "/"
          : ""));
    } else {
      if(((BookmarkItem) bookmark).getKeyType().equals("USK")) {
        try {
          USK u = ((BookmarkItem) bookmark).getUSK();
          if(!wantUSK(u, (BookmarkItem)bookmark)) {
            this.node.uskManager.unsubscribe(u, this.uskCB);
          }
        } catch(MalformedURLException mue) {
        }
      }
    }

    getCategoryByPath(parentPath(path)).removeBookmark(bookmark);
    synchronized(bookmarks) {
      bookmarks.remove(path);
    }
  }

  private boolean wantUSK(USK u, BookmarkItem ignore) {
    List<BookmarkItem> items = MAIN_CATEGORY.getAllItems();
    for(BookmarkItem item : items) {
      if(item == ignore)
        continue;
      if(!"USK".equals(item.getKeyType()))
        continue;

      try {
        FreenetURI furi = new FreenetURI(item.getKey());
        USK usk = USK.create(furi);

        if(usk.equals(u, false)) return true;
      } catch(MalformedURLException mue) {
      }
    }
    return false;
  }

  public void moveBookmarkUp(String path, boolean store) {
    BookmarkCategory parent = getCategoryByPath(parentPath(path));
    parent.moveBookmarkUp(getBookmarkByPath(path));

    if(store)
      storeBookmarks();
  }

  public void moveBookmarkDown(String path, boolean store) {
    BookmarkCategory parent = getCategoryByPath(parentPath(path));
    parent.moveBookmarkDown(getBookmarkByPath(path));

    if(store)
      storeBookmarks();
  }

  private void putPaths(String path, Bookmark b) {
    synchronized(bookmarks) {
      bookmarks.put(path, b);
    }
    if(b instanceof BookmarkCategory)
      for(int i = 0; i < ((BookmarkCategory) b).size(); i++) {
        Bookmark child = ((BookmarkCategory) b).get(i);
        putPaths(path + child.getName() + (child instanceof BookmarkItem ? "" : "/"), child);
      }

  }

  private void removePaths(String path) {
    if(getBookmarkByPath(path) instanceof BookmarkCategory) {
      BookmarkCategory cat = getCategoryByPath(path);
      for(int i = 0; i < cat.size(); i++)
        removePaths(path + cat.get(i).getName() + (cat.get(i) instanceof BookmarkCategory ? "/" : ""));
    }
    bookmarks.remove(path);
  }

  public FreenetURI[] getBookmarkURIs() {
    List<BookmarkItem> items = MAIN_CATEGORY.getAllItems();
    FreenetURI[] uris = new FreenetURI[items.size()];
    for(int i = 0; i < items.size(); i++)
      uris[i] = items.get(i).getURI();

    return uris;
  }
 
  public void storeBookmarksLazy() {
    synchronized(bookmarks) {
      if(isSavingBookmarksLazy) return;
      isSavingBookmarksLazy = true;
      node.node.ticker.queueTimedJob(new Runnable() {

        @Override
        public void run() {
          try {
            storeBookmarks();
          } finally {
            isSavingBookmarksLazy = false;
          }
        }

      }, MINUTES.toMillis(5));
    }
  }

  public void storeBookmarks() {
    Logger.normal(this, "Attempting to save bookmarks to " + bookmarksFile.toString());
    SimpleFieldSet sfs = null;
    synchronized(bookmarks) {
      if(isSavingBookmarks)
        return;
      isSavingBookmarks = true;

      sfs = toSimpleFieldSet();
    }
    FileOutputStream fos = null;
    try {
      fos = new FileOutputStream(backupBookmarksFile);
      sfs.writeToBigBuffer(fos);
      fos.close();
      fos = null;
      if(!FileUtil.renameTo(backupBookmarksFile, bookmarksFile))
        Logger.error(this, "Unable to rename " + backupBookmarksFile.toString() + " to " + bookmarksFile.toString());
    } catch(IOException ioe) {
      Logger.error(this, "An error has occured saving the bookmark file :" + ioe.getMessage(), ioe);
    } finally {
      Closer.close(fos);

      synchronized(bookmarks) {
        isSavingBookmarks = false;
      }
    }
  }

  private void readBookmarks(BookmarkCategory category, SimpleFieldSet sfs) {
    _innerReadBookmarks("", category, sfs);
  }

  static final short PRIORITY = RequestStarter.BULK_SPLITFILE_PRIORITY_CLASS;
  static final short PRIORITY_PROGRESS = RequestStarter.UPDATE_PRIORITY_CLASS;

  private void subscribeToUSK(BookmarkItem item) {
    if("USK".equals(item.getKeyType()))
      try {
        USK u = item.getUSK();
        this.node.uskManager.subscribe(u, this.uskCB, true, this);
      } catch(MalformedURLException mue) {}
  }

  private synchronized void _innerReadBookmarks(String prefix, BookmarkCategory category, SimpleFieldSet sfs) {
    boolean hasBeenParsedWithoutAnyProblem = true;
    boolean isRoot = ("".equals(prefix) && MAIN_CATEGORY.equals(category));
    synchronized(bookmarks) {
      if(!isRoot)
        putPaths(prefix + category.name + '/', category);

      try {
        int nbBookmarks = sfs.getInt(BookmarkItem.NAME);
        int nbCategories = sfs.getInt(BookmarkCategory.NAME);

        for(int i = 0; i < nbBookmarks; i++) {
          SimpleFieldSet subset = sfs.getSubset(BookmarkItem.NAME + i);
          try {
            BookmarkItem item = new BookmarkItem(subset, node.alerts);
            String name = (isRoot ? "" : prefix + category.name) + '/' + item.name;
            putPaths(name, item);
            category.addBookmark(item);
            subscribeToUSK(item);
          } catch(MalformedURLException e) {
            throw new FSParseException(e);
          }
        }

        for(int i = 0; i < nbCategories; i++) {
          SimpleFieldSet subset = sfs.getSubset(BookmarkCategory.NAME + i);
          BookmarkCategory currentCategory = new BookmarkCategory(subset);
          category.addBookmark(currentCategory);
          String name = (isRoot ? "/" : (prefix + category.name + '/'));
          _innerReadBookmarks(name, currentCategory, subset.getSubset("Content"));
        }

      } catch(FSParseException e) {
        Logger.error(this, "Error parsing the bookmarks file!", e);
        hasBeenParsedWithoutAnyProblem = false;
      }

    }
    if(hasBeenParsedWithoutAnyProblem)
      storeBookmarks();
  }


  public SimpleFieldSet toSimpleFieldSet() {
    SimpleFieldSet sfs = new SimpleFieldSet(true);

    sfs.put("Version", 1);
    synchronized(bookmarks) {
      sfs.putAllOverwrite(BookmarkManager.toSimpleFieldSet(MAIN_CATEGORY));
    }

    return sfs;
  }

  public static SimpleFieldSet toSimpleFieldSet(BookmarkCategory cat) {
    SimpleFieldSet sfs = new SimpleFieldSet(true);
    List<BookmarkCategory> bc = cat.getSubCategories();

    for(int i = 0; i < bc.size(); i++) {
      BookmarkCategory currentCat = bc.get(i);
      sfs.put(BookmarkCategory.NAME + i, currentCat.getSimpleFieldSet());
    }
    sfs.put(BookmarkCategory.NAME, bc.size());


    List<BookmarkItem> bi = cat.getItems();
    for(int i = 0; i < bi.size(); i++)
      sfs.put(BookmarkItem.NAME + i, bi.get(i).getSimpleFieldSet());
    sfs.put(BookmarkItem.NAME, bi.size());

    return sfs;
  }

  @Override
  public boolean persistent() {
    return false;
  }

  @Override
  public boolean realTimeFlag() {
    return false;
  }
}
TOP

Related Classes of freenet.clients.http.bookmark.BookmarkManager$USKUpdatedCallback

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.