diff options
author | Jan Vanhercke <jan.vanhercke@novotea.com> | 2017-07-30 00:03:05 +0200 |
---|---|---|
committer | Florian Zschocke <f.zschocke+git@gmail.com> | 2022-11-09 22:28:43 +0100 |
commit | 9186cf7f1196aacce486558b5b18751b548aea17 (patch) | |
tree | 02796dd50994d94da95d291470363cbe962268fd /src | |
parent | 73e5faac4b17e8ec26117939d334af744f855427 (diff) | |
download | gitblit-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.java | 31 | ||||
-rw-r--r-- | src/main/java/com/gitblit/utils/MapUtils.java | 116 |
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(); + } + } +} |