1 /*******************************************************************************
2  * Copyright (c) 2005, 2015 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 
15 package org.eclipse.ui.internal.contexts;
16 
17 import java.util.ArrayList;
18 import java.util.List;
19 import org.eclipse.core.commands.contexts.Context;
20 import org.eclipse.core.commands.contexts.ContextManager;
21 import org.eclipse.core.runtime.IConfigurationElement;
22 import org.eclipse.core.runtime.IExtensionDelta;
23 import org.eclipse.core.runtime.IExtensionRegistry;
24 import org.eclipse.core.runtime.IRegistryChangeEvent;
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.core.runtime.Platform;
27 import org.eclipse.ui.PlatformUI;
28 import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
29 import org.eclipse.ui.internal.services.RegistryPersistence;
30 
31 /**
32  * <p>
33  * A static class for accessing the registry.
34  * </p>
35  *
36  * @since 3.1
37  */
38 public final class ContextPersistence extends RegistryPersistence {
39 
40 	/**
41 	 * The index of the context elements in the indexed array.
42 	 *
43 	 * @see ContextPersistence#read()
44 	 */
45 	private static final int INDEX_CONTEXT_DEFINITIONS = 0;
46 
47 	/**
48 	 * Reads all of the command definitions from the commands extension point.
49 	 *
50 	 * @param configurationElements     The configuration elements in the commands
51 	 *                                  extension point; must not be
52 	 *                                  <code>null</code>, but may be empty.
53 	 * @param configurationElementCount The number of configuration elements that
54 	 *                                  are really in the array.
55 	 * @param contextManager            The context manager to which the commands
56 	 *                                  should be added; must not be
57 	 *                                  <code>null</code>.
58 	 */
readContextsFromRegistry(final IConfigurationElement[] configurationElements, final int configurationElementCount, final ContextManager contextManager)59 	private static void readContextsFromRegistry(final IConfigurationElement[] configurationElements,
60 			final int configurationElementCount, final ContextManager contextManager) {
61 		final List<IStatus> warningsToLog = new ArrayList<>(1);
62 
63 		for (int i = 0; i < configurationElementCount; i++) {
64 			final IConfigurationElement configurationElement = configurationElements[i];
65 
66 			// Read out the command identifier.
67 			final String contextId = readRequired(configurationElement, ATT_ID, warningsToLog, "Contexts need an id"); //$NON-NLS-1$
68 			if (contextId == null) {
69 				continue;
70 			}
71 
72 			// Read out the name.
73 			final String name = readRequired(configurationElement, ATT_NAME, warningsToLog, "Contexts need a name", //$NON-NLS-1$
74 					contextId);
75 			if (name == null) {
76 				continue;
77 			}
78 
79 			// Read out the description.
80 			final String description = readOptional(configurationElement, ATT_DESCRIPTION);
81 
82 			// Read out the parent id.
83 			String parentId = configurationElement.getAttribute(ATT_PARENT_ID);
84 			if ((parentId == null) || (parentId.length() == 0)) {
85 				parentId = configurationElement.getAttribute(ATT_PARENT);
86 				if ((parentId == null) || (parentId.length() == 0)) {
87 					parentId = configurationElement.getAttribute(ATT_PARENT_SCOPE);
88 				}
89 			}
90 			if ((parentId != null) && (parentId.length() == 0)) {
91 				parentId = null;
92 			}
93 
94 			final Context context = contextManager.getContext(contextId);
95 			if (!context.isDefined()) {
96 				context.define(name, description, parentId);
97 			}
98 		}
99 
100 		logWarnings(warningsToLog,
101 				"Warnings while parsing the contexts from the 'org.eclipse.ui.contexts', 'org.eclipse.ui.commands' and 'org.eclipse.ui.acceleratorScopes' extension points."); //$NON-NLS-1$
102 	}
103 
104 	/**
105 	 * The context manager for this instance; must not be <code>null</code>.
106 	 */
107 	private final ContextManager contextManager;
108 
109 	/**
110 	 * Constructs a new instance of <code>ContextPersistence</code>.
111 	 */
ContextPersistence(final ContextManager contextManager)112 	public ContextPersistence(final ContextManager contextManager) {
113 		if (contextManager == null) {
114 			throw new NullPointerException("The context manager must not be null"); //$NON-NLS-1$
115 		}
116 		this.contextManager = contextManager;
117 	}
118 
119 	@Override
isChangeImportant(final IRegistryChangeEvent event)120 	protected boolean isChangeImportant(final IRegistryChangeEvent event) {
121 		final IExtensionDelta[] acceleratorScopeDeltas = event.getExtensionDeltas(PlatformUI.PLUGIN_ID,
122 				IWorkbenchRegistryConstants.PL_ACCELERATOR_SCOPES);
123 		if (acceleratorScopeDeltas.length == 0) {
124 			final IExtensionDelta[] contextDeltas = event.getExtensionDeltas(PlatformUI.PLUGIN_ID,
125 					IWorkbenchRegistryConstants.PL_CONTEXTS);
126 			if (contextDeltas.length == 0) {
127 				final IExtensionDelta[] commandDeltas = event.getExtensionDeltas(PlatformUI.PLUGIN_ID,
128 						IWorkbenchRegistryConstants.PL_COMMANDS);
129 				if (commandDeltas.length == 0) {
130 					return false;
131 				}
132 			}
133 		}
134 
135 		return true;
136 	}
137 
138 	/**
139 	 * Reads all of the contexts from the registry,
140 	 *
141 	 * @param contextManager The context manager which should be populated with the
142 	 *                       values from the registry; must not be
143 	 *                       <code>null</code>.
144 	 */
145 	@Override
read()146 	protected void read() {
147 		super.read();
148 		reRead();
149 	}
150 
reRead()151 	public void reRead() {
152 
153 		// Create the extension registry mementos.
154 		final IExtensionRegistry registry = Platform.getExtensionRegistry();
155 		int contextDefinitionCount = 0;
156 		final IConfigurationElement[][] indexedConfigurationElements = new IConfigurationElement[1][];
157 
158 		/*
159 		 * Retrieve the accelerator scopes from the accelerator scopes extension point.
160 		 */
161 		final IConfigurationElement[] acceleratorScopesExtensionPoint = registry
162 				.getConfigurationElementsFor(EXTENSION_ACCELERATOR_SCOPES);
163 		for (final IConfigurationElement configurationElement : acceleratorScopesExtensionPoint) {
164 			final String name = configurationElement.getName();
165 
166 			// Check if it is a binding definition.
167 			if (TAG_ACCELERATOR_SCOPE.equals(name)) {
168 				addElementToIndexedArray(configurationElement, indexedConfigurationElements, INDEX_CONTEXT_DEFINITIONS,
169 						contextDefinitionCount++);
170 			}
171 		}
172 
173 		/*
174 		 * Retrieve the deprecated scopes and contexts from the commands extension
175 		 * point.
176 		 */
177 		final IConfigurationElement[] commandsExtensionPoint = registry.getConfigurationElementsFor(EXTENSION_COMMANDS);
178 		for (final IConfigurationElement configurationElement : commandsExtensionPoint) {
179 			final String name = configurationElement.getName();
180 
181 			// Check if it is a binding definition.
182 			if (TAG_SCOPE.equals(name)) {
183 				addElementToIndexedArray(configurationElement, indexedConfigurationElements, INDEX_CONTEXT_DEFINITIONS,
184 						contextDefinitionCount++);
185 			} else if (TAG_CONTEXT.equals(name)) {
186 				addElementToIndexedArray(configurationElement, indexedConfigurationElements, INDEX_CONTEXT_DEFINITIONS,
187 						contextDefinitionCount++);
188 
189 			}
190 		}
191 
192 		/*
193 		 * Retrieve the contexts from the contexts extension point.
194 		 */
195 		final IConfigurationElement[] contextsExtensionPoint = registry.getConfigurationElementsFor(EXTENSION_CONTEXTS);
196 		for (final IConfigurationElement configurationElement : contextsExtensionPoint) {
197 			final String name = configurationElement.getName();
198 
199 			// Check if it is a binding definition.
200 			if (TAG_CONTEXT.equals(name)) {
201 				addElementToIndexedArray(configurationElement, indexedConfigurationElements, INDEX_CONTEXT_DEFINITIONS,
202 						contextDefinitionCount++);
203 			}
204 		}
205 
206 		readContextsFromRegistry(indexedConfigurationElements[INDEX_CONTEXT_DEFINITIONS], contextDefinitionCount,
207 				contextManager);
208 	}
209 
210 }
211