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
.SystemReader
;
33 import org
.eclipse
.ui
.IActionBars
;
34 import org
.eclipse
.ui
.preferences
.ScopedPreferenceStore
;
35 import org
.eclipse
.ui
.views
.properties
.IPropertyDescriptor
;
36 import org
.eclipse
.ui
.views
.properties
.IPropertySource
;
37 import org
.eclipse
.ui
.views
.properties
.IPropertySource2
;
38 import org
.eclipse
.ui
.views
.properties
.PropertyDescriptor
;
39 import org
.eclipse
.ui
.views
.properties
.PropertySheetPage
;
40 import org
.eclipse
.ui
.views
.properties
.TextPropertyDescriptor
;
43 * Properties for repository configuration
46 public class RepositoryPropertySource
implements IPropertySource
,
49 private static final String USER_ID_PREFIX
= "user"; //$NON-NLS-1$
51 private static final String REPO_ID_PREFIX
= "repo"; //$NON-NLS-1$
53 private static final String EFFECTIVE_ID_PREFIX
= "effe"; //$NON-NLS-1$
55 private static final String PREFERENCE_KEYS
= "RepositoryPropertySource.ConfiguredKeys"; //$NON-NLS-1$
57 private Action configureKeyAction
;
59 private Action modeToggleAction
;
61 private Action restoreKeyAction
;
63 private final PropertySheetPage myPage
;
65 private final FileBasedConfig userHomeConfig
;
67 private final FileBasedConfig repositoryConfig
;
69 private final RepositoryConfig effectiveConfig
;
76 public RepositoryPropertySource(Repository rep
, PropertySheetPage page
) {
83 effectiveConfig
= rep
.getConfig();
84 userHomeConfig
= SystemReader
.getInstance().openUserConfig();
86 File configFile
= new File(rep
.getDirectory(), "config"); //$NON-NLS-1$
87 repositoryConfig
= new FileBasedConfig(configFile
);
90 effectiveConfig
.load();
91 userHomeConfig
.load();
92 repositoryConfig
.load();
93 } catch (IOException e
) {
94 showExceptionMessage(e
);
95 } catch (ConfigInvalidException e
) {
96 showExceptionMessage(e
);
100 private void makeActions() {
102 configureKeyAction
= new Action(
103 UIText
.RepositoryPropertySource_ConfigureKeysAction
) {
106 public String
getId() {
107 return "ConfigKeyActionId"; //$NON-NLS-1$
112 ConfigureKeysDialog dlg
= new ConfigureKeysDialog(myPage
113 .getSite().getShell(), getConfiguredKeys());
114 if (dlg
.open() == Window
.OK
)
116 setConfiguredKeys(dlg
.getActiveKeys());
118 } catch (IOException e
) {
119 showExceptionMessage(e
);
126 modeToggleAction
= new Action(
127 UIText
.RepositoryPropertySource_EffectiveConfigurationAction
) {
130 public String
getId() {
131 return "ViewModeToggle"; //$NON-NLS-1$
140 public int getStyle() {
141 return IAction
.AS_CHECK_BOX
;
146 restoreKeyAction
= new Action(
147 UIText
.RepositoryPropertySource_RestoreStandardAction
) {
150 public String
getId() {
151 return "RestoreKeys"; //$NON-NLS-1$
157 setConfiguredKeys(new ArrayList
<String
>());
159 } catch (IOException e
) {
160 showExceptionMessage(e
);
167 private void addActions() {
169 boolean refreshToolbar
= false;
170 IActionBars bars
= myPage
.getSite().getActionBars();
172 if (bars
.getToolBarManager().find(modeToggleAction
.getId()) == null) {
173 bars
.getToolBarManager().add(modeToggleAction
);
174 refreshToolbar
= true;
177 if (bars
.getMenuManager().find(configureKeyAction
.getId()) == null)
178 bars
.getMenuManager().add(configureKeyAction
);
180 if (bars
.getMenuManager().find(restoreKeyAction
.getId()) == null)
181 bars
.getMenuManager().add(restoreKeyAction
);
184 bars
.getToolBarManager().update(false);
187 private List
<String
> getConfiguredKeys() {
189 List
<String
> result
= new ArrayList
<String
>();
190 ScopedPreferenceStore store
= new ScopedPreferenceStore(
191 new InstanceScope(), Activator
.getPluginId());
192 String keys
= store
.getString(PREFERENCE_KEYS
);
193 if (keys
.length() > 0) {
194 StringTokenizer tok
= new StringTokenizer(keys
, " "); //$NON-NLS-1$
195 while (tok
.hasMoreTokens()) {
196 result
.add(tok
.nextToken());
199 result
.addAll(ConfigureKeysDialog
.standardKeys
);
204 private void setConfiguredKeys(List
<String
> keys
) throws IOException
{
206 StringBuilder sb
= new StringBuilder();
207 for (String key
: keys
) {
209 sb
.append(" "); //$NON-NLS-1$
211 ScopedPreferenceStore store
= new ScopedPreferenceStore(
212 new InstanceScope(), Activator
.getPluginId());
213 store
.putValue(PREFERENCE_KEYS
, sb
.toString());
218 private Object
getValueFromConfig(Config config
, String keyString
) {
220 StringTokenizer tok
= new StringTokenizer(keyString
, "."); //$NON-NLS-1$
226 String
[] valueList
= null;
227 if (tok
.countTokens() == 2) {
228 section
= tok
.nextToken();
230 name
= tok
.nextToken();
231 } else if (tok
.countTokens() == 3) {
232 section
= tok
.nextToken();
233 subsection
= tok
.nextToken();
234 name
= tok
.nextToken();
240 valueList
= config
.getStringList(section
, subsection
, name
);
242 if (valueList
== null || valueList
.length
== 0)
245 if (valueList
.length
== 1) {
249 StringBuilder sb
= new StringBuilder();
250 for (String value
: valueList
){
256 return sb
.toString();
260 public Object
getEditableValue() {
264 public IPropertyDescriptor
[] getPropertyDescriptors() {
269 userHomeConfig
.load();
270 repositoryConfig
.load();
271 effectiveConfig
.load();
272 } catch (IOException e
) {
273 showExceptionMessage(e
);
274 } catch (ConfigInvalidException e
) {
275 showExceptionMessage(e
);
278 List
<IPropertyDescriptor
> resultList
= new ArrayList
<IPropertyDescriptor
>();
280 List
<String
> configuredKeys
= getConfiguredKeys();
282 boolean effectiveMode
= false;
284 ActionContributionItem item
= (ActionContributionItem
) myPage
.getSite()
285 .getActionBars().getToolBarManager().find(
286 modeToggleAction
.getId());
288 effectiveMode
= ((Action
) item
.getAction()).isChecked();
292 for (String key
: configuredKeys
) {
294 for (String sub
: getSubSections(effectiveConfig
, key
)) {
295 PropertyDescriptor desc
= new PropertyDescriptor(
296 EFFECTIVE_ID_PREFIX
+ sub
, sub
);
299 .setCategory(UIText
.RepositoryPropertySource_EffectiveConfigurationCategory
);
300 resultList
.add(desc
);
306 String categoryString
= UIText
.RepositoryPropertySource_GlobalConfigurationCategory
307 + userHomeConfig
.getFile().getAbsolutePath();
308 for (String key
: configuredKeys
) {
310 // no remote configuration globally....
311 if (key
.startsWith(RepositoriesView
.REMOTE
+ ".")) //$NON-NLS-1$
314 for (String sub
: getSubSections(effectiveConfig
, key
)) {
315 TextPropertyDescriptor desc
= new TextPropertyDescriptor(
316 USER_ID_PREFIX
+ sub
, sub
);
317 desc
.setCategory(categoryString
);
318 resultList
.add(desc
);
321 categoryString
= UIText
.RepositoryPropertySource_RepositoryConfigurationCategory
322 + repositoryConfig
.getFile().getAbsolutePath();
324 boolean editable
= true;
326 for (String key
: configuredKeys
) {
328 // remote stuff is not configurable
329 editable
= !key
.startsWith("remote"); //$NON-NLS-1$
331 for (String sub
: getSubSections(effectiveConfig
, key
)) {
332 PropertyDescriptor desc
;
334 desc
= new TextPropertyDescriptor(REPO_ID_PREFIX
+ sub
,
337 desc
= new PropertyDescriptor(REPO_ID_PREFIX
+ sub
, sub
);
338 desc
.setCategory(categoryString
);
339 resultList
.add(desc
);
344 return resultList
.toArray(new IPropertyDescriptor
[0]);
347 private List
<String
> getSubSections(Config configuration
, String key
) {
349 List
<String
> result
= new ArrayList
<String
>();
351 if (key
.indexOf(".?.") < 0) { //$NON-NLS-1$
356 StringTokenizer stok
= new StringTokenizer(key
, "."); //$NON-NLS-1$
357 if (stok
.countTokens() == 3) {
358 String section
= stok
.nextToken();
359 String subsection
= stok
.nextToken();
360 String name
= stok
.nextToken();
361 if (subsection
.equals("?")) { //$NON-NLS-1$
362 Set
<String
> subs
= configuration
.getSubsections(section
);
363 for (String sub
: subs
)
364 result
.add(section
+ "." + sub
+ "." + name
); //$NON-NLS-1$ //$NON-NLS-2$
373 public Object
getPropertyValue(Object id
) {
374 String actId
= ((String
) id
);
376 if (actId
.startsWith(USER_ID_PREFIX
)) {
377 value
= getValueFromConfig(userHomeConfig
, actId
.substring(4));
378 } else if (actId
.startsWith(REPO_ID_PREFIX
)) {
379 value
= getValueFromConfig(repositoryConfig
, actId
.substring(4));
380 } else if (actId
.startsWith(EFFECTIVE_ID_PREFIX
)) {
381 value
= getValueFromConfig(effectiveConfig
, actId
.substring(4));
384 // the text editor needs this to work
385 return ""; //$NON-NLS-1$
390 public boolean isPropertySet(Object id
) {
391 String actId
= ((String
) id
);
393 if (actId
.startsWith(USER_ID_PREFIX
)) {
394 value
= getValueFromConfig(userHomeConfig
, actId
.substring(4));
395 } else if (actId
.startsWith(REPO_ID_PREFIX
)) {
396 value
= getValueFromConfig(repositoryConfig
, actId
.substring(4));
397 } else if (actId
.startsWith(EFFECTIVE_ID_PREFIX
)) {
398 value
= getValueFromConfig(effectiveConfig
, actId
.substring(4));
400 return value
!= null;
403 public void resetPropertyValue(Object id
) {
404 setPropertyValue(id
, null);
407 public void setPropertyValue(Object id
, Object value
) {
409 String actId
= (String
) id
;
411 if (actId
.startsWith(USER_ID_PREFIX
)) {
412 setConfigValue(userHomeConfig
, actId
.substring(4),
415 if (actId
.startsWith(REPO_ID_PREFIX
)) {
416 setConfigValue(repositoryConfig
, actId
.substring(4),
419 } catch (IOException e
) {
420 showExceptionMessage(e
);
425 public boolean isPropertyResettable(Object id
) {
426 return isPropertySet(id
);
429 private void setConfigValue(FileBasedConfig configuration
, String key
,
430 String value
) throws IOException
{
431 // we un-set empty strings, as the config API does not allow to
432 // distinguish this case
433 // (null is returned, even if the value is set to "", but in the
434 // effective configuration
435 // this results in shadowing of the base configured values
436 StringTokenizer tok
= new StringTokenizer(key
, "."); //$NON-NLS-1$
437 if (tok
.countTokens() == 2) {
438 if (value
== null || value
.length() == 0) {
439 configuration
.unset(tok
.nextToken(), null, tok
.nextToken());
441 configuration
.setString(tok
.nextToken(), null, tok
.nextToken(),
445 if (tok
.countTokens() == 3) {
446 if (value
== null || value
.length() == 0) {
447 configuration
.unset(tok
.nextToken(), tok
.nextToken(), tok
450 configuration
.setString(tok
.nextToken(), tok
.nextToken(), tok
451 .nextToken(), value
);
455 configuration
.save();
458 private void showExceptionMessage(Exception e
) {
459 org
.eclipse
.egit
.ui
.Activator
.handleError(UIText
.RepositoryPropertySource_ErrorHeader
, e
, true);