Skip to main content
summaryrefslogtreecommitdiffstats
blob: 8c976513905780af3aca9c1a1a1333087e08254a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.help.internal.search;

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.*;
import org.eclipse.help.internal.base.util.*;
import org.osgi.framework.*;

/**
 * Table of plugins. Records all plugins, their version, corresponding fragments
 * versions The values are String in format:
 * pluginID\npluginVersion\nfragment1ID\nfragment1Version\nfragment2ID\nfragment2Version
 */
public class PluginVersionInfo extends HelpProperties {
	private static final long serialVersionUID = 1L;

	// Separates plugins and versions in value strings
	protected static final String SEPARATOR = "\n"; //$NON-NLS-1$

	File dir;

	boolean doComparison = true;

	boolean hasChanged = false;

	boolean ignoreSavedVersions;

	Collection<String> added = new ArrayList<>();

	Collection<String> removed = new ArrayList<>();

	/**
	 * Creates table of current contributing plugins and their fragments with
	 * versions.
	 *
	 * @param name
	 *            the name of the file to serialize the data to
	 * @param docBundleIds
	 *            Collection of String
	 * @param dir
	 *            location to store the data
	 * @param ignoreSavedVersions
	 *            if true, will cause detect change to ignore saved plugin
	 *            version and behave like there was nothing saved
	 */
	public PluginVersionInfo(String name, Collection<String> docBundleIds, File dir,
			boolean ignoreSavedVersions) {
		super(name, dir);
		this.dir = dir;
		this.ignoreSavedVersions = ignoreSavedVersions;
		createTable(docBundleIds);
	}

	protected void createTable(Collection<String> docBundleIds) {
		// create table of current contributions
		for (Iterator<String> it = docBundleIds.iterator(); it.hasNext();) {
			String bundleId = it.next();
			Bundle pluginBundle = Platform.getBundle(bundleId);
			if (pluginBundle == null) {
				continue;
			}
			StringBuffer pluginVersionAndFragments = new StringBuffer();
			appendBundleInformation(pluginVersionAndFragments, bundleId,
					pluginBundle.getHeaders().get(
							Constants.BUNDLE_VERSION));
			Bundle[] fragmentBundles = Platform.getFragments(pluginBundle);
			if (fragmentBundles != null) {
				for (int f = 0; f < fragmentBundles.length; f++) {
					if (fragmentBundles[f].getState() == Bundle.INSTALLED
							|| fragmentBundles[f].getState() == Bundle.UNINSTALLED)
						continue;
					appendBundleInformation(pluginVersionAndFragments,
							fragmentBundles[f].getSymbolicName(),
							fragmentBundles[f].getHeaders().get(
									Constants.BUNDLE_VERSION));
				}
			}
			this.put(bundleId, pluginVersionAndFragments.toString());
		}
	}

	protected void appendBundleInformation(StringBuffer buffer, String id,
			String version) {
		if (buffer.length()>0)
			buffer.append(SEPARATOR);
		buffer.append(id);
		buffer.append(SEPARATOR);
		buffer.append(version);
	}

	/**
	 * Detects changes in contributions or their version since last time the
	 * contribution table was saved.
	 *
	 * @return true if contributions have changed
	 */
	public boolean detectChange() {
		if (!doComparison)
			return hasChanged;
		// Create table of contributions present before last save()
		HelpProperties oldContrs = new HelpProperties(this.name, dir);
		if (!ignoreSavedVersions) {
			oldContrs.restore();
		}
		// check if contributions changed
		hasChanged = false;
		for (Enumeration<Object> keysEnum = this.keys(); keysEnum.hasMoreElements();) {
			String oneContr = (String) keysEnum.nextElement();
			if (!oldContrs.containsKey(oneContr)) {
				// plugin has been added
				added.add(oneContr);
			} else {
				String versions = (String) this.get(oneContr);
				String oldVersions = (String) oldContrs.get(oneContr);
				if (!compare(versions, oldVersions)) {
					// plugin version changed or fragments changed
					added.add(oneContr);
					removed.add(oneContr);
				}
			}
		}
		for (Enumeration<?> keysEnum = oldContrs.keys(); keysEnum
				.hasMoreElements();) {
			String oneContr = (String) keysEnum.nextElement();
			if (!this.containsKey(oneContr)) {
				// plugin has been removed
				removed.add(oneContr);
			}
		}
		hasChanged = added.size() > 0 || removed.size() > 0;
		doComparison = false;
		return hasChanged;
	}

	/**
	 * @return String - Collection of IDs of contributions that were added or
	 *         upgraded
	 */
	public Collection<String> getAdded() {
		if (doComparison)
			detectChange();
		return added;
	}

	/**
	 * @return String - Collection of IDs of contributions that were removed or
	 *         upgraded
	 */
	public Collection<String> getRemoved() {
		if (doComparison)
			detectChange();
		return removed;
	}

	/**
	 * Saves contributions to a file. After this method is called, calls to
	 * detectChange() will return false.
	 *
	 * @return true if operation was successful
	 */
	@Override
	public boolean save() {
		if (super.save()) {
			doComparison = false;
			hasChanged = false;
			ignoreSavedVersions = false;
			added = new ArrayList<>();
			removed = new ArrayList<>();
			return true;
		}
		return false;
	}

	/**
	 * Compares plugins and versions represented as a string for equality String
	 * have form id1\nverison1\nid2\nversion2 String are equal of they contain
	 * the same set of IDs and their corresponding version equal
	 *
	 * @return true if plugins and versions match
	 */
	private boolean compare(String versions, String oldVersions) {
		Map<String, String> versionMap = new HashMap<>();
		for (StringTokenizer t = new StringTokenizer(versions, SEPARATOR, false); t
				.hasMoreTokens();) {
			String pluginOrFragment = t.nextToken();
			if (t.hasMoreTokens()) {
				versionMap.put(pluginOrFragment, t.nextToken());
			}
		}
		Map<String, String> oldVersionMap = new HashMap<>();
		for (StringTokenizer t = new StringTokenizer(oldVersions, SEPARATOR,
				false); t.hasMoreTokens();) {
			String pluginOrFragment = t.nextToken();
			if (t.hasMoreTokens()) {
				oldVersionMap.put(pluginOrFragment, t.nextToken());
			}
		}
		return versionMap.equals(oldVersionMap);
	}
}

Back to the top