tikhomirov@64: /* tikhomirov@431: * Copyright (c) 2011-2012 TMate Software Ltd tikhomirov@64: * tikhomirov@64: * This program is free software; you can redistribute it and/or modify tikhomirov@64: * it under the terms of the GNU General Public License as published by tikhomirov@64: * the Free Software Foundation; version 2 of the License. tikhomirov@64: * tikhomirov@64: * This program is distributed in the hope that it will be useful, tikhomirov@64: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@64: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@64: * GNU General Public License for more details. tikhomirov@64: * tikhomirov@64: * For information on how to redistribute this software under tikhomirov@64: * the terms of a license other than GNU General Public License tikhomirov@102: * contact TMate Software at support@hg4j.com tikhomirov@64: */ tikhomirov@431: package org.tmatesoft.hg.internal; tikhomirov@64: tikhomirov@64: import java.lang.ref.SoftReference; tikhomirov@64: import java.util.WeakHashMap; tikhomirov@64: tikhomirov@431: import org.tmatesoft.hg.util.Convertor; tikhomirov@431: import org.tmatesoft.hg.util.Path; tikhomirov@431: import org.tmatesoft.hg.util.PathRewrite; tikhomirov@431: tikhomirov@64: tikhomirov@64: /** tikhomirov@431: * Produces path from strings and caches (weakly) result for reuse tikhomirov@141: * tikhomirov@64: * @author Artem Tikhomirov tikhomirov@64: * @author TMate Software Ltd. tikhomirov@64: */ tikhomirov@431: public class PathPool implements Path.Source, Convertor { tikhomirov@431: private final WeakHashMap> cache; tikhomirov@64: private final PathRewrite pathRewrite; tikhomirov@64: tikhomirov@64: public PathPool(PathRewrite rewrite) { tikhomirov@64: pathRewrite = rewrite; tikhomirov@431: cache = new WeakHashMap>(); tikhomirov@64: } tikhomirov@64: tikhomirov@431: /* tikhomirov@431: * (non-Javadoc) tikhomirov@431: * @see org.tmatesoft.hg.util.Path.Source#path(java.lang.CharSequence) tikhomirov@431: */ tikhomirov@431: public Path path(CharSequence p) { tikhomirov@431: if (p instanceof Path) { tikhomirov@431: return asPath((Path) p); tikhomirov@431: } tikhomirov@431: p = pathRewrite.rewrite(p); tikhomirov@141: return get(p, true); tikhomirov@141: } tikhomirov@141: tikhomirov@431: /* tikhomirov@431: * (non-Javadoc) tikhomirov@431: * @see org.tmatesoft.hg.util.Convertor#mangle(java.lang.Object) tikhomirov@431: */ tikhomirov@431: public Path mangle(Path p) { tikhomirov@431: return asPath(p); tikhomirov@431: } tikhomirov@431: tikhomirov@141: // pipes path object through cache to reuse instance, if possible tikhomirov@231: // TODO unify with Pool tikhomirov@431: private Path asPath(Path p) { tikhomirov@431: CharSequence s = pathRewrite.rewrite(p.toString()); tikhomirov@431: // rewrite string, not path to avoid use of Path object as key tikhomirov@431: // in case pathRewrite does nothing and returns supplied instance tikhomirov@431: // tikhomirov@141: Path cached = get(s, false); tikhomirov@141: if (cached == null) { tikhomirov@141: cache.put(s, new SoftReference(cached = p)); tikhomirov@64: } tikhomirov@141: return cached; tikhomirov@64: } tikhomirov@64: tikhomirov@64: // XXX what would be parent of an empty path? tikhomirov@64: // Path shall have similar functionality tikhomirov@64: public Path parent(Path path) { tikhomirov@64: if (path.length() == 0) { tikhomirov@64: throw new IllegalArgumentException(); tikhomirov@64: } tikhomirov@64: for (int i = path.length() - 2 /*if path represents a dir, trailing char is slash, skip*/; i >= 0; i--) { tikhomirov@64: if (path.charAt(i) == '/') { tikhomirov@64: return get(path.subSequence(0, i+1).toString(), true); tikhomirov@64: } tikhomirov@64: } tikhomirov@64: return get("", true); tikhomirov@64: } tikhomirov@231: tikhomirov@231: // invoke when path pool is no longer in use, to ease gc work tikhomirov@231: public void clear() { tikhomirov@231: cache.clear(); tikhomirov@231: } tikhomirov@64: tikhomirov@431: private Path get(CharSequence p, boolean create) { tikhomirov@64: SoftReference sr = cache.get(p); tikhomirov@64: Path path = sr == null ? null : sr.get(); tikhomirov@64: if (path == null) { tikhomirov@64: if (create) { tikhomirov@64: path = Path.create(p); tikhomirov@64: cache.put(p, new SoftReference(path)); tikhomirov@64: } else if (sr != null) { tikhomirov@64: // cached path no longer used, clear cache entry - do not wait for RefQueue to step in tikhomirov@64: cache.remove(p); tikhomirov@64: } tikhomirov@64: } tikhomirov@64: return path; tikhomirov@64: } tikhomirov@64: }