summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Vanhercke <jan.vanhercke@novotea.com>2017-07-30 00:03:05 +0200
committerFlorian Zschocke <f.zschocke+git@gmail.com>2022-11-09 22:28:43 +0100
commit9186cf7f1196aacce486558b5b18751b548aea17 (patch)
tree02796dd50994d94da95d291470363cbe962268fd /src
parent73e5faac4b17e8ec26117939d334af744f855427 (diff)
downloadgitblit-9186cf7f1196aacce486558b5b18751b548aea17.tar.gz
gitblit-9186cf7f1196aacce486558b5b18751b548aea17.zip
Add wrapper class to return a default encoding
Unknown encodings may cause gitblit to fail to start. This modification injects a wrapper class in the JGit internal to fake a valid return value.
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/gitblit/manager/RepositoryManager.java31
-rw-r--r--src/main/java/com/gitblit/utils/MapUtils.java116
2 files changed, 145 insertions, 2 deletions
diff --git a/src/main/java/com/gitblit/manager/RepositoryManager.java b/src/main/java/com/gitblit/manager/RepositoryManager.java
index 2be65873..efbdef6a 100644
--- a/src/main/java/com/gitblit/manager/RepositoryManager.java
+++ b/src/main/java/com/gitblit/manager/RepositoryManager.java
@@ -19,9 +19,11 @@ import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -87,6 +89,7 @@ import com.gitblit.utils.CommitCache;
import com.gitblit.utils.DeepCopier;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.JGitUtils.LastChange;
+import com.gitblit.utils.MapUtils;
import com.gitblit.utils.MetricUtils;
import com.gitblit.utils.ModelUtils;
import com.gitblit.utils.ObjectCache;
@@ -1924,6 +1927,7 @@ public class RepositoryManager implements IRepositoryManager {
}
}
+ @SuppressWarnings("unchecked")
protected void configureJGit() {
// Configure JGit
WindowCacheConfig cfg = new WindowCacheConfig();
@@ -1944,16 +1948,39 @@ public class RepositoryManager implements IRepositoryManager {
} catch (IllegalArgumentException e) {
logger.error("Failed to configure JGit parameters!", e);
}
-
+
try {
// issue-486/ticket-151: UTF-9 & UTF-18
// issue-560/ticket-237: 'UTF8'
Field field = RawParseUtils.class.getDeclaredField("encodingAliases");
field.setAccessible(true);
- Map<String, Charset> encodingAliases = (Map<String, Charset>) field.get(null);
+
+ Map<String, Charset> encodingAliases;
+
+ try {
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
+ modifiersField.setAccessible(true);
+ modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+
+ // Since unknown encodingAliases cause GitBlit to crash we replace the
+ // map by a wrapper class that always returns a value. ISO-8859-1 seems
+ // appropriate since it is a fixed 8-bit encoding.
+ encodingAliases = (Map<String, Charset>) field.get(null);
+ encodingAliases = MapUtils.defaultMap(encodingAliases, StandardCharsets.ISO_8859_1);
+ field.set(null, encodingAliases);
+
+ modifiersField.setInt(field, field.getModifiers() | Modifier.FINAL);
+ modifiersField.setAccessible(false);
+ } catch(Throwable t) {
+ logger.error("Failed to inject wrapper class for encoding Aliases", t);
+ encodingAliases = (Map<String, Charset>) field.get(null);
+ }
+
+ // Provided sensible default mappings
encodingAliases.put("'utf8'", RawParseUtils.UTF8_CHARSET);
encodingAliases.put("utf-9", RawParseUtils.UTF8_CHARSET);
encodingAliases.put("utf-18", RawParseUtils.UTF8_CHARSET);
+
logger.info("Alias 'UTF8', UTF-9 & UTF-18 encodings as UTF-8 in JGit");
} catch (Throwable t) {
logger.error("Failed to inject UTF-9 & UTF-18 encoding aliases into JGit", t);
diff --git a/src/main/java/com/gitblit/utils/MapUtils.java b/src/main/java/com/gitblit/utils/MapUtils.java
new file mode 100644
index 00000000..98568780
--- /dev/null
+++ b/src/main/java/com/gitblit/utils/MapUtils.java
@@ -0,0 +1,116 @@
+package com.gitblit.utils;
+
+import java.text.MessageFormat;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.mina.util.ConcurrentHashSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A utility wrapper class to generate a default value over an existing map
+ *
+ * @author Jan Vanhercke
+ *
+ */
+public class MapUtils {
+
+ private static final Logger logger = LoggerFactory.getLogger(MapUtils.class);
+
+ public static <K, V> Map<K, V> defaultMap(Map<K, V> delegate, V value) {
+ return new Wrap<>(delegate, value);
+ }
+
+ private static class Wrap<K, V> implements Map<K, V> {
+
+ private Map<K, V> delegate;
+
+ // HashSet is only used to reduce logging
+
+ private Set<K> unknownKeys = new ConcurrentHashSet<>();
+
+ private V value;
+
+ private Wrap(Map<K, V> delegate, V value) {
+ this.delegate = delegate;
+ this.value = value;
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return true;
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V get(Object key) {
+ V retv = delegate.get(key);
+
+ if (retv == null) {
+ if (unknownKeys.add((K) key))
+ logger.error(MessageFormat.format("Default value {0} generated for key {1}", value, key));
+
+ return value;
+ }
+
+ return retv;
+ }
+
+ @Override
+ public V put(K key, V value) {
+ return delegate.put(key, value);
+ }
+
+ @Override
+ public V remove(Object key) {
+ V retv = delegate.remove(key);
+
+ if (retv == null)
+ return value;
+
+ return value;
+ }
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+ delegate.putAll(m);
+ }
+
+ @Override
+ public void clear() {
+ delegate.clear();
+ }
+
+ @Override
+ public Set<K> keySet() {
+ return delegate.keySet();
+ }
+
+ @Override
+ public Collection<V> values() {
+ return delegate.values();
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<K, V>> entrySet() {
+ return delegate.entrySet();
+ }
+ }
+}