package ch.cyberduck.core; /* * Copyright (c) 2005 David Kocher. All rights reserved. * http://cyberduck.ch/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Bug fixes, suggestions and comments should be sent to: * dkocher@cyberduck.ch */ import java.beans.XMLEncoder; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.util.logging.Level; import org.apache.commons.collections.map.LRUMap; import org.apache.log4j.Logger; import java.util.*; /** * A cache for remote directory listings * * @version $Id: Cache.java 5543 2009-11-08 00:10:56Z dkocher $ */ public class Cache<E extends AbstractPath> { protected static Logger log = Logger.getLogger(Cache.class); /** * @uml.property name="_impl" * @uml.associationEnd qualifier="getAbsolute:java.lang.String ch.cyberduck.core.AttributedList" */ private Map<String, AttributedList<E>> _impl = Collections.<String, AttributedList<E>>synchronizedMap(new LRUMap( Preferences.instance().getInteger("browser.cache.size")) { @Override protected boolean removeLRU(LinkEntry entry) { log.debug("Removing from cache:" + entry); return true; } }); /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#lookup(ch.cyberduck.core.PathReference) */ public E lookup(PathReference path) { final AttributedList<E> childs = this.get(Path.getParent(path.toString())); final E found = childs.get(path); if (null == found) { log.warn("Lookup failed for " + path + " in cache"); return null; } return found; } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#containsKey(E) */ public boolean containsKey(E path) { return this.containsKey(path.getAbsolute()); } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#containsKey(java.lang.String) */ public boolean containsKey(String path) { return getImpl().containsKey(path); } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#remove(E) */ public AttributedList<E> remove(E path) { return getImpl().remove(path.getAbsolute()); } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#get(E) */ public AttributedList<E> get(E path) { return this.get(path.getAbsolute()); } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#get(java.lang.String) */ public AttributedList<E> get(String path) { final AttributedList<E> childs = getImpl().get(path); if (null == childs) { log.warn("No cache for " + path); return AttributedList.emptyList(); } return childs; } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#get(E, java.util.Comparator, ch.cyberduck.core.PathFilter) */ public AttributedList<E> get(final E path, final Comparator<E> comparator, final PathFilter<E> filter) { return this.get(path.getAbsolute(), comparator, filter); } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#get(java.lang.String, java.util.Comparator, ch.cyberduck.core.PathFilter) */ public AttributedList<E> get(final String path, final Comparator<E> comparator, final PathFilter<E> filter) { AttributedList<E> childs = getImpl().get(path); if (null == childs) { log.warn("No cache for " + path); return AttributedList.emptyList(); } boolean needsSorting = !childs.attributes().get(AttributedList.COMPARATOR).equals(comparator); boolean needsFiltering = !childs.attributes().get(AttributedList.FILTER).equals(filter); if (needsSorting) { // Do not sort when the list has not been filtered yet if (!needsFiltering) { this.sort(childs, comparator); } // Saving last sorting comparator childs.attributes().put(AttributedList.COMPARATOR, comparator); } if (needsFiltering) { // Add previously hidden files to childs final Set<E> hidden = childs.attributes().getHidden(); childs.addAll(hidden); // Clear the previously set of hidden files hidden.clear(); for (E child : childs) { if (!filter.accept(child)) { //child not accepted by filter; add to cached hidden files childs.attributes().addHidden(child); //remove hidden file from current file listing childs.remove(child); } } // Saving last filter childs.attributes().put(AttributedList.FILTER, filter); // Sort again because the list has changed this.sort(childs, comparator); } return childs; } /** * The CopyOnWriteArrayList iterator does not support remove but the sort implementation * makes use of it. Provide our own implementation here to circumvent. * * @param childs * @param comparator * @see java.util.Collections#sort(java.util.List, java.util.Comparator) * @see java.util.concurrent.CopyOnWriteArrayList#iterator() */ private void sort(AttributedList<E> childs, Comparator comparator) { // Because AttributedList is a CopyOnWriteArrayList we can not use Collections.sort AbstractPath[] sorted = childs.toArray(new AbstractPath[childs.size()]); Arrays.sort(sorted, (Comparator<AbstractPath>) comparator); for (int j = 0; j < sorted.length; j++) { childs.set(j, (E) sorted[j]); } } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#put(E, ch.cyberduck.core.AttributedList) */ public AttributedList<E> put(E path, AttributedList<E> childs) { return getImpl().put(path.getAbsolute(), childs); } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#clear() */ public void clear() { log.info("Clearing cache " + this.toString()); getImpl().clear(); } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#encodeToXML() */ public void encodeToXML() { FileOutputStream os = null; try { os = new FileOutputStream("D:\\cust.xml"); } catch (FileNotFoundException ex) { java.util.logging.Logger.getLogger(Cache.class.getName()).log(Level.SEVERE, null, ex); } XMLEncoder encoder = new XMLEncoder(os); //Person p = new Person(); //p.setFirstName("John"); //encoder.writeObject(p); encoder.writeObject(getImpl()); encoder.close(); } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#getImpl() */ public Map<String, AttributedList<E>> getImpl() { return _impl; } /* (non-Javadoc) * @see ch.cyberduck.core.CacheService#setImpl(java.util.Map) */ public void setImpl(Map<String, AttributedList<E>> impl) { this._impl = impl; } }