|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.vcscore.caching; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.openide.ErrorManager; import org.openide.util.WeakSet; import org.netbeans.modules.vcscore.cache.CacheDir; import org.netbeans.modules.vcscore.cache.CacheFile; import org.netbeans.modules.vcscore.cache.CacheHandler; /** * File in the cache. * @author Martin Entlicher */ public final class VcsCacheFile extends CacheFile { // true if the file is not in VCS //private boolean local = false; public VcsCacheFile(String memberOfCache) { super(memberOfCache, new VcsCacheFile.VcsPersistentData(false)); //System.out.println("new File with anonymous name."); //Thread.currentThread().dumpStack(); } public VcsCacheFile(String memberOfCache, String name) { super(memberOfCache, name, new VcsCacheFile.VcsPersistentData(false)); //System.out.println("new File '"+name+"'"); } public VcsCacheFile(String memberOfCache, String name, boolean local) { this(memberOfCache, name); setLocal(local); //System.out.println("new File '"+name+"', local = "+local); } VcsCacheFile(String memberOfCache, CacheFile.PersistentData data) { super(memberOfCache, data.getName(), data); //System.out.println("new File '"+data.getName()+"' FROM DATA"); } public void setLocal (boolean local) { ((VcsCacheFile.VcsPersistentData) getPersistentData()).setLocal(local); } public boolean isLocal () { return ((VcsCacheFile.VcsPersistentData) getPersistentData()).isLocal(); } public String getStatus() { CacheDir parent = getParent(); if (isLocal() && parent != null && parent.isIgnoreListSet() && parent.isIgnored(getName())) { return CacheStatuses.STATUS_IGNORED; } else return super.getStatus(); } protected void setParent(CacheDir par) { super.setParent(par); VcsCacheFile.VcsPersistentData vdata = (VcsCacheFile.VcsPersistentData) getPersistentData(); if (par != null) { vdata.setCacheFileName(((VcsCacheDir) par).getCacheFileName()); } else { vdata.setRemoved(true); } vdata.setModified(true); // I should be saved under my new parent } public static String readFileCacheName(String line, String cacheName, boolean[] isDir) { String[] elements = StatusFormat.getElementsFromLine(line); String name = elements[StatusFormat.ELEMENT_INDEX_FILE_NAME]; if (name == null) throw new IllegalArgumentException("File name element is missing."); // NOI18N isDir[0] = name.endsWith("/"); // NOI18N return (isDir[0]) ? name.substring(0, name.length()-1) : name; } public static CacheFile readFileCache(String line, String cacheName, java.io.File parent) { //VcsCacheFile file = new VcsCacheFile(cacheName); //System.out.println("VcsCacheFile.readFileCache("+line+", "+cacheName+", "+parent+")"); String[] elements = StatusFormat.getElementsFromLine(line); String name = elements[StatusFormat.ELEMENT_INDEX_FILE_NAME]; if (name == null) throw new IllegalArgumentException("File name element is missing."); // NOI18N boolean fileIsDir = name.endsWith("/"); // NOI18N String fileName = (fileIsDir) ? name.substring(0, name.length()-1) : name; VcsCache cache = (VcsCache) CacheHandler.getInstance().getCache(cacheName); CacheFile file = null; if (cache != null) { VcsCacheDir parentDir = (VcsCacheDir) cache.getDir(parent.getAbsolutePath()); if (parentDir != null) { file = parentDir.getChildIfExists(fileName); } } if (file == null) { if (fileIsDir) { file = new VcsCacheDir(cacheName, new java.io.File(parent, fileName)); } else { file = new VcsCacheFile(cacheName); } file.setName(fileName); } RefreshCommandSupport.matchToFile(elements, file); if (file instanceof VcsCacheFile) ((VcsCacheFile) file).setLocal(false); if (file instanceof VcsCacheDir) ((VcsCacheDir) file).setLocal(false); file.getPersistentData().setModified(false); //System.out.println("VcsCacheFile.readFileCache("+line+", "+cacheName+", "+parent+") = "+file); return file; } /* public String writeLineToDisk() { return RefreshCommandSupport.getLineFromElements(RefreshCommandSupport.makeElements(this)); /* StringBuffer buff = new StringBuffer("/"); buff.append(getName()); buff.append("/"); buff.append(getStatus()); buff.append("///"); //TODO - temporary //TODO return buff.toString(); * } */ public String toString(){ return "VcsFile["+ // NOI18N "name='"+getName()+"'"+ // NOI18N ",status="+getStatus()+ // NOI18N ",locker="+getLocker()+ // NOI18N ",revision="+getRevision()+ // NOI18N ",sticky="+getSticky()+ // NOI18N ",attr="+getAttr()+ // NOI18N ",size="+getSize()+ // NOI18N ",date="+getDate()+ // NOI18N ",time="+getTime()+ // NOI18N ",local="+isLocal()+ // NOI18N "]"; // NOI18N } /* TEST METHOD ONLY * protected void finalize() throws Throwable { System.out.println("File "+getName()+" FINALIZED"); } */ protected static class VcsPersistentData extends CacheFile.PersistentData { private File cacheFile = null; private boolean removed = false; private volatile boolean loaded = false; //private CacheFile.PersistentData parentData; private boolean errorLineReported = false; private Object errorLock = new Object(); public VcsPersistentData(boolean directory) { super(directory); //System.out.println("CREATED VcsPersistentData: "+this); } /** * Set the data as removed. The write process should then remove * this data from the disk cache. */ protected void setRemoved(boolean removed) { this.removed = removed; } protected final void setLoaded(boolean loaded) { this.loaded = loaded; } protected final boolean isLoaded() { return loaded; } void setCacheFileName(String cacheFileName) { this.cacheFile = (cacheFileName == null) ? null : new File(cacheFileName); } /** * If it's necessary to save the parent's data when I'm saved, set the * parent's data with this method. * It's recommended, that if this is directory data, parent directory * data should be set, so that the parent directory has correct content * in the disk cache. * void setParentData(CacheFile.PersistentData parentData) { this.parentData = parentData; } */ public String writeLineToDisk() { if (removed) return ""; String[] elements = RefreshCommandSupport.makeElements(this); if (isDirectory()) elements[StatusFormat.ELEMENT_INDEX_FILE_NAME] += "/"; // NOI18N return StatusFormat.getLineFromElements(elements); } /** * Subclasses need to implement this to store the data into disk cache. * This implementation stores not only this data, but also all it's siblings * for efficiency. */ protected void doWriteToDisk() throws IOException { // Do not store data, that do not have a cache file to be written into // or data, that were not loaded yet. if (cacheFile == null || (isDirectory() && !isLoaded())) return ; Object lock = getFileAccessLock(cacheFile); try { synchronized (lock) { //Just write the cache info for a file, no siblings information //is written here. // BufferedWriter out = null; try { File cacheDir = cacheFile.getParentFile(); if (!cacheDir.exists()) cacheDir.mkdirs(); cacheFile.createNewFile(); out = new BufferedWriter(new FileWriter(cacheFile)); if (isLocal()) { //System.out.println("VcsPersistentData: WRITE: "+data.writeLineToDisk()+"\n"+ // " Written data = "+data+"\n"+ // " INTO "+cacheFile); String line = writeLineToDisk(); if (line.length() > 0) { out.write(line); out.newLine(); } } setModified(false); out.flush(); } finally { if (out != null) out.close(); } } } finally { releaseFileAccessLock(cacheFile, lock); } } private void setUnmodified(Set siblings) { for (Iterator it = siblings.iterator(); it.hasNext(); ) { VcsPersistentData data = (VcsPersistentData) it.next(); data.setModified(false); } } private void doWriteToDisk(Set siblings, boolean canOverwrite) throws IOException { //System.err.println("VcsPersistentData("+cacheFile+").doWriteToDisk("+siblings.size()+", "+canOverwrite+")"); if (!canOverwrite) { addSiblingsFromDisk(siblings); //System.out.println("SIBLINGS AFTER ADD from disk: "+dumpSiblings(true, siblings)); } BufferedWriter out = null; try { File cacheDir = cacheFile.getParentFile(); if (!cacheDir.exists()) cacheDir.mkdirs(); cacheFile.createNewFile(); out = new BufferedWriter(new FileWriter(cacheFile)); for (Iterator it = siblings.iterator(); it.hasNext(); ) { VcsPersistentData data = (VcsPersistentData) it.next(); if (!data.isLocal()) { //System.err.println("VcsPersistentData: WRITE: "+data.writeLineToDisk()+"\n"+ // " Written data = "+data+"\n"+ // " INTO "+cacheFile); String line = data.writeLineToDisk(); if (line.length() > 0) { out.write(line); out.newLine(); } } else { //System.err.println("VcsPersistentData: NOT Written: "+data); } data.setModified(false); } out.flush(); } finally { if (out != null) out.close(); } //System.out.println("Write finished."); } private void addSiblingsFromDisk(Set siblings) throws IOException { Set siblingsNames = new HashSet(); for (Iterator it = siblings.iterator(); it.hasNext(); ) { CacheFile.PersistentData data = (CacheFile.PersistentData) it.next(); siblingsNames.add(data.getName()); } if (cacheFile.exists() && cacheFile.canRead()) { BufferedReader in = null; try { in = new BufferedReader(new FileReader(cacheFile)); String line = null; while ((line = in.readLine()) != null) { try { String[] elements = StatusFormat.getElementsFromLine(line); String fileName = elements[StatusFormat.ELEMENT_INDEX_FILE_NAME]; if (fileName == null) { synchronized (errorLock) { if (!errorLineReported) { ErrorManager.getDefault().notify(org.openide.ErrorManager.WARNING, ErrorManager.getDefault().annotate( new IllegalArgumentException("File name element is missing."), // NOI18N "Line read: '"+line+"' in file "+cacheFile)); // NOI18N errorLineReported = true; } } continue; } boolean isDir = fileName.endsWith("/"); if (isDir) fileName = fileName.substring(0, fileName.length() - 1); if (!siblingsNames.contains(fileName)) { VcsCacheFile.VcsPersistentData data = new VcsCacheFile.VcsPersistentData(isDir); data.setName(fileName); RefreshCommandSupport.matchToFile(elements, data); data.setModified(false); // I just read them, they should not be modified! siblings.add(data); siblingsNames.add(data.getName()); } } catch (IllegalArgumentException iaex) { synchronized (errorLock) { if (!errorLineReported) { ErrorManager.getDefault().notify(org.openide.ErrorManager.WARNING, ErrorManager.getDefault().annotate(iaex, "Line read: '"+line+"'")); } } } } in.close(); } catch (IOException e){ ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); } finally { if (in != null) { try { in.close(); } catch (IOException exc) {} } } } } private void doWriteToDiskSimple() throws IOException { Map dataMap = readExistingData(); dataMap.put(getName(), this); BufferedWriter out = null; try { File cacheDir = cacheFile.getParentFile(); if (!cacheDir.exists()) cacheDir.mkdirs(); cacheFile.createNewFile(); out = new BufferedWriter(new FileWriter(cacheFile)); for (Iterator it = dataMap.values().iterator(); it.hasNext(); ) { VcsPersistentData data = (VcsPersistentData) it.next(); if (!data.isLocal()) { //System.err.println("VcsPersistentData: WRITE: "+data.writeLineToDisk()+"\n"+ // " Written data = "+data+"\n"+ // " INTO "+cacheFile); String line = data.writeLineToDisk(); if (line.length() > 0) { out.write(line); out.newLine(); } } else { //System.err.println("VcsPersistentData: NOT Written: "+data); } data.setModified(false); } out.flush(); } finally { if (out != null) out.close(); } } private Map readExistingData() { Map datas = new HashMap(); if (cacheFile.exists() && cacheFile.canRead()) { BufferedReader in = null; try { in = new BufferedReader(new FileReader(cacheFile)); String line = null; while ((line = in.readLine()) != null) { try { String[] elements = StatusFormat.getElementsFromLine(line); String fileName = elements[StatusFormat.ELEMENT_INDEX_FILE_NAME]; if (fileName == null) { synchronized (errorLock) { if (!errorLineReported) { ErrorManager.getDefault().notify(org.openide.ErrorManager.WARNING, ErrorManager.getDefault().annotate( new IllegalArgumentException("File name element is missing."), // NOI18N "Line read: '"+line+"' in file "+cacheFile)); // NOI18N errorLineReported = true; } } continue; } boolean isDir = fileName.endsWith("/"); if (isDir) fileName = fileName.substring(0, fileName.length() - 1); VcsCacheFile.VcsPersistentData data = new VcsCacheFile.VcsPersistentData(isDir); data.setName(fileName); RefreshCommandSupport.matchToFile(elements, data); data.setModified(false); // I just read them, they should not be modified! datas.put(fileName, data); } catch (IllegalArgumentException iaex) { synchronized (errorLock) { if (!errorLineReported) { ErrorManager.getDefault().notify(org.openide.ErrorManager.WARNING, ErrorManager.getDefault().annotate(iaex, "Line read: '"+line+"'")); } } } } in.close(); } catch (IOException e){ ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); } finally { if (in != null) { try { in.close(); } catch (IOException exc) {} } } } return datas; } private static Map OPEN_FILES_LOCKS = new HashMap(); /** * Process an exlusive access to a disk file. * @param file The disk file to access * @run The runnable task, that performs the access. * static void processCacheFileAccess(File file, Runnable run) { MutableInt lock; synchronized (OPEN_FILES_LOCKS) { lock = (MutableInt) OPEN_FILES_LOCKS.get(file); if (lock == null) { lock = new MutableInt(); OPEN_FILES_LOCKS.put(file, lock); } lock.inc(); } try { synchronized (lock) { run.run(); } } finally { synchronized (OPEN_FILES_LOCKS) { lock.dec(); if (lock.get() == 0) { OPEN_FILES_LOCKS.remove(file); } } } } */ /** * Get an exlusive access to a disk file. releaseFileAccessLock() * must be called after the access is finished to release the lock. * @param file The disk file to access * @return The lock object, that can be used to synchronize the exlusive * access to the file. */ static Object getFileAccessLock(File file) { MutableInt lock; synchronized (OPEN_FILES_LOCKS) { lock = (MutableInt) OPEN_FILES_LOCKS.get(file); if (lock == null) { lock = new MutableInt(); OPEN_FILES_LOCKS.put(file, lock); } lock.inc(); //System.out.println("Lock ACQUIRED for file '"+file+"', "+lock); //System.err.println("Lock ACQUIRED for file '"+file+"', "+lock); } return lock; } /** * Release the exlusive access to a disk file. * @param file The disk file, that was accessed * @param lock The lock object obtained from getFileAccessLock(). */ static void releaseFileAccessLock(File file, Object lock) { if (!(lock instanceof MutableInt)) throw new IllegalArgumentException("Bad lock instance"); MutableInt miLock = (MutableInt) lock; synchronized (OPEN_FILES_LOCKS) { miLock.dec(); if (miLock.get() <= 0) { OPEN_FILES_LOCKS.remove(file); } //System.out.println("Lock RELEASED for file '"+file+"', "+lock); //System.err.println("Lock RELEASED for file '"+file+"', "+lock); } } private static final class MutableInt { private int i; public MutableInt() { i = 0; } public void set(int i) { this.i = i; } public int get() { return i; } public void inc() { i++; } public void dec() { i--; } public String toString() { return Integer.toString(i); } } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.