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
.dialogs
.MessageDialog
;
27 import org
.eclipse
.jface
.window
.Window
;
28 import org
.eclipse
.jgit
.errors
.ConfigInvalidException
;
29 import org
.eclipse
.jgit
.lib
.Config
;
30 import org
.eclipse
.jgit
.lib
.FileBasedConfig
;
31 import org
.eclipse
.jgit
.lib
.Repository
;
32 import org
.eclipse
.jgit
.lib
.RepositoryConfig
;
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();
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 // TODO refactor to a method and react on exceptions
97 } catch (ConfigInvalidException e
) {
98 // TODO refactor to a method and react on exceptions
104 private void makeActions() {
106 configureKeyAction
= new Action(
107 UIText
.RepositoryPropertySource_ConfigureKeysAction
) {
110 public String
getId() {
111 return "ConfigKeyActionId"; //$NON-NLS-1$
116 ConfigureKeysDialog dlg
= new ConfigureKeysDialog(myPage
117 .getSite().getShell(), getConfiguredKeys());
118 if (dlg
.open() == Window
.OK
)
120 setConfiguredKeys(dlg
.getActiveKeys());
122 } catch (IOException e
) {
123 showExceptionMessage(e
);
130 modeToggleAction
= new Action(
131 UIText
.RepositoryPropertySource_EffectiveConfigurationAction
) {
134 public String
getId() {
135 return "ViewModeToggle"; //$NON-NLS-1$
144 public int getStyle() {
145 return IAction
.AS_CHECK_BOX
;
150 restoreKeyAction
= new Action(
151 UIText
.RepositoryPropertySource_RestoreStandardAction
) {
154 public String
getId() {
155 return "RestoreKeys"; //$NON-NLS-1$
161 setConfiguredKeys(new ArrayList
<String
>());
163 } catch (IOException e
) {
164 showExceptionMessage(e
);
171 private void addActions() {
173 boolean refreshToolbar
= false;
174 IActionBars bars
= myPage
.getSite().getActionBars();
176 if (bars
.getToolBarManager().find(modeToggleAction
.getId()) == null) {
177 bars
.getToolBarManager().add(modeToggleAction
);
178 refreshToolbar
= true;
181 if (bars
.getMenuManager().find(configureKeyAction
.getId()) == null)
182 bars
.getMenuManager().add(configureKeyAction
);
184 if (bars
.getMenuManager().find(restoreKeyAction
.getId()) == null)
185 bars
.getMenuManager().add(restoreKeyAction
);
188 bars
.getToolBarManager().update(false);
191 private List
<String
> getConfiguredKeys() {
193 List
<String
> result
= new ArrayList
<String
>();
194 ScopedPreferenceStore store
= new ScopedPreferenceStore(
195 new InstanceScope(), Activator
.getPluginId());
196 String keys
= store
.getString(PREFERENCE_KEYS
);
197 if (keys
.length() > 0) {
198 StringTokenizer tok
= new StringTokenizer(keys
, " "); //$NON-NLS-1$
199 while (tok
.hasMoreTokens()) {
200 result
.add(tok
.nextToken());
203 result
.addAll(ConfigureKeysDialog
.standardKeys
);
208 private void setConfiguredKeys(List
<String
> keys
) throws IOException
{
210 StringBuilder sb
= new StringBuilder();
211 for (String key
: keys
) {
213 sb
.append(" "); //$NON-NLS-1$
215 ScopedPreferenceStore store
= new ScopedPreferenceStore(
216 new InstanceScope(), Activator
.getPluginId());
217 store
.putValue(PREFERENCE_KEYS
, sb
.toString());
222 private Object
getValueFromConfig(Config config
, String keyString
) {
224 StringTokenizer tok
= new StringTokenizer(keyString
, "."); //$NON-NLS-1$
230 String
[] valueList
= null;
232 if (tok
.countTokens() == 2) {
233 section
= tok
.nextToken();
235 name
= tok
.nextToken();
236 } else if (tok
.countTokens() == 3) {
237 section
= tok
.nextToken();
238 subsection
= tok
.nextToken();
239 name
= tok
.nextToken();
245 value
= config
.getString(section
, subsection
, name
);
250 valueList
= config
.getStringList(section
, subsection
, name
);
252 if (valueList
== null || valueList
.length
== 0)
255 if (valueList
.length
== 1) {
263 public Object
getEditableValue() {
267 public IPropertyDescriptor
[] getPropertyDescriptors() {
272 userHomeConfig
.load();
273 repositoryConfig
.load();
274 effectiveConfig
.load();
275 } catch (IOException e
) {
276 showExceptionMessage(e
);
277 } catch (ConfigInvalidException e
) {
278 showExceptionMessage(e
);
281 List
<IPropertyDescriptor
> resultList
= new ArrayList
<IPropertyDescriptor
>();
283 List
<String
> configuredKeys
= getConfiguredKeys();
285 boolean effectiveMode
= false;
287 ActionContributionItem item
= (ActionContributionItem
) myPage
.getSite()
288 .getActionBars().getToolBarManager().find(
289 modeToggleAction
.getId());
291 effectiveMode
= ((Action
) item
.getAction()).isChecked();
295 for (String key
: configuredKeys
) {
297 for (String sub
: getSubSections(effectiveConfig
, key
)) {
298 PropertyDescriptor desc
= new PropertyDescriptor(
299 EFFECTIVE_ID_PREFIX
+ sub
, sub
);
302 .setCategory(UIText
.RepositoryPropertySource_EffectiveConfigurationCategory
);
303 resultList
.add(desc
);
309 String categoryString
= UIText
.RepositoryPropertySource_GlobalConfigurationCategory
310 + userHomeConfig
.getFile().getAbsolutePath();
311 for (String key
: configuredKeys
) {
313 // no remote configuration globally....
314 if (key
.startsWith(RepositoriesView
.REMOTE
+ ".")) //$NON-NLS-1$
317 for (String sub
: getSubSections(effectiveConfig
, key
)) {
318 TextPropertyDescriptor desc
= new TextPropertyDescriptor(
319 USER_ID_PREFIX
+ sub
, sub
);
320 desc
.setCategory(categoryString
);
321 resultList
.add(desc
);
324 categoryString
= UIText
.RepositoryPropertySource_RepositoryConfigurationCategory
325 + repositoryConfig
.getFile().getAbsolutePath();
326 for (String key
: configuredKeys
) {
328 for (String sub
: getSubSections(effectiveConfig
, key
)) {
329 TextPropertyDescriptor desc
= new TextPropertyDescriptor(
330 REPO_ID_PREFIX
+ sub
, sub
);
331 desc
.setCategory(categoryString
);
332 resultList
.add(desc
);
337 return resultList
.toArray(new IPropertyDescriptor
[0]);
340 private List
<String
> getSubSections(Config configuration
, String key
) {
342 List
<String
> result
= new ArrayList
<String
>();
344 if (key
.indexOf(".?.") < 0) { //$NON-NLS-1$
349 StringTokenizer stok
= new StringTokenizer(key
, "."); //$NON-NLS-1$
350 if (stok
.countTokens() == 3) {
351 String section
= stok
.nextToken();
352 String subsection
= stok
.nextToken();
353 String name
= stok
.nextToken();
354 if (subsection
.equals("?")) { //$NON-NLS-1$
355 Set
<String
> subs
= configuration
.getSubsections(section
);
356 for (String sub
: subs
)
357 result
.add(section
+ "." + sub
+ "." + name
); //$NON-NLS-1$ //$NON-NLS-2$
366 public Object
getPropertyValue(Object id
) {
367 String actId
= ((String
) id
);
369 if (actId
.startsWith(USER_ID_PREFIX
)) {
370 value
= getValueFromConfig(userHomeConfig
, actId
.substring(4));
371 } else if (actId
.startsWith(REPO_ID_PREFIX
)) {
372 value
= getValueFromConfig(repositoryConfig
, actId
.substring(4));
373 } else if (actId
.startsWith(EFFECTIVE_ID_PREFIX
)) {
374 value
= getValueFromConfig(effectiveConfig
, actId
.substring(4));
377 // the text editor needs this to work
378 return ""; //$NON-NLS-1$
383 public boolean isPropertySet(Object id
) {
384 String actId
= ((String
) id
);
386 if (actId
.startsWith(USER_ID_PREFIX
)) {
387 value
= getValueFromConfig(userHomeConfig
, actId
.substring(4));
388 } else if (actId
.startsWith(REPO_ID_PREFIX
)) {
389 value
= getValueFromConfig(repositoryConfig
, actId
.substring(4));
390 } else if (actId
.startsWith(EFFECTIVE_ID_PREFIX
)) {
391 value
= getValueFromConfig(effectiveConfig
, actId
.substring(4));
393 return value
!= null;
396 public void resetPropertyValue(Object id
) {
397 setPropertyValue(id
, null);
400 public void setPropertyValue(Object id
, Object value
) {
402 String actId
= (String
) id
;
404 if (actId
.startsWith(USER_ID_PREFIX
)) {
405 setConfigValue(userHomeConfig
, actId
.substring(4),
408 if (actId
.startsWith(REPO_ID_PREFIX
)) {
409 setConfigValue(repositoryConfig
, actId
.substring(4),
412 } catch (IOException e
) {
413 showExceptionMessage(e
);
418 public boolean isPropertyResettable(Object id
) {
419 return isPropertySet(id
);
422 private void setConfigValue(FileBasedConfig configuration
, String key
,
423 String value
) throws IOException
{
424 // we un-set empty strings, as the config API does not allow to
425 // distinguish this case
426 // (null is returned, even if the value is set to "", but in the
427 // effective configuration
428 // this results in shadowing of the base configured values
429 StringTokenizer tok
= new StringTokenizer(key
, "."); //$NON-NLS-1$
430 if (tok
.countTokens() == 2) {
431 if (value
== null || value
.length() == 0) {
432 configuration
.unset(tok
.nextToken(), null, tok
.nextToken());
434 configuration
.setString(tok
.nextToken(), null, tok
.nextToken(),
438 if (tok
.countTokens() == 3) {
439 if (value
== null || value
.length() == 0) {
440 configuration
.unset(tok
.nextToken(), tok
.nextToken(), tok
443 configuration
.setString(tok
.nextToken(), tok
.nextToken(), tok
444 .nextToken(), value
);
448 configuration
.save();
451 private void showExceptionMessage(Exception e
) {
452 MessageDialog
.openError(myPage
.getSite().getShell(),
453 UIText
.RepositoryPropertySource_ErrorHeader
, e
.getMessage());