KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > localstore > BucketTree


1 /*******************************************************************************
2  * Copyright (c) 2004, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

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 /**
25  * @since 3,1
26  */

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; //two hex characters
33

34     /**
35      * Store all bucket names to avoid creating garbage when traversing the tree
36      */

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     /**
55      * From a starting point in the tree, visit all nodes under it.
56      * @param visitor
57      * @param base
58      * @param depth
59      */

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     /**
92      * This will never be called for a bucket for the workspace root.
93      *
94      * @return whether to continue visiting other branches
95      */

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         //optimized to avoid string and path creations
119
IPath baseLocation = workspace.getMetaArea().locationFor(resourcePath).removeTrailingSeparator();
120         int segmentCount = resourcePath.segmentCount();
121         String JavaDoc locationString = baseLocation.toOSString();
122         StringBuffer JavaDoc locationBuffer = new StringBuffer JavaDoc(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         // the last segment is ignored
127
for (int i = 1; i < segmentCount - 1; i++) {
128             // translate all segments except the first one (project name)
129
locationBuffer.append(File.separatorChar);
130             locationBuffer.append(translateSegment(resourcePath.segment(i)));
131         }
132         return new File(locationBuffer.toString());
133     }
134
135     /**
136      * Writes the version tag to a file on disk.
137      */

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 JavaDoc 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 JavaDoc 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 JavaDoc segment) {
165         // String.hashCode algorithm is API
166
return HEX_STRINGS[Math.abs(segment.hashCode()) % SEGMENT_QUOTA];
167     }
168 }
169
Popular Tags