1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.team.core.variants;
15 
16 import org.eclipse.core.resources.IResource;
17 import org.eclipse.core.resources.IWorkspaceRunnable;
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.OperationCanceledException;
21 import org.eclipse.team.core.TeamException;
22 
23 /**
24  * The purpose of a <code>ResourceVariantByteStore</code> is to support the caching of
25  * the synchronization bytes for the resource variants that represent
26  * a resource line-up of interest such as a version, baseline or branch. The
27  * cache stores bytes in order to minimize the memory footprint of the tree. It is the
28  * responsibility of the client of this API to cache enough bytes to meaningfully identify
29  * a resource variant (and possibly create an {@link IResourceVariant} handle from them).
30  * <p>
31  * The bytes for a resource variant are accessed using the local <code>IResource</code> handle
32  * that corresponds to the resource variant (using the <code>getBytes</code> method).
33  * The potential children of a resource variant are also accessed
34  * by using the local handle that corresponds to the resource variant
35  * (using the <code>members</code> method).
36  *
37  * @since 3.0
38  */
39 public abstract class ResourceVariantByteStore {
40 
41 	/**
42 	 * Dispose of any cached sync bytes when this cache is no longer needed.
43 	 */
dispose()44 	public abstract void dispose();
45 
46 	/**
47 	 * Return the bytes for the variant corresponding the given local resource.
48 	 * A return value of <code>null</code> means that no bytes have been stored
49 	 * for the resource variant. It is up to the client to determine whether
50 	 * this means that the resource variant does not exist or that it has not been
51 	 * fetched or otherwise determined yet.
52 	 * @param resource the local resource
53 	 * @return the bytes that represent the resource's variant
54 	 * @throws TeamException if an error occurs
55 	 */
getBytes(IResource resource)56 	public abstract byte[] getBytes(IResource resource) throws TeamException;
57 
58 	/**
59 	 * Set the bytes for the variant corresponding the given local resource.
60 	 * The bytes should never be <code>null</code>. If it is known that the remote
61 	 * does not exist, <code>deleteBytes(IResource)</code> should be used instead.
62 	 * If the sync bytes for the remote are stale and should be removed,
63 	 * <code>flushBytes(IResouce, int)</code> should be called.
64 	 * @param resource the local resource
65 	 * @param bytes the bytes that represent the resource's variant
66 	 * @return <code>true</code> if the bytes changed
67 	 * @throws TeamException if an error occurs
68 	 */
setBytes(IResource resource, byte[] bytes)69 	public abstract boolean setBytes(IResource resource, byte[] bytes) throws TeamException;
70 
71 	/**
72 	 * Remove the bytes from the tree for the resource variants corresponding to the
73 	 * given local resource and its descendants to the given depth.
74 	 * After the bytes are removed, <code>getBytes(resource)</code> will
75 	 * return <code>null</code> for the affected resources.
76 	 * @param resource the local resource
77 	 * @param depth the depth of the operation (one of <code>IResource.DEPTH_ZERO</code>,
78 	 * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
79 	 * @return <code>true</code> if there were bytes present which were removed
80 	 * @throws TeamException if an error occurs
81 	 */
flushBytes(IResource resource, int depth)82 	public abstract boolean flushBytes(IResource resource, int depth) throws TeamException;
83 
84 	/**
85 	 * Method called to indicate that it is known that there is no variant associated
86 	 * with the local resource. Subclasses may handle this information in different ways.
87 	 * The <code>flush(IResource, int)</code> method should be used in the cases
88 	 * where a client wishes to remove bytes for other reason.
89 	 * @param resource the local resource
90 	 * @return <code>true</code> if this changes the bytes for the variant
91 	 */
deleteBytes(IResource resource)92 	public abstract boolean deleteBytes(IResource resource) throws TeamException;
93 
94 	/**
95 	 * Return the children of the given resource that have resource variants in this tree.
96 	 * @param resource the parent resource
97 	 * @return the members who have resource variants in this tree.
98 	 */
members(IResource resource)99 	public abstract IResource[] members(IResource resource) throws TeamException;
100 
101 	/**
102 	 * Helper method to compare two byte arrays for equality
103 	 * @param syncBytes1 the first byte array or <code>null</code>
104 	 * @param syncBytes2 the second byte array or <code>null</code>
105 	 * @return whether the two arrays are equal (i.e. same content)
106 	 */
equals(byte[] syncBytes1, byte[] syncBytes2)107 	protected boolean equals(byte[] syncBytes1, byte[] syncBytes2) {
108 		if (syncBytes1 == null) {
109 			return syncBytes2 == null;
110 		} else if (syncBytes2 == null) {
111 			return false;
112 		}
113 		if (syncBytes1.length != syncBytes2.length) return false;
114 		for (int i = 0; i < syncBytes1.length; i++) {
115 			if (syncBytes1[i] != syncBytes2[i]) return false;
116 		}
117 		return true;
118 	}
119 
120 	/**
121 	 * Run the given action which may contain multiple modifications
122 	 * to the byte store. By default, the action is run. Subclasses
123 	 * may override to obtain scheduling rules or batch deltas (if
124 	 * the byte store modifies workspace resources).
125 	 * @param root the root resource for all modifications
126 	 * @param runnable the action to perform
127 	 * @param monitor a progress monitor.
128 	 * @exception TeamException if the operation failed.
129 	 * @exception OperationCanceledException if the operation is canceled.
130 	 */
run(IResource root, IWorkspaceRunnable runnable, IProgressMonitor monitor)131 	public void run(IResource root, IWorkspaceRunnable runnable, IProgressMonitor monitor) throws TeamException {
132 		try {
133 			runnable.run(monitor);
134 		} catch (CoreException e) {
135 			throw TeamException.asTeamException(e);
136 		}
137 	}
138 }
139