1 /*******************************************************************************
2 * Copyright (c) 2010 SAP AG.
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
9 * Mathias Kinzler (SAP AG) - initial implementation
10 *******************************************************************************/
11 package org
.eclipse
.egit
.ui
.internal
.repository
;
14 import java
.io
.IOException
;
15 import java
.util
.ArrayList
;
16 import java
.util
.List
;
18 import java
.util
.StringTokenizer
;
20 import org
.eclipse
.core
.runtime
.preferences
.InstanceScope
;
21 import org
.eclipse
.egit
.core
.Activator
;
22 import org
.eclipse
.egit
.ui
.UIText
;
23 import org
.eclipse
.jface
.action
.Action
;
24 import org
.eclipse
.jface
.action
.ActionContributionItem
;
25 import org
.eclipse
.jface
.action
.IAction
;
26 import org
.eclipse
.jface
.window
.Window
;
27 import org
.eclipse
.jgit
.errors
.ConfigInvalidException
;
28 import org
.eclipse
.jgit
.lib
.Config
;
29 import org
.eclipse
.jgit
.lib
.FileBasedConfig
;
30 import org
.eclipse
.jgit
.lib
.Repository
;
31 import org
.eclipse
.jgit
.lib
.RepositoryConfig
;
32 import org
.eclipse
.jgit
.util
.FS
;
33 import org
.eclipse
.jgit
.util
.SystemReader
;
34 import org
.eclipse
.ui
.IActionBars
;
35 import org
.eclipse
.ui
.preferences
.ScopedPreferenceStore
;
36 import org
.eclipse
.ui
.views
.properties
.IPropertyDescriptor
;
37 import org
.eclipse
.ui
.views
.properties
.IPropertySource
;
38 import org
.eclipse
.ui
.views
.properties
.IPropertySource2
;
39 import org
.eclipse
.ui
.views
.properties
.PropertyDescriptor
;
40 import org
.eclipse
.ui
.views
.properties
.PropertySheetPage
;
41 import org
.eclipse
.ui
.views
.properties
.TextPropertyDescriptor
;
44 * Properties for repository configuration
47 public class RepositoryPropertySource
implements IPropertySource
,
50 private static final String USER_ID_PREFIX
= "user"; //$NON-NLS-1$
52 private static final String REPO_ID_PREFIX
= "repo"; //$NON-NLS-1$
54 private static final String EFFECTIVE_ID_PREFIX
= "effe"; //$NON-NLS-1$
56 private static final String PREFERENCE_KEYS
= "RepositoryPropertySource.ConfiguredKeys"; //$NON-NLS-1$
58 private Action configureKeyAction
;
60 private Action modeToggleAction
;
62 private Action restoreKeyAction
;
64 private final PropertySheetPage myPage
;
66 private final FileBasedConfig userHomeConfig
;
68 private final FileBasedConfig repositoryConfig
;
70 private final RepositoryConfig effectiveConfig
;
77 public RepositoryPropertySource(Repository rep
, PropertySheetPage page
) {
84 effectiveConfig
= rep
.getConfig();
85 userHomeConfig
= SystemReader
.getInstance().openUserConfig(FS
.DETECTED
);
87 File configFile
= new File(rep
.getDirectory(), "config"); //$NON-NLS-1$
88 repositoryConfig
= new FileBasedConfig(configFile
);
91 effectiveConfig
.load();
92 userHomeConfig
.load();
93 repositoryConfig
.load();
94 } catch (IOException e
) {
95 showExceptionMessage(e
);
96 } catch (ConfigInvalidException e
) {
97 showExceptionMessage(e
);
101 private void makeActions() {
103 configureKeyAction
= new Action(
104 UIText
.RepositoryPropertySource_ConfigureKeysAction
) {
107 public String
getId() {
108 return "ConfigKeyActionId"; //$NON-NLS-1$
113 ConfigureKeysDialog dlg
= new ConfigureKeysDialog(myPage
114 .getSite().getShell(), getConfiguredKeys());
115 if (dlg
.open() == Window
.OK
)
117 setConfiguredKeys(dlg
.getActiveKeys());
119 } catch (IOException e
) {
120 showExceptionMessage(e
);
127 modeToggleAction
= new Action(
128 UIText
.RepositoryPropertySource_EffectiveConfigurationAction
) {
131 public String
getId() {
132 return "ViewModeToggle"; //$NON-NLS-1$
141 public int getStyle() {
142 return IAction
.AS_CHECK_BOX
;
147 restoreKeyAction
= new Action(
148 UIText
.RepositoryPropertySource_RestoreStandardAction
) {
151 public String
getId() {
152 return "RestoreKeys"; //$NON-NLS-1$
158 setConfiguredKeys(new ArrayList
<String
>());
160 } catch (IOException e
) {
161 showExceptionMessage(e
);
168 private void addActions() {
170 boolean refreshToolbar
= false;
171 IActionBars bars
= myPage
.getSite().getActionBars();
173 if (bars
.getToolBarManager().find(modeToggleAction
.getId()) == null) {
174 bars
.getToolBarManager().add(modeToggleAction
);
175 refreshToolbar
= true;
178 if (bars
.getMenuManager().find(configureKeyAction
.getId()) == null)
179 bars
.getMenuManager().add(configureKeyAction
);
181 if (bars
.getMenuManager().find(restoreKeyAction
.getId()) == null)
182 bars
.getMenuManager().add(restoreKeyAction
);
185 bars
.getToolBarManager().update(false);
188 private List
<String
> getConfiguredKeys() {
190 List
<String
> result
= new ArrayList
<String
>();
191 ScopedPreferenceStore store
= new ScopedPreferenceStore(
192 new InstanceScope(), Activator
.getPluginId());
193 String keys
= store
.getString(PREFERENCE_KEYS
);
194 if (keys
.length() > 0) {
195 StringTokenizer tok
= new StringTokenizer(keys
, " "); //$NON-NLS-1$
196 while (tok
.hasMoreTokens()) {
197 result
.add(tok
.nextToken());
200 result
.addAll(ConfigureKeysDialog
.standardKeys
);
205 private void setConfiguredKeys(List
<String
> keys
) throws IOException
{
207 StringBuilder sb
= new StringBuilder();
208 for (String key
: keys
) {
210 sb
.append(" "); //$NON-NLS-1$
212 ScopedPreferenceStore store
= new ScopedPreferenceStore(
213 new InstanceScope(), Activator
.getPluginId());
214 store
.putValue(PREFERENCE_KEYS
, sb
.toString());
219 private Object
getValueFromConfig(Config config
, String keyString
) {
221 StringTokenizer tok
= new StringTokenizer(keyString
, "."); //$NON-NLS-1$
227 String
[] valueList
= null;
228 if (tok
.countTokens() == 2) {
229 section
= tok
.nextToken();
231 name
= tok
.nextToken();
232 } else if (tok
.countTokens() == 3) {
233 section
= tok
.nextToken();
234 subsection
= tok
.nextToken();
235 name
= tok
.nextToken();
241 valueList
= config
.getStringList(section
, subsection
, name
);
243 if (valueList
== null || valueList
.length
== 0)
246 if (valueList
.length
== 1) {
250 StringBuilder sb
= new StringBuilder();
251 for (String value
: valueList
){
257 return sb
.toString();
261 public Object
getEditableValue() {
265 public IPropertyDescriptor
[] getPropertyDescriptors() {
270 userHomeConfig
.load();
271 repositoryConfig
.load();
272 effectiveConfig
.load();
273 } catch (IOException e
) {
274 showExceptionMessage(e
);
275 } catch (ConfigInvalidException e
) {
276 showExceptionMessage(e
);
279 List
<IPropertyDescriptor
> resultList
= new ArrayList
<IPropertyDescriptor
>();
281 List
<String
> configuredKeys
= getConfiguredKeys();
283 boolean effectiveMode
= false;
285 ActionContributionItem item
= (ActionContributionItem
) myPage
.getSite()
286 .getActionBars().getToolBarManager().find(
287 modeToggleAction
.getId());
289 effectiveMode
= ((Action
) item
.getAction()).isChecked();
293 for (String key
: configuredKeys
) {
295 for (String sub
: getSubSections(effectiveConfig
, key
)) {
296 PropertyDescriptor desc
= new PropertyDescriptor(
297 EFFECTIVE_ID_PREFIX
+ sub
, sub
);
300 .setCategory(UIText
.RepositoryPropertySource_EffectiveConfigurationCategory
);
301 resultList
.add(desc
);
307 String categoryString
= UIText
.RepositoryPropertySource_GlobalConfigurationCategory
308 + userHomeConfig
.getFile().getAbsolutePath();
309 for (String key
: configuredKeys
) {
311 // no remote configuration globally....
312 if (key
.startsWith(RepositoriesView
.REMOTE
+ ".")) //$NON-NLS-1$
315 for (String sub
: getSubSections(effectiveConfig
, key
)) {
316 TextPropertyDescriptor desc
= new TextPropertyDescriptor(
317 USER_ID_PREFIX
+ sub
, sub
);
318 desc
.setCategory(categoryString
);
319 resultList
.add(desc
);
322 categoryString
= UIText
.RepositoryPropertySource_RepositoryConfigurationCategory
323 + repositoryConfig
.getFile().getAbsolutePath();
325 boolean editable
= true;
327 for (String key
: configuredKeys
) {
329 // remote stuff is not configurable
330 editable
= !key
.startsWith("remote"); //$NON-NLS-1$
332 for (String sub
: getSubSections(effectiveConfig
, key
)) {
333 PropertyDescriptor desc
;
335 desc
= new TextPropertyDescriptor(REPO_ID_PREFIX
+ sub
,
338 desc
= new PropertyDescriptor(REPO_ID_PREFIX
+ sub
, sub
);
339 desc
.setCategory(categoryString
);
340 resultList
.add(desc
);
345 return resultList
.toArray(new IPropertyDescriptor
[0]);
348 private List
<String
> getSubSections(Config configuration
, String key
) {
350 List
<String
> result
= new ArrayList
<String
>();
352 if (key
.indexOf(".?.") < 0) { //$NON-NLS-1$
357 StringTokenizer stok
= new StringTokenizer(key
, "."); //$NON-NLS-1$
358 if (stok
.countTokens() == 3) {
359 String section
= stok
.nextToken();
360 String subsection
= stok
.nextToken();
361 String name
= stok
.nextToken();
362 if (subsection
.equals("?")) { //$NON-NLS-1$
363 Set
<String
> subs
= configuration
.getSubsections(section
);
364 for (String sub
: subs
)
365 result
.add(section
+ "." + sub
+ "." + name
); //$NON-NLS-1$ //$NON-NLS-2$
374 public Object
getPropertyValue(Object id
) {
375 String actId
= ((String
) id
);
377 if (actId
.startsWith(USER_ID_PREFIX
)) {
378 value
= getValueFromConfig(userHomeConfig
, actId
.substring(4));
379 } else if (actId
.startsWith(REPO_ID_PREFIX
)) {
380 value
= getValueFromConfig(repositoryConfig
, actId
.substring(4));
381 } else if (actId
.startsWith(EFFECTIVE_ID_PREFIX
)) {
382 value
= getValueFromConfig(effectiveConfig
, actId
.substring(4));
385 // the text editor needs this to work
386 return ""; //$NON-NLS-1$
391 public boolean isPropertySet(Object id
) {
392 String actId
= ((String
) id
);
394 if (actId
.startsWith(USER_ID_PREFIX
)) {
395 value
= getValueFromConfig(userHomeConfig
, actId
.substring(4));
396 } else if (actId
.startsWith(REPO_ID_PREFIX
)) {
397 value
= getValueFromConfig(repositoryConfig
, actId
.substring(4));
398 } else if (actId
.startsWith(EFFECTIVE_ID_PREFIX
)) {
399 value
= getValueFromConfig(effectiveConfig
, actId
.substring(4));
401 return value
!= null;
404 public void resetPropertyValue(Object id
) {
405 setPropertyValue(id
, null);
408 public void setPropertyValue(Object id
, Object value
) {
410 String actId
= (String
) id
;
412 if (actId
.startsWith(USER_ID_PREFIX
)) {
413 setConfigValue(userHomeConfig
, actId
.substring(4),
416 if (actId
.startsWith(REPO_ID_PREFIX
)) {
417 setConfigValue(repositoryConfig
, actId
.substring(4),
420 } catch (IOException e
) {
421 showExceptionMessage(e
);
426 public boolean isPropertyResettable(Object id
) {
427 return isPropertySet(id
);
430 private void setConfigValue(FileBasedConfig configuration
, String key
,
431 String value
) throws IOException
{
432 // we un-set empty strings, as the config API does not allow to
433 // distinguish this case
434 // (null is returned, even if the value is set to "", but in the
435 // effective configuration
436 // this results in shadowing of the base configured values
437 StringTokenizer tok
= new StringTokenizer(key
, "."); //$NON-NLS-1$
438 if (tok
.countTokens() == 2) {
439 if (value
== null || value
.length() == 0) {
440 configuration
.unset(tok
.nextToken(), null, tok
.nextToken());
442 configuration
.setString(tok
.nextToken(), null, tok
.nextToken(),
446 if (tok
.countTokens() == 3) {
447 if (value
== null || value
.length() == 0) {
448 configuration
.unset(tok
.nextToken(), tok
.nextToken(), tok
451 configuration
.setString(tok
.nextToken(), tok
.nextToken(), tok
452 .nextToken(), value
);
456 configuration
.save();
459 private void showExceptionMessage(Exception e
) {
460 org
.eclipse
.egit
.ui
.Activator
.handleError(UIText
.RepositoryPropertySource_ErrorHeader
, e
, true);