]> source.dussan.org Git - gitblit.git/commitdiff
Add wrapper class to return a default encoding
authorJan Vanhercke <jan.vanhercke@novotea.com>
Sat, 29 Jul 2017 22:03:05 +0000 (00:03 +0200)
committerFlorian Zschocke <f.zschocke+git@gmail.com>
Wed, 9 Nov 2022 21:28:43 +0000 (22:28 +0100)
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.

src/main/java/com/gitblit/manager/RepositoryManager.java
src/main/java/com/gitblit/utils/MapUtils.java [new file with mode: 0644]

index 2be658733eb5a5c15735a87f15647f97a2676b49..efbdef6a5f5c4cb19bc9462d74e15ae0dc66edf5 100644 (file)
@@ -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 (file)
index 0000000..9856878
--- /dev/null
@@ -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();
+               }
+       }
+}