1 11 package org.eclipse.core.internal.localstore; 12 13 import java.io.*; 14 import org.eclipse.core.internal.localstore.Bucket.Visitor; 15 import org.eclipse.core.internal.resources.ResourceException; 16 import org.eclipse.core.internal.resources.Workspace; 17 import org.eclipse.core.internal.utils.Messages; 18 import org.eclipse.core.resources.IProject; 19 import org.eclipse.core.resources.IResourceStatus; 20 import org.eclipse.core.runtime.*; 21 import org.eclipse.osgi.util.NLS; 22 23 24 27 public class BucketTree { 28 public static final int DEPTH_INFINITE = Integer.MAX_VALUE; 29 public static final int DEPTH_ONE = 1; 30 public static final int DEPTH_ZERO = 0; 31 32 private final static int SEGMENT_QUOTA = 256; 34 37 private static final char[][] HEX_STRINGS; 38 39 static { 40 HEX_STRINGS = new char[SEGMENT_QUOTA][]; 41 for (int i = 0; i < HEX_STRINGS.length; i++) 42 HEX_STRINGS[i] = Integer.toHexString(i).toCharArray(); 43 } 44 45 protected Bucket current; 46 47 private Workspace workspace; 48 49 public BucketTree(Workspace workspace, Bucket bucket) { 50 this.current = bucket; 51 this.workspace = workspace; 52 } 53 54 60 public void accept(Bucket.Visitor visitor, IPath base, int depth) throws CoreException { 61 if (Path.ROOT.equals(base)) { 62 current.load(null, locationFor(Path.ROOT)); 63 if (current.accept(visitor, base, DEPTH_ZERO) != Visitor.CONTINUE) 64 return; 65 if (depth == DEPTH_ZERO) 66 return; 67 boolean keepVisiting = true; 68 depth--; 69 IProject[] projects = workspace.getRoot().getProjects(); 70 for (int i = 0; keepVisiting && i < projects.length; i++) { 71 IPath projectPath = projects[i].getFullPath(); 72 keepVisiting = internalAccept(visitor, projectPath, locationFor(projectPath), depth, 1); 73 } 74 } else 75 internalAccept(visitor, base, locationFor(base), depth, 0); 76 } 77 78 public void close() throws CoreException { 79 current.save(); 80 saveVersion(); 81 } 82 83 public Bucket getCurrent() { 84 return current; 85 } 86 87 public File getVersionFile() { 88 return new File(locationFor(Path.ROOT), current.getVersionFileName()); 89 } 90 91 96 private boolean internalAccept(Bucket.Visitor visitor, IPath base, File bucketDir, int depthRequested, int currentDepth) throws CoreException { 97 current.load(base.segment(0), bucketDir); 98 int outcome = current.accept(visitor, base, depthRequested); 99 if (outcome != Visitor.CONTINUE) 100 return outcome == Visitor.RETURN; 101 if (depthRequested <= currentDepth) 102 return true; 103 File[] subDirs = bucketDir.listFiles(); 104 if (subDirs == null) 105 return true; 106 for (int i = 0; i < subDirs.length; i++) 107 if (subDirs[i].isDirectory()) 108 if (!internalAccept(visitor, base, subDirs[i], depthRequested, currentDepth + 1)) 109 return false; 110 return true; 111 } 112 113 public void loadBucketFor(IPath path) throws CoreException { 114 current.load(Path.ROOT.equals(path) ? null : path.segment(0), locationFor(path)); 115 } 116 117 private File locationFor(IPath resourcePath) { 118 IPath baseLocation = workspace.getMetaArea().locationFor(resourcePath).removeTrailingSeparator(); 120 int segmentCount = resourcePath.segmentCount(); 121 String locationString = baseLocation.toOSString(); 122 StringBuffer locationBuffer = new StringBuffer (locationString.length() + Bucket.INDEXES_DIR_NAME.length() + 16); 123 locationBuffer.append(locationString); 124 locationBuffer.append(File.separatorChar); 125 locationBuffer.append(Bucket.INDEXES_DIR_NAME); 126 for (int i = 1; i < segmentCount - 1; i++) { 128 locationBuffer.append(File.separatorChar); 130 locationBuffer.append(translateSegment(resourcePath.segment(i))); 131 } 132 return new File(locationBuffer.toString()); 133 } 134 135 138 private void saveVersion() throws CoreException { 139 File versionFile = getVersionFile(); 140 if (!versionFile.getParentFile().exists()) 141 versionFile.getParentFile().mkdirs(); 142 FileOutputStream stream = null; 143 boolean failed = false; 144 try { 145 stream = new FileOutputStream(versionFile); 146 stream.write(current.getVersion()); 147 } catch (IOException e) { 148 failed = true; 149 String message = NLS.bind(Messages.resources_writeWorkspaceMeta, versionFile.getAbsolutePath()); 150 throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, null, message, e); 151 } finally { 152 try { 153 if (stream != null) 154 stream.close(); 155 } catch (IOException e) { 156 if (!failed) { 157 String message = NLS.bind(Messages.resources_writeWorkspaceMeta, versionFile.getAbsolutePath()); 158 throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, null, message, e); 159 } 160 } 161 } 162 } 163 164 private char[] translateSegment(String segment) { 165 return HEX_STRINGS[Math.abs(segment.hashCode()) % SEGMENT_QUOTA]; 167 } 168 } 169 | Popular Tags |