import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jgit.errors.ConfigInvalidException;
* This state is copy-on-write. It should always contain an immutable list
* of the configuration keys/values.
*/
- private final AtomicReference<State> state;
+ private final AtomicReference<ConfigSnapshot> state;
private final Config baseConfig;
*/
public Config(Config defaultConfig) {
baseConfig = defaultConfig;
- state = new AtomicReference<State>(newState());
+ state = new AtomicReference<ConfigSnapshot>(newState());
}
/**
*/
@SuppressWarnings("unchecked")
public <T> T get(final SectionParser<T> parser) {
- final State myState = getState();
+ final ConfigSnapshot myState = getState();
T obj = (T) myState.cache.get(parser);
if (obj == null) {
obj = parser.parse(this);
private List<String> getRawStringList(final String section,
final String subsection, final String name) {
List<String> r = null;
- for (final Entry e : state.get().entryList) {
+ for (final ConfigLine e : state.get().entryList) {
if (e.match(section, subsection, name))
r = add(r, e.value);
}
return curr;
}
- private State getState() {
- State cur, upd;
+ private ConfigSnapshot getState() {
+ ConfigSnapshot cur, upd;
do {
cur = state.get();
- final State base = getBaseState();
+ final ConfigSnapshot base = getBaseState();
if (cur.baseState == base)
return cur;
- upd = new State(cur.entryList, base);
+ upd = new ConfigSnapshot(cur.entryList, base);
} while (!state.compareAndSet(cur, upd));
return upd;
}
- private State getBaseState() {
+ private ConfigSnapshot getBaseState() {
return baseConfig != null ? baseConfig.getState() : null;
}
* optional subsection value, e.g. a branch name
*/
public void unsetSection(String section, String subsection) {
- State src, res;
+ ConfigSnapshot src, res;
do {
src = state.get();
res = unsetSection(src, section, subsection);
} while (!state.compareAndSet(src, res));
}
- private State unsetSection(final State srcState, final String section,
+ private ConfigSnapshot unsetSection(final ConfigSnapshot srcState,
+ final String section,
final String subsection) {
final int max = srcState.entryList.size();
- final ArrayList<Entry> r = new ArrayList<Entry>(max);
+ final ArrayList<ConfigLine> r = new ArrayList<ConfigLine>(max);
boolean lastWasMatch = false;
- for (Entry e : srcState.entryList) {
+ for (ConfigLine e : srcState.entryList) {
if (e.match(section, subsection)) {
// Skip this record, it's for the section we are removing.
lastWasMatch = true;
*/
public void setStringList(final String section, final String subsection,
final String name, final List<String> values) {
- State src, res;
+ ConfigSnapshot src, res;
do {
src = state.get();
res = replaceStringList(src, section, subsection, name, values);
fireConfigChangedEvent();
}
- private State replaceStringList(final State srcState,
+ private ConfigSnapshot replaceStringList(final ConfigSnapshot srcState,
final String section, final String subsection, final String name,
final List<String> values) {
- final List<Entry> entries = copy(srcState, values);
+ final List<ConfigLine> entries = copy(srcState, values);
int entryIndex = 0;
int valueIndex = 0;
int insertPosition = -1;
// Reset the first n Entry objects that match this input name.
//
while (entryIndex < entries.size() && valueIndex < values.size()) {
- final Entry e = entries.get(entryIndex);
+ final ConfigLine e = entries.get(entryIndex);
if (e.match(section, subsection, name)) {
entries.set(entryIndex, e.forValue(values.get(valueIndex++)));
insertPosition = entryIndex + 1;
//
if (valueIndex == values.size() && entryIndex < entries.size()) {
while (entryIndex < entries.size()) {
- final Entry e = entries.get(entryIndex++);
+ final ConfigLine e = entries.get(entryIndex++);
if (e.match(section, subsection, name))
entries.remove(--entryIndex);
}
// We didn't find any matching section header for this key,
// so we must create a new section header at the end.
//
- final Entry e = new Entry();
+ final ConfigLine e = new ConfigLine();
e.section = section;
e.subsection = subsection;
entries.add(e);
insertPosition = entries.size();
}
while (valueIndex < values.size()) {
- final Entry e = new Entry();
+ final ConfigLine e = new ConfigLine();
e.section = section;
e.subsection = subsection;
e.name = name;
return newState(entries);
}
- private static List<Entry> copy(final State src, final List<String> values) {
+ private static List<ConfigLine> copy(final ConfigSnapshot src,
+ final List<String> values) {
// At worst we need to insert 1 line for each value, plus 1 line
// for a new section header. Assume that and allocate the space.
//
final int max = src.entryList.size() + values.size() + 1;
- final ArrayList<Entry> r = new ArrayList<Entry>(max);
+ final ArrayList<ConfigLine> r = new ArrayList<ConfigLine>(max);
r.addAll(src.entryList);
return r;
}
- private static int findSectionEnd(final List<Entry> entries,
+ private static int findSectionEnd(final List<ConfigLine> entries,
final String section, final String subsection) {
for (int i = 0; i < entries.size(); i++) {
- Entry e = entries.get(i);
+ ConfigLine e = entries.get(i);
if (e.match(section, subsection, null)) {
i++;
while (i < entries.size()) {
*/
public String toText() {
final StringBuilder out = new StringBuilder();
- for (final Entry e : state.get().entryList) {
+ for (final ConfigLine e : state.get().entryList) {
if (e.prefix != null)
out.append(e.prefix);
if (e.section != null && e.name == null) {
* made to {@code this}.
*/
public void fromText(final String text) throws ConfigInvalidException {
- final List<Entry> newEntries = new ArrayList<Entry>();
+ final List<ConfigLine> newEntries = new ArrayList<ConfigLine>();
final StringReader in = new StringReader(text);
- Entry last = null;
- Entry e = new Entry();
+ ConfigLine last = null;
+ ConfigLine e = new ConfigLine();
for (;;) {
int input = in.read();
if (-1 == input)
newEntries.add(e);
if (e.section != null)
last = e;
- e = new Entry();
+ e = new ConfigLine();
} else if (e.suffix != null) {
// Everything up until the end-of-line is in the suffix.
state.set(newState(newEntries));
}
- private State newState() {
- return new State(Collections.<Entry> emptyList(), getBaseState());
+ private ConfigSnapshot newState() {
+ return new ConfigSnapshot(Collections.<ConfigLine> emptyList(),
+ getBaseState());
}
- private State newState(final List<Entry> entries) {
- return new State(Collections.unmodifiableList(entries), getBaseState());
+ private ConfigSnapshot newState(final List<ConfigLine> entries) {
+ return new ConfigSnapshot(Collections.unmodifiableList(entries),
+ getBaseState());
}
/**
public Set<String> parse(Config cfg) {
final Set<String> result = new LinkedHashSet<String>();
while (cfg != null) {
- for (final Entry e : cfg.state.get().entryList) {
+ for (final ConfigLine e : cfg.state.get().entryList) {
if (e.subsection != null && e.name == null
&& StringUtils.equalsIgnoreCase(section, e.section))
result.add(e.subsection);
public Set<String> parse(Config cfg) {
final Map<String, String> m = new LinkedHashMap<String, String>();
while (cfg != null) {
- for (final Entry e : cfg.state.get().entryList) {
+ for (final ConfigLine e : cfg.state.get().entryList) {
if (e.name == null)
continue;
if (!StringUtils.equalsIgnoreCase(section, e.section))
public Set<String> parse(Config cfg) {
final Map<String, String> m = new LinkedHashMap<String, String>();
while (cfg != null) {
- for (final Entry e : cfg.state.get().entryList) {
+ for (final ConfigLine e : cfg.state.get().entryList) {
if (e.section != null) {
String lc = StringUtils.toLowerCase(e.section);
if (!m.containsKey(lc))
}
}
- private static class State {
- final List<Entry> entryList;
-
- final Map<Object, Object> cache;
-
- final State baseState;
-
- State(List<Entry> entries, State base) {
- entryList = entries;
- cache = new ConcurrentHashMap<Object, Object>(16, 0.75f, 1);
- baseState = base;
- }
- }
-
- /**
- * The configuration file entry
- */
- private static class Entry {
-
- /**
- * The text content before entry
- */
- String prefix;
-
- /**
- * The section name for the entry
- */
- String section;
-
- /**
- * Subsection name
- */
- String subsection;
-
- /**
- * The key name
- */
- String name;
-
- /**
- * The value
- */
- String value;
-
- /**
- * The text content after entry
- */
- String suffix;
-
- Entry forValue(final String newValue) {
- final Entry e = new Entry();
- e.prefix = prefix;
- e.section = section;
- e.subsection = subsection;
- e.name = name;
- e.value = newValue;
- e.suffix = suffix;
- return e;
- }
-
- boolean match(final String aSection, final String aSubsection,
- final String aKey) {
- return eqIgnoreCase(section, aSection)
- && eqSameCase(subsection, aSubsection)
- && eqIgnoreCase(name, aKey);
- }
-
- boolean match(final String aSection, final String aSubsection) {
- return eqIgnoreCase(section, aSection)
- && eqSameCase(subsection, aSubsection);
- }
-
- private static boolean eqIgnoreCase(final String a, final String b) {
- if (a == null && b == null)
- return true;
- if (a == null || b == null)
- return false;
- return StringUtils.equalsIgnoreCase(a, b);
- }
-
- private static boolean eqSameCase(final String a, final String b) {
- if (a == null && b == null)
- return true;
- if (a == null || b == null)
- return false;
- return a.equals(b);
- }
-
- @Override
- public String toString() {
- if (section == null)
- return "<empty>";
- StringBuilder b = new StringBuilder(section);
- if (subsection != null)
- b.append(".").append(subsection);
- if (name != null)
- b.append(".").append(name);
- if (value != null)
- b.append("=").append(value);
- return b.toString();
- }
- }
-
private static class StringReader {
private final char[] buf;
--- /dev/null
+/*
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
+ * Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2008-2010, Google Inc.
+ * Copyright (C) 2009, Google, Inc.
+ * Copyright (C) 2009, JetBrains s.r.o.
+ * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Thad Hughes <thadh@thad.corp.google.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.lib;
+
+import org.eclipse.jgit.util.StringUtils;
+
+/** A line in a Git {@link Config} file. */
+class ConfigLine {
+ /** The text content before entry. */
+ String prefix;
+
+ /** The section name for the entry. */
+ String section;
+
+ /** Subsection name. */
+ String subsection;
+
+ /** The key name. */
+ String name;
+
+ /** The value. */
+ String value;
+
+ /** The text content after entry. */
+ String suffix;
+
+ ConfigLine forValue(final String newValue) {
+ final ConfigLine e = new ConfigLine();
+ e.prefix = prefix;
+ e.section = section;
+ e.subsection = subsection;
+ e.name = name;
+ e.value = newValue;
+ e.suffix = suffix;
+ return e;
+ }
+
+ boolean match(final String aSection, final String aSubsection,
+ final String aKey) {
+ return eqIgnoreCase(section, aSection)
+ && eqSameCase(subsection, aSubsection)
+ && eqIgnoreCase(name, aKey);
+ }
+
+ boolean match(final String aSection, final String aSubsection) {
+ return eqIgnoreCase(section, aSection)
+ && eqSameCase(subsection, aSubsection);
+ }
+
+ private static boolean eqIgnoreCase(final String a, final String b) {
+ if (a == null && b == null)
+ return true;
+ if (a == null || b == null)
+ return false;
+ return StringUtils.equalsIgnoreCase(a, b);
+ }
+
+ private static boolean eqSameCase(final String a, final String b) {
+ if (a == null && b == null)
+ return true;
+ if (a == null || b == null)
+ return false;
+ return a.equals(b);
+ }
+
+ @Override
+ public String toString() {
+ if (section == null)
+ return "<empty>";
+ StringBuilder b = new StringBuilder(section);
+ if (subsection != null)
+ b.append(".").append(subsection);
+ if (name != null)
+ b.append(".").append(name);
+ if (value != null)
+ b.append("=").append(value);
+ return b.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
+ * Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2008-2010, Google Inc.
+ * Copyright (C) 2009, Google, Inc.
+ * Copyright (C) 2009, JetBrains s.r.o.
+ * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Thad Hughes <thadh@thad.corp.google.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.lib;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+class ConfigSnapshot {
+ final List<ConfigLine> entryList;
+ final Map<Object, Object> cache;
+ final ConfigSnapshot baseState;
+
+ ConfigSnapshot(List<ConfigLine> entries, ConfigSnapshot base) {
+ entryList = entries;
+ cache = new ConcurrentHashMap<Object, Object>(16, 0.75f, 1);
+ baseState = base;
+ }
+}