diff --git a/Jenkinsfile b/Jenkinsfile index 36135cf4a4..6a9fa7e044 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,7 +7,7 @@ import com.cloudogu.ces.cesbuildlib.* node('docker') { // Change this as when we go back to default - necessary for proper SonarQube analysis - mainBranch = '2.0.0-m3' + mainBranch = 'default' properties([ // Keep only the last 10 build to preserve space diff --git a/package.json b/package.json index b2f14826c5..8d9a9c931b 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "test": "lerna run --scope '@scm-manager/ui-*' test", "typecheck": "lerna run --scope '@scm-manager/ui-*' typecheck", "serve": "webpack-dev-server --mode=development --config=scm-ui/ui-scripts/src/webpack.config.js", - "deploy": "ui-scripts publish" + "deploy": "ui-scripts publish", + "set-version": "ui-scripts version" }, "devDependencies": { "babel-plugin-reflow": "^0.2.7", diff --git a/scm-annotation-processor/src/main/java/sonia/scm/annotation/ScmAnnotationProcessor.java b/scm-annotation-processor/src/main/java/sonia/scm/annotation/ScmAnnotationProcessor.java index c548f30d45..38961ccaf8 100644 --- a/scm-annotation-processor/src/main/java/sonia/scm/annotation/ScmAnnotationProcessor.java +++ b/scm-annotation-processor/src/main/java/sonia/scm/annotation/ScmAnnotationProcessor.java @@ -99,8 +99,9 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import static javax.lang.model.util.ElementFilter.methodsIn; + /** - * * @author Sebastian Sdorra */ @SupportedAnnotationTypes("*") @@ -372,6 +373,18 @@ public final class ScmAnnotationProcessor extends AbstractProcessor { attributes.put(entry.getKey().getSimpleName().toString(), getValue(entry.getValue())); } + + // add default values + for (ExecutableElement meth : methodsIn(annotationMirror.getAnnotationType().asElement().getEnclosedElements())) { + String attribute = meth.getSimpleName().toString(); + AnnotationValue defaultValue = meth.getDefaultValue(); + if (defaultValue != null && !attributes.containsKey(attribute)) { + String value = getValue(defaultValue); + if (value != null && !value.isEmpty()) { + attributes.put(attribute, value); + } + } + } } } diff --git a/scm-annotations/pom.xml b/scm-annotations/pom.xml index ba8922e0b6..c5a892af95 100644 --- a/scm-annotations/pom.xml +++ b/scm-annotations/pom.xml @@ -8,8 +8,7 @@ scm 2.0.0-SNAPSHOT - - sonia.scm + scm-annotations 2.0.0-SNAPSHOT scm-annotations diff --git a/scm-core/src/main/java/sonia/scm/collect/IterableQueue.java b/scm-core/src/main/java/sonia/scm/collect/IterableQueue.java index 9d3c85bb90..6b6af9fd0f 100644 --- a/scm-core/src/main/java/sonia/scm/collect/IterableQueue.java +++ b/scm-core/src/main/java/sonia/scm/collect/IterableQueue.java @@ -134,7 +134,7 @@ public final class IterableQueue implements Iterable else { logger.trace("create queue iterator"); - iterator = new QueueIterator(this); + iterator = new QueueIterator<>(this); } return iterator; diff --git a/scm-core/src/main/java/sonia/scm/collect/LimitedSortedSet.java b/scm-core/src/main/java/sonia/scm/collect/LimitedSortedSet.java index fe99ee7a1c..681b8ef07c 100644 --- a/scm-core/src/main/java/sonia/scm/collect/LimitedSortedSet.java +++ b/scm-core/src/main/java/sonia/scm/collect/LimitedSortedSet.java @@ -63,7 +63,7 @@ public class LimitedSortedSet extends ForwardingSortedSet */ public LimitedSortedSet(int maxSize) { - this.sortedSet = new TreeSet(); + this.sortedSet = new TreeSet<>(); this.maxSize = maxSize; } diff --git a/scm-core/src/main/java/sonia/scm/io/AbstractResourceProcessor.java b/scm-core/src/main/java/sonia/scm/io/AbstractResourceProcessor.java index 8b5c1d1dd7..6c00a319c9 100644 --- a/scm-core/src/main/java/sonia/scm/io/AbstractResourceProcessor.java +++ b/scm-core/src/main/java/sonia/scm/io/AbstractResourceProcessor.java @@ -183,5 +183,5 @@ public abstract class AbstractResourceProcessor implements ResourceProcessor //~--- fields --------------------------------------------------------------- /** Field description */ - private Map variableMap = new HashMap(); + private Map variableMap = new HashMap<>(); } diff --git a/scm-core/src/main/java/sonia/scm/io/INIConfiguration.java b/scm-core/src/main/java/sonia/scm/io/INIConfiguration.java index 9f3cce03f6..c9695b7ca6 100644 --- a/scm-core/src/main/java/sonia/scm/io/INIConfiguration.java +++ b/scm-core/src/main/java/sonia/scm/io/INIConfiguration.java @@ -52,7 +52,7 @@ public class INIConfiguration */ public INIConfiguration() { - this.sectionMap = new LinkedHashMap(); + this.sectionMap = new LinkedHashMap<>(); } //~--- methods -------------------------------------------------------------- diff --git a/scm-core/src/main/java/sonia/scm/io/INISection.java b/scm-core/src/main/java/sonia/scm/io/INISection.java index 03768a84ca..0ce6ea6bcf 100644 --- a/scm-core/src/main/java/sonia/scm/io/INISection.java +++ b/scm-core/src/main/java/sonia/scm/io/INISection.java @@ -55,7 +55,7 @@ public class INISection public INISection(String name) { this.name = name; - this.parameters = new LinkedHashMap(); + this.parameters = new LinkedHashMap<>(); } /** diff --git a/scm-core/src/main/java/sonia/scm/util/Base32.java b/scm-core/src/main/java/sonia/scm/util/Base32.java index cadbab3d8f..5ff3576078 100644 --- a/scm-core/src/main/java/sonia/scm/util/Base32.java +++ b/scm-core/src/main/java/sonia/scm/util/Base32.java @@ -46,7 +46,7 @@ public final class Base32 extends AbstractBase { /** base value */ - private static final BigInteger BASE = BigInteger.valueOf(32l); + private static final BigInteger BASE = BigInteger.valueOf(32L); /** char table */ private static final String CHARS = "0123456789bcdefghjkmnpqrstuvwxyz"; diff --git a/scm-core/src/main/java/sonia/scm/util/Base62.java b/scm-core/src/main/java/sonia/scm/util/Base62.java index 04fd1657d6..b9c9fd6a54 100644 --- a/scm-core/src/main/java/sonia/scm/util/Base62.java +++ b/scm-core/src/main/java/sonia/scm/util/Base62.java @@ -46,7 +46,7 @@ public final class Base62 extends AbstractBase { /** base value */ - private static final BigInteger BASE = BigInteger.valueOf(62l); + private static final BigInteger BASE = BigInteger.valueOf(62L); /** char table */ private static final String CHARS = diff --git a/scm-core/src/main/java/sonia/scm/util/LinkTextParser.java b/scm-core/src/main/java/sonia/scm/util/LinkTextParser.java index 2037beeeff..67ca800bcb 100644 --- a/scm-core/src/main/java/sonia/scm/util/LinkTextParser.java +++ b/scm-core/src/main/java/sonia/scm/util/LinkTextParser.java @@ -79,7 +79,7 @@ public final class LinkTextParser public static String parseText(String content) { Matcher m = REGEX_URL.matcher(content); - List tokens = new ArrayList(); + List tokens = new ArrayList<>(); int position = 0; String tokenContent = null; diff --git a/scm-core/src/main/java/sonia/scm/util/ServiceUtil.java b/scm-core/src/main/java/sonia/scm/util/ServiceUtil.java index 138345bb05..04bdfb6dea 100644 --- a/scm-core/src/main/java/sonia/scm/util/ServiceUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/ServiceUtil.java @@ -119,7 +119,7 @@ public final class ServiceUtil */ public static List getServices(Class type) { - List result = new ArrayList(); + List result = new ArrayList<>(); try { diff --git a/scm-core/src/main/java/sonia/scm/util/Util.java b/scm-core/src/main/java/sonia/scm/util/Util.java index 5439cc77ec..cb64b75aff 100644 --- a/scm-core/src/main/java/sonia/scm/util/Util.java +++ b/scm-core/src/main/java/sonia/scm/util/Util.java @@ -38,23 +38,12 @@ package sonia.scm.util; import com.google.common.base.Strings; import com.google.common.collect.Multimap; -//~--- JDK imports ------------------------------------------------------------ - import java.math.BigInteger; - import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.TimeZone; +//~--- JDK imports ------------------------------------------------------------ /** * @@ -273,12 +262,12 @@ public final class Util Comparator comparator, CollectionAppender appender, int start, int limit) { - List result = new ArrayList(); - List valueList = new ArrayList(values); + List result = new ArrayList<>(); + List valueList = new ArrayList<>(values); if (comparator != null) { - Collections.sort(valueList, comparator); + valueList.sort(comparator); } int length = valueList.size(); @@ -506,12 +495,10 @@ public final class Util { StringBuilder buffer = new StringBuilder(); - for (int i = 0; i < byteValue.length; i++) - { - int x = byteValue[i] & 0xff; + for (final byte aByteValue : byteValue) { + int x = aByteValue & 0xff; - if (x < 16) - { + if (x < 16) { buffer.append('0'); } diff --git a/scm-core/src/main/java/sonia/scm/web/cgi/EnvList.java b/scm-core/src/main/java/sonia/scm/web/cgi/EnvList.java index 796d6125d8..541ae9ba23 100644 --- a/scm-core/src/main/java/sonia/scm/web/cgi/EnvList.java +++ b/scm-core/src/main/java/sonia/scm/web/cgi/EnvList.java @@ -66,7 +66,7 @@ public class EnvList */ public EnvList() { - envMap = new HashMap(); + envMap = new HashMap<>(); } /** @@ -77,7 +77,7 @@ public class EnvList */ public EnvList(EnvList l) { - envMap = new HashMap(l.envMap); + envMap = new HashMap<>(l.envMap); } //~--- methods -------------------------------------------------------------- diff --git a/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletResponse.java b/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletResponse.java index b91f2b62c9..ff174c4fe8 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletResponse.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/BufferedHttpServletResponse.java @@ -470,13 +470,13 @@ public class BufferedHttpServletResponse extends HttpServletResponseWrapper private ByteArrayPrintWriter pw = null; /** Field description */ - private Set cookies = new HashSet(); + private Set cookies = new HashSet<>(); /** Field description */ private int statusCode = HttpServletResponse.SC_OK; /** Field description */ - private Map headers = new LinkedHashMap(); + private Map headers = new LinkedHashMap<>(); /** Field description */ private String statusMessage; diff --git a/scm-core/src/main/java/sonia/scm/web/proxy/ProxyServlet.java b/scm-core/src/main/java/sonia/scm/web/proxy/ProxyServlet.java index 1d865dc4bc..06059c2926 100644 --- a/scm-core/src/main/java/sonia/scm/web/proxy/ProxyServlet.java +++ b/scm-core/src/main/java/sonia/scm/web/proxy/ProxyServlet.java @@ -40,28 +40,20 @@ import com.google.common.io.ByteStreams; import com.google.common.io.Closer; import com.google.inject.Inject; import com.google.inject.Singleton; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; import java.net.HttpURLConnection; - import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +//~--- JDK imports ------------------------------------------------------------ /** * @@ -175,10 +167,8 @@ public class ProxyServlet extends HttpServlet private void copyContent(HttpURLConnection con, HttpServletResponse response) throws IOException { - Closer closer = Closer.create(); - try - { + try (Closer closer = Closer.create()) { InputStream webToProxyBuf = closer.register(new BufferedInputStream(con.getInputStream())); OutputStream proxyToClientBuf = @@ -188,10 +178,6 @@ public class ProxyServlet extends HttpServlet logger.trace("copied {} bytes for proxy", bytes); } - finally - { - closer.close(); - } } /** diff --git a/scm-core/src/main/java/sonia/scm/xml/XmlMapStringAdapter.java b/scm-core/src/main/java/sonia/scm/xml/XmlMapStringAdapter.java index ab6cd83ccc..04d04fae60 100644 --- a/scm-core/src/main/java/sonia/scm/xml/XmlMapStringAdapter.java +++ b/scm-core/src/main/java/sonia/scm/xml/XmlMapStringAdapter.java @@ -102,7 +102,7 @@ public class XmlMapStringAdapter public Map unmarshal(XmlMapStringElement[] elements) throws Exception { - Map map = new HashMap(); + Map map = new HashMap<>(); if (elements != null) { diff --git a/scm-core/src/main/java/sonia/scm/xml/XmlSetStringAdapter.java b/scm-core/src/main/java/sonia/scm/xml/XmlSetStringAdapter.java index 708159bfac..8d088aa205 100644 --- a/scm-core/src/main/java/sonia/scm/xml/XmlSetStringAdapter.java +++ b/scm-core/src/main/java/sonia/scm/xml/XmlSetStringAdapter.java @@ -90,7 +90,7 @@ public class XmlSetStringAdapter extends XmlAdapter> @Override public Set unmarshal(String rawString) throws Exception { - Set tokens = new HashSet(); + Set tokens = new HashSet<>(); for (String token : rawString.split(",")) { diff --git a/scm-core/src/test/java/sonia/scm/collect/IterableQueueTest.java b/scm-core/src/test/java/sonia/scm/collect/IterableQueueTest.java index ade4f3247b..130924fcd4 100644 --- a/scm-core/src/test/java/sonia/scm/collect/IterableQueueTest.java +++ b/scm-core/src/test/java/sonia/scm/collect/IterableQueueTest.java @@ -63,7 +63,7 @@ public class IterableQueueTest @Test(expected = IllegalStateException.class) public void testDuplicatedEndReached() { - IterableQueue queue = new IterableQueue(); + IterableQueue queue = new IterableQueue<>(); queue.endReached(); queue.endReached(); @@ -76,7 +76,7 @@ public class IterableQueueTest @Test public void testIterator() { - IterableQueue queue = new IterableQueue(); + IterableQueue queue = new IterableQueue<>(); assertEquals(QueueIterator.class, queue.iterator().getClass()); queue.endReached(); @@ -120,7 +120,7 @@ public class IterableQueueTest @Test(expected = IllegalStateException.class) public void testPushEndReached() { - IterableQueue queue = new IterableQueue(); + IterableQueue queue = new IterableQueue<>(); queue.push("a"); queue.endReached(); @@ -134,7 +134,7 @@ public class IterableQueueTest @Test public void testSingleConsumer() { - final IterableQueue queue = new IterableQueue(); + final IterableQueue queue = new IterableQueue<>(); new Thread(new IntegerProducer(queue, false, 100)).start(); assertResult(Lists.newArrayList(queue), 100); @@ -176,12 +176,12 @@ public class IterableQueueTest ExecutorService executor = Executors.newFixedThreadPool(threads); List>> futures = Lists.newArrayList(); - final IterableQueue queue = new IterableQueue(); + final IterableQueue queue = new IterableQueue<>(); for (int i = 0; i < consumer; i++) { Future> future = - executor.submit(new CallableQueueCollector(queue)); + executor.submit(new CallableQueueCollector<>(queue)); futures.add(future); } diff --git a/scm-core/src/test/java/sonia/scm/plugin/ScmModuleTest.java b/scm-core/src/test/java/sonia/scm/plugin/ScmModuleTest.java index 45c490d15e..1629562132 100644 --- a/scm-core/src/test/java/sonia/scm/plugin/ScmModuleTest.java +++ b/scm-core/src/test/java/sonia/scm/plugin/ScmModuleTest.java @@ -71,8 +71,8 @@ public class ScmModuleTest assertThat( module.getExtensions(), containsInAnyOrder( - (Class) String.class, - (Class) Integer.class + String.class, + Integer.class ) ); assertThat( @@ -86,8 +86,8 @@ public class ScmModuleTest assertThat( module.getEvents(), containsInAnyOrder( - (Class) String.class, - (Class) Boolean.class + String.class, + Boolean.class ) ); assertThat( @@ -100,15 +100,15 @@ public class ScmModuleTest assertThat( module.getRestProviders(), containsInAnyOrder( - (Class) Integer.class, - (Class) Long.class + Integer.class, + Long.class ) ); assertThat( module.getRestResources(), containsInAnyOrder( - (Class) Float.class, - (Class) Double.class + Float.class, + Double.class ) ); //J+ diff --git a/scm-core/src/test/java/sonia/scm/template/TemplateEngineFactoryTest.java b/scm-core/src/test/java/sonia/scm/template/TemplateEngineFactoryTest.java index b676b4bbaf..775f9f0814 100644 --- a/scm-core/src/test/java/sonia/scm/template/TemplateEngineFactoryTest.java +++ b/scm-core/src/test/java/sonia/scm/template/TemplateEngineFactoryTest.java @@ -128,7 +128,7 @@ public class TemplateEngineFactoryTest assertTrue(engines.contains(engine1)); assertTrue(engines.contains(engine2)); - Set ce = new HashSet(); + Set ce = new HashSet<>(); ce.add(engine1); factory = new TemplateEngineFactory(ce, engine2); diff --git a/scm-core/src/test/java/sonia/scm/util/UrlBuilderTest.java b/scm-core/src/test/java/sonia/scm/util/UrlBuilderTest.java index 16d4b59ffc..eb0af7926c 100644 --- a/scm-core/src/test/java/sonia/scm/util/UrlBuilderTest.java +++ b/scm-core/src/test/java/sonia/scm/util/UrlBuilderTest.java @@ -56,7 +56,7 @@ public class UrlBuilderTest UrlBuilder builder = new UrlBuilder("http://www.short.de"); builder.appendParameter("i", 123).appendParameter("s", "abc"); - builder.appendParameter("b", true).appendParameter("l", 321l); + builder.appendParameter("b", true).appendParameter("l", 321L); assertEquals("http://www.short.de?i=123&s=abc&b=true&l=321", builder.toString()); builder.appendParameter("c", "a b"); assertEquals("http://www.short.de?i=123&s=abc&b=true&l=321&c=a%20b", builder.toString()); diff --git a/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupDatabase.java b/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupDatabase.java index 431d53594a..e4d436283c 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupDatabase.java +++ b/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupDatabase.java @@ -199,7 +199,7 @@ public class XmlGroupDatabase implements XmlDatabase /** Field description */ @XmlJavaTypeAdapter(XmlGroupMapAdapter.class) @XmlElement(name = "groups") - private Map groupMap = new LinkedHashMap(); + private Map groupMap = new LinkedHashMap<>(); /** Field description */ private Long lastModified; diff --git a/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupList.java b/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupList.java index da14968d30..c889944fc4 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupList.java +++ b/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupList.java @@ -72,7 +72,7 @@ public class XmlGroupList implements Iterable */ public XmlGroupList(Map groupMap) { - this.groups = new LinkedList(groupMap.values()); + this.groups = new LinkedList<>(groupMap.values()); } //~--- methods -------------------------------------------------------------- diff --git a/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupMapAdapter.java b/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupMapAdapter.java index b79c8836d2..430d0a84a8 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupMapAdapter.java +++ b/scm-dao-xml/src/main/java/sonia/scm/group/xml/XmlGroupMapAdapter.java @@ -81,7 +81,7 @@ public class XmlGroupMapAdapter @Override public Map unmarshal(XmlGroupList groups) throws Exception { - Map groupMap = new LinkedHashMap(); + Map groupMap = new LinkedHashMap<>(); for (Group group : groups) { diff --git a/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserDatabase.java b/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserDatabase.java index 579856fce7..2306fd588b 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserDatabase.java +++ b/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserDatabase.java @@ -202,5 +202,5 @@ public class XmlUserDatabase implements XmlDatabase /** Field description */ @XmlJavaTypeAdapter(XmlUserMapAdapter.class) @XmlElement(name = "users") - private Map userMap = new LinkedHashMap(); + private Map userMap = new LinkedHashMap<>(); } diff --git a/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserList.java b/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserList.java index e76f008b92..6877d8544e 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserList.java +++ b/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserList.java @@ -72,7 +72,7 @@ public class XmlUserList implements Iterable */ public XmlUserList(Map userMap) { - this.users = new LinkedList(userMap.values()); + this.users = new LinkedList<>(userMap.values()); } //~--- methods -------------------------------------------------------------- diff --git a/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserMapAdapter.java b/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserMapAdapter.java index f5573310d5..0c2386f37c 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserMapAdapter.java +++ b/scm-dao-xml/src/main/java/sonia/scm/user/xml/XmlUserMapAdapter.java @@ -81,7 +81,7 @@ public class XmlUserMapAdapter @Override public Map unmarshal(XmlUserList users) throws Exception { - Map userMap = new LinkedHashMap(); + Map userMap = new LinkedHashMap<>(); for (User user : users) { diff --git a/scm-dao-xml/src/main/java/sonia/scm/xml/XmlStreams.java b/scm-dao-xml/src/main/java/sonia/scm/xml/XmlStreams.java index 4b3d9b0f28..c8c5240f88 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/xml/XmlStreams.java +++ b/scm-dao-xml/src/main/java/sonia/scm/xml/XmlStreams.java @@ -52,7 +52,9 @@ public final class XmlStreams { } private static XMLStreamReader createReader(Reader reader) throws XMLStreamException { - return XMLInputFactory.newInstance().createXMLStreamReader(reader); + XMLInputFactory factory = XMLInputFactory.newInstance(); + factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); + return factory.createXMLStreamReader(reader); } diff --git a/scm-plugins/scm-git-plugin/src/main/js/ProtocolInformation.tsx b/scm-plugins/scm-git-plugin/src/main/js/ProtocolInformation.tsx index f871ab8f2f..9f36abf302 100644 --- a/scm-plugins/scm-git-plugin/src/main/js/ProtocolInformation.tsx +++ b/scm-plugins/scm-git-plugin/src/main/js/ProtocolInformation.tsx @@ -14,6 +14,12 @@ const Switcher = styled(ButtonAddons)` right: 0; `; +const SmallButton = styled(Button).attrs(props => ({ + className: "is-small" +}))` + height: inherit; +`; + type Props = { repository: Repository; }; @@ -62,9 +68,9 @@ export default class ProtocolInformation extends React.Component { } return ( - + ); }; diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/HgPackageReader.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/HgPackageReader.java index d16f056889..cb09c32870 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/HgPackageReader.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/HgPackageReader.java @@ -145,7 +145,7 @@ public class HgPackageReader */ private void filterPackage(HgPackages packages) { - List pkgList = new ArrayList(); + List pkgList = new ArrayList<>(); for (HgPackage pkg : packages) { @@ -228,7 +228,7 @@ public class HgPackageReader if (packages == null) { packages = new HgPackages(); - packages.setPackages(new ArrayList()); + packages.setPackages(new ArrayList<>()); } return packages; diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/logging/SVNKitLogger.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/logging/SVNKitLogger.java index e156defaf5..177bc05069 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/logging/SVNKitLogger.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/logging/SVNKitLogger.java @@ -211,15 +211,7 @@ public class SVNKitLogger extends SVNDebugLogAdapter */ private Logger getLogger(SVNLogType type) { - Logger logger = loggerMap.get(type); - - if (logger == null) - { - logger = LoggerFactory.getLogger(parseName(type.getName())); - loggerMap.put(type, logger); - } - - return logger; + return loggerMap.computeIfAbsent(type, t -> LoggerFactory.getLogger(parseName(t.getName()))); } //~--- fields --------------------------------------------------------------- diff --git a/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java b/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java index 0e4faddb4a..1f606fc908 100644 --- a/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java +++ b/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java @@ -81,15 +81,7 @@ public class MapCacheManager @Override public synchronized MapCache getCache(String name) { - MapCache cache = cacheMap.get(name); - - if (cache == null) - { - cache = new MapCache(); - cacheMap.put(name, cache); - } - - return cache; + return (MapCache) cacheMap.computeIfAbsent(name, k -> new MapCache()); } //~--- fields --------------------------------------------------------------- diff --git a/scm-ui/ui-components/src/Autocomplete.tsx b/scm-ui/ui-components/src/Autocomplete.tsx index 7618464b57..814be20aa2 100644 --- a/scm-ui/ui-components/src/Autocomplete.tsx +++ b/scm-ui/ui-components/src/Autocomplete.tsx @@ -1,4 +1,5 @@ import React from "react"; +import classNames from "classnames"; import { Async, AsyncCreatable } from "react-select"; import { SelectValue } from "@scm-manager/ui-types"; import LabelWithHelpIcon from "./forms/LabelWithHelpIcon"; @@ -14,6 +15,7 @@ type Props = { loadingMessage: string; noOptionsMessage: string; creatable?: boolean; + className?: string; }; type State = {}; @@ -53,10 +55,11 @@ class Autocomplete extends React.Component { loadingMessage, noOptionsMessage, loadSuggestions, - creatable + creatable, + className } = this.props; return ( -
+
{creatable ? ( diff --git a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap index 0350b44219..ac759241d2 100644 --- a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap +++ b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap @@ -336,7 +336,7 @@ exports[`Storyshots DateFromNow Default 1`] = ` exports[`Storyshots Forms|Checkbox Default 1`] = `
`; + +exports[`Storyshots Table|Table Default 1`] = ` + + + + + + + + + + + + + + + + + + + + +
+ First Name + + Last Name + + + E-Mail +
+

+ Tricia +

+
+ + McMillan + + + + tricia@hitchhiker.com + +
+

+ Arthur +

+
+ + Dent + + + + arthur@hitchhiker.com + +
+`; + +exports[`Storyshots Table|Table Empty 1`] = ` +
+ + No data found. +
+`; + +exports[`Storyshots Table|Table TextColumn 1`] = ` + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Id + + + Name + + + Description + +
+ 21 + + Pommes + + Fried potato sticks +
+ 42 + + Quarter-Pounder + + Big burger +
+ -84 + + Icecream + + Cold dessert +
+`; diff --git a/scm-ui/ui-components/src/buttons/DownloadButton.tsx b/scm-ui/ui-components/src/buttons/DownloadButton.tsx index 0e63d34073..98860cecc6 100644 --- a/scm-ui/ui-components/src/buttons/DownloadButton.tsx +++ b/scm-ui/ui-components/src/buttons/DownloadButton.tsx @@ -2,8 +2,8 @@ import React from "react"; type Props = { displayName: string; - url: string; - disabled: boolean; + url?: string; + disabled?: boolean; onClick?: () => void; }; diff --git a/scm-ui/ui-components/src/config/Configuration.tsx b/scm-ui/ui-components/src/config/Configuration.tsx index 967feabb2b..453fac421e 100644 --- a/scm-ui/ui-components/src/config/Configuration.tsx +++ b/scm-ui/ui-components/src/config/Configuration.tsx @@ -1,8 +1,7 @@ -import React from "react"; +import React, { FormEvent } from "react"; import { WithTranslation, withTranslation } from "react-i18next"; import { Links, Link } from "@scm-manager/ui-types"; -import { apiClient, SubmitButton, Loading, ErrorNotification } from "../"; -import { FormEvent } from "react"; +import { apiClient, Level, SubmitButton, Loading, ErrorNotification } from "../"; type RenderProps = { readOnly: boolean; @@ -179,7 +178,9 @@ class Configuration extends React.Component {
{this.props.render(renderProps)}
- + } + /> ); diff --git a/scm-ui/ui-components/src/forms/AddEntryToTableField.tsx b/scm-ui/ui-components/src/forms/AddEntryToTableField.tsx index d1e1b77cb6..3e18674244 100644 --- a/scm-ui/ui-components/src/forms/AddEntryToTableField.tsx +++ b/scm-ui/ui-components/src/forms/AddEntryToTableField.tsx @@ -1,7 +1,8 @@ import React, { MouseEvent } from "react"; - -import { AddButton } from "../buttons"; +import styled from "styled-components"; +import Level from "../layout/Level"; import InputField from "./InputField"; +import AddButton from "../buttons/AddButton"; type Props = { addEntry: (p: string) => void; @@ -17,6 +18,22 @@ type State = { entryToAdd: string; }; +const StyledLevel = styled(Level)` + align-items: stretch; + margin-bottom: 1rem !important; // same margin as field +`; + +const StyledInputField = styled(InputField)` + width: 100%; + margin-right: 1.5rem; +`; + +const StyledField = styled.div.attrs(props => ({ + className: "field" +}))` + align-self: flex-end; +`; + class AddEntryToTableField extends React.Component { constructor(props: Props) { super(props); @@ -37,23 +54,29 @@ class AddEntryToTableField extends React.Component { render() { const { disabled, buttonLabel, fieldLabel, errorMessage, helpText } = this.props; return ( - <> - - - + + } + right={ + + + + } + /> ); } diff --git a/scm-ui/ui-components/src/forms/AutocompleteAddEntryToTableField.tsx b/scm-ui/ui-components/src/forms/AutocompleteAddEntryToTableField.tsx index e09b0d1ef2..8287249858 100644 --- a/scm-ui/ui-components/src/forms/AutocompleteAddEntryToTableField.tsx +++ b/scm-ui/ui-components/src/forms/AutocompleteAddEntryToTableField.tsx @@ -1,6 +1,7 @@ import React, { MouseEvent } from "react"; - -import { AutocompleteObject, SelectValue } from "@scm-manager/ui-types"; +import styled from "styled-components"; +import { SelectValue } from "@scm-manager/ui-types"; +import Level from "../layout/Level"; import Autocomplete from "../Autocomplete"; import AddButton from "../buttons/AddButton"; @@ -20,6 +21,11 @@ type State = { selectedValue?: SelectValue; }; +const StyledAutocomplete = styled(Autocomplete)` + width: 100%; + margin-right: 1.5rem; +`; + class AutocompleteAddEntryToTableField extends React.Component { constructor(props: Props) { super(props); @@ -41,21 +47,26 @@ class AutocompleteAddEntryToTableField extends React.Component { const { selectedValue } = this.state; return ( -
- - - -
+ + } + right={ +
+ +
+ } + /> ); } diff --git a/scm-ui/ui-components/src/forms/InputField.tsx b/scm-ui/ui-components/src/forms/InputField.tsx index a0fd1c631c..d832d8a7d6 100644 --- a/scm-ui/ui-components/src/forms/InputField.tsx +++ b/scm-ui/ui-components/src/forms/InputField.tsx @@ -15,6 +15,7 @@ type Props = { errorMessage?: string; disabled?: boolean; helpText?: string; + className?: string; }; class InputField extends React.Component { @@ -47,11 +48,21 @@ class InputField extends React.Component { }; render() { - const { type, placeholder, value, validationError, errorMessage, disabled, label, helpText } = this.props; + const { + type, + placeholder, + value, + validationError, + errorMessage, + disabled, + label, + helpText, + className + } = this.props; const errorView = validationError ? "is-danger" : ""; const helper = validationError ?

{errorMessage}

: ""; return ( -
+
{ render() { - const { className, left, right } = this.props; + const { className, left, children, right } = this.props; + let child = null; + if (children) { + child =
{children}
; + } + return (
{left}
+ {child}
{right}
); diff --git a/scm-ui/ui-components/src/table/Column.tsx b/scm-ui/ui-components/src/table/Column.tsx new file mode 100644 index 0000000000..7f95535c36 --- /dev/null +++ b/scm-ui/ui-components/src/table/Column.tsx @@ -0,0 +1,18 @@ +import React, { FC, ReactNode } from "react"; +import { ColumnProps } from "./types"; + +type Props = ColumnProps & { + children: (row: any, columnIndex: number) => ReactNode; +}; + +const Column: FC = ({ row, columnIndex, children }) => { + if (row === undefined) { + throw new Error("missing row, use column only as child of Table"); + } + if (columnIndex === undefined) { + throw new Error("missing row, use column only as child of Table"); + } + return <>{children(row, columnIndex)}; +}; + +export default Column; diff --git a/scm-ui/ui-components/src/table/SortIcon.tsx b/scm-ui/ui-components/src/table/SortIcon.tsx new file mode 100644 index 0000000000..0d553041c6 --- /dev/null +++ b/scm-ui/ui-components/src/table/SortIcon.tsx @@ -0,0 +1,19 @@ +import React, { FC } from "react"; +import styled from "styled-components"; +import Icon from "../Icon"; + +type Props = { + name: string; + isVisible: boolean; +}; + +const IconWithMarginLeft = styled(Icon)` + visibility: ${(props: Props) => (props.isVisible ? "visible" : "hidden")}; + margin-left: 0.25em; +`; + +const SortIcon: FC = (props: Props) => { + return ; +}; + +export default SortIcon; diff --git a/scm-ui/ui-components/src/table/Table.stories.tsx b/scm-ui/ui-components/src/table/Table.stories.tsx new file mode 100644 index 0000000000..b4df2a1cb8 --- /dev/null +++ b/scm-ui/ui-components/src/table/Table.stories.tsx @@ -0,0 +1,53 @@ +import React from "react"; +import { storiesOf } from "@storybook/react"; +import Table from "./Table"; +import Column from "./Column"; +import TextColumn from "./TextColumn"; + +storiesOf("Table|Table", module) + .add("Default", () => ( + + {(row: any) =>

{row.firstname}

}
+ { + return (a: any, b: any) => { + if (a.lastname > b.lastname) { + return -1; + } else if (a.lastname < b.lastname) { + return 1; + } else { + return 0; + } + }; + }} + > + {(row: any) => {row.lastname}} + + {(row: any) => {row.email}} +
+ )) + .add("TextColumn", () => ( + + + + +
+ )) + .add("Empty", () => ( + + + +
+ )); diff --git a/scm-ui/ui-components/src/table/Table.tsx b/scm-ui/ui-components/src/table/Table.tsx new file mode 100644 index 0000000000..4d12e1c681 --- /dev/null +++ b/scm-ui/ui-components/src/table/Table.tsx @@ -0,0 +1,120 @@ +import React, { FC, ReactElement, useEffect, useState } from "react"; +import styled from "styled-components"; +import { Comparator } from "./types"; +import SortIcon from "./SortIcon"; +import Notification from "../Notification"; + +const StyledTable = styled.table.attrs(() => ({ + className: "table content is-hoverable" +}))``; + +type Props = { + data: any[]; + sortable?: boolean; + emptyMessage?: string; + children: Array; +}; + +const Table: FC = ({ data, sortable, children, emptyMessage }) => { + const [tableData, setTableData] = useState(data); + useEffect(() => { + setTableData(data); + }, [data]); + const [ascending, setAscending] = useState(false); + const [lastSortBy, setlastSortBy] = useState(); + const [hoveredColumnIndex, setHoveredColumnIndex] = useState(); + + const isSortable = (child: ReactElement) => { + return sortable && child.props.createComparator; + }; + + const sortFunctions: Comparator | undefined[] = []; + React.Children.forEach(children, (child, index) => { + if (child && isSortable(child)) { + sortFunctions.push(child.props.createComparator(child.props, index)); + } else { + sortFunctions.push(undefined); + } + }); + + const mapDataToColumns = (row: any) => { + return ( + + {React.Children.map(children, (child, columnIndex) => { + return {React.cloneElement(child, { ...child.props, columnIndex, row })}; + })} + + ); + }; + + const sortDescending = (sortAscending: (a: any, b: any) => number) => { + return (a: any, b: any) => { + return sortAscending(a, b) * -1; + }; + }; + + const tableSort = (index: number) => { + const sortFn = sortFunctions[index]; + if (!sortFn) { + throw new Error(`column with index ${index} is not sortable`); + } + const sortableData = [...tableData]; + let sortOrder = ascending; + if (lastSortBy !== index) { + setAscending(true); + sortOrder = true; + } + const sortFunction = sortOrder ? sortFn : sortDescending(sortFn); + sortableData.sort(sortFunction); + setTableData(sortableData); + setAscending(!sortOrder); + setlastSortBy(index); + }; + + const shouldShowIcon = (index: number) => { + return index === lastSortBy || index === hoveredColumnIndex; + }; + + if (!tableData || tableData.length <= 0) { + if (emptyMessage) { + return {emptyMessage}; + } else { + return null; + } + } + + return ( + + + + {React.Children.map(children, (child, index) => ( + tableSort(index) : undefined} + onMouseEnter={() => setHoveredColumnIndex(index)} + onMouseLeave={() => setHoveredColumnIndex(undefined)} + > + {child.props.header} + {isSortable(child) && renderSortIcon(child, ascending, shouldShowIcon(index))} + + ))} + + + {tableData.map(mapDataToColumns)} + + ); +}; + +Table.defaultProps = { + sortable: true +}; + +const renderSortIcon = (child: ReactElement, ascending: boolean, showIcon: boolean) => { + if (child.props.ascendingIcon && child.props.descendingIcon) { + return ; + } else { + return ; + } +}; + +export default Table; diff --git a/scm-ui/ui-components/src/table/TextColumn.tsx b/scm-ui/ui-components/src/table/TextColumn.tsx new file mode 100644 index 0000000000..0ad5375503 --- /dev/null +++ b/scm-ui/ui-components/src/table/TextColumn.tsx @@ -0,0 +1,28 @@ +import React, { FC } from "react"; +import { ColumnProps } from "./types"; + +type Props = ColumnProps & { + dataKey: string; +}; + +const TextColumn: FC = ({ row, dataKey }) => { + return row[dataKey]; +}; + +TextColumn.defaultProps = { + createComparator: (props: Props) => { + return (a: any, b: any) => { + if (a[props.dataKey] < b[props.dataKey]) { + return -1; + } else if (a[props.dataKey] > b[props.dataKey]) { + return 1; + } else { + return 0; + } + }; + }, + ascendingIcon: "sort-alpha-down-alt", + descendingIcon: "sort-alpha-down" +}; + +export default TextColumn; diff --git a/scm-ui/ui-components/src/table/index.ts b/scm-ui/ui-components/src/table/index.ts new file mode 100644 index 0000000000..c99a4e64c1 --- /dev/null +++ b/scm-ui/ui-components/src/table/index.ts @@ -0,0 +1,4 @@ +export { default as Table } from "./Table"; +export { default as Column } from "./Column"; +export { default as TextColumn } from "./TextColumn"; +export { default as SortIcon } from "./SortIcon"; diff --git a/scm-ui/ui-components/src/table/types.ts b/scm-ui/ui-components/src/table/types.ts new file mode 100644 index 0000000000..9af3e872cb --- /dev/null +++ b/scm-ui/ui-components/src/table/types.ts @@ -0,0 +1,12 @@ +import { ReactNode } from "react"; + +export type Comparator = (a: any, b: any) => number; + +export type ColumnProps = { + header: ReactNode; + row?: any; + columnIndex?: number; + createComparator?: (props: any, columnIndex: number) => Comparator; + ascendingIcon?: string; + descendingIcon?: string; +}; diff --git a/scm-ui/ui-scripts/bin/ui-scripts.js b/scm-ui/ui-scripts/bin/ui-scripts.js index 41549ac27a..28f5ef3315 100755 --- a/scm-ui/ui-scripts/bin/ui-scripts.js +++ b/scm-ui/ui-scripts/bin/ui-scripts.js @@ -1,7 +1,7 @@ #!/usr/bin/env node const { spawnSync } = require("child_process"); -const commands = ["plugin", "plugin-watch", "publish"]; +const commands = ["plugin", "plugin-watch", "publish", "version"]; const args = process.argv.slice(2); diff --git a/scm-ui/ui-scripts/src/commands/publish.js b/scm-ui/ui-scripts/src/commands/publish.js index d3cdc60724..2e5ad90440 100644 --- a/scm-ui/ui-scripts/src/commands/publish.js +++ b/scm-ui/ui-scripts/src/commands/publish.js @@ -4,7 +4,7 @@ const versions = require("../versions"); const args = process.argv.slice(2); if (args.length < 1) { - console.log("usage ui-scripts publish version"); + console.log("usage ui-scripts publish "); process.exit(1); } diff --git a/scm-ui/ui-scripts/src/commands/version.js b/scm-ui/ui-scripts/src/commands/version.js new file mode 100644 index 0000000000..c1feb85318 --- /dev/null +++ b/scm-ui/ui-scripts/src/commands/version.js @@ -0,0 +1,12 @@ +const lerna = require("../lerna"); + +const args = process.argv.slice(2); + +if (args.length < 1) { + console.log("usage ui-scripts version "); + process.exit(1); +} + +const version = args[0]; + +lerna.version(version); diff --git a/scm-ui/ui-styles/src/scm.scss b/scm-ui/ui-styles/src/scm.scss index 01d8d3e55a..cc62fa5dd6 100644 --- a/scm-ui/ui-styles/src/scm.scss +++ b/scm-ui/ui-styles/src/scm.scss @@ -622,6 +622,10 @@ form .field:not(.is-grouped) { } } +.help { + position: absolute; +} + // label with help-icon compensation .label-icon-spacing { margin-top: 30px; diff --git a/scm-ui/ui-webapp/public/locales/de/admin.json b/scm-ui/ui-webapp/public/locales/de/admin.json index af34c5b759..364fa5a5b7 100644 --- a/scm-ui/ui-webapp/public/locales/de/admin.json +++ b/scm-ui/ui-webapp/public/locales/de/admin.json @@ -6,7 +6,7 @@ "settingsNavLink": "Einstellungen", "generalNavLink": "Generell" }, - "info": { + "info": { "currentAppVersion": "Aktuelle Software-Versionsnummer", "communityTitle": "Community Support", "communityIconAlt": "Community Support Icon", @@ -91,8 +91,7 @@ "submit": "Speichern" }, "delete": { - "button": "Löschen", - "subtitle": "Berechtigungsrolle löschen", + "button": "Berechtigungsrolle löschen", "confirmAlert": { "title": "Berechtigungsrolle löschen?", "message": "Wollen Sie diese Rolle wirklich löschen? Alle Benutzer mit dieser Rolle verlieren die entsprechenden Berechtigungen.", diff --git a/scm-ui/ui-webapp/public/locales/de/groups.json b/scm-ui/ui-webapp/public/locales/de/groups.json index 04b368c56b..2e8c7aeb88 100644 --- a/scm-ui/ui-webapp/public/locales/de/groups.json +++ b/scm-ui/ui-webapp/public/locales/de/groups.json @@ -60,8 +60,7 @@ } }, "deleteGroup": { - "subtitle": "Gruppe löschen", - "button": "Löschen", + "button": "Gruppe löschen", "confirmAlert": { "title": "Gruppe löschen", "message": "Soll die Gruppe wirklich gelöscht werden?", diff --git a/scm-ui/ui-webapp/public/locales/de/repos.json b/scm-ui/ui-webapp/public/locales/de/repos.json index 4dfba695ab..df6c534ece 100644 --- a/scm-ui/ui-webapp/public/locales/de/repos.json +++ b/scm-ui/ui-webapp/public/locales/de/repos.json @@ -114,7 +114,7 @@ "size": "Größe" }, "noSources": "Keine Sources in diesem Branch gefunden.", - "extension" : { + "extension": { "notBound": "Keine Erweiterung angebunden." } }, @@ -166,8 +166,7 @@ } }, "deleteRepo": { - "subtitle": "Repository löschen", - "button": "Löschen", + "button": "Repository löschen", "confirmAlert": { "title": "Repository löschen", "message": "Soll das Repository wirklich gelöscht werden?", diff --git a/scm-ui/ui-webapp/public/locales/de/users.json b/scm-ui/ui-webapp/public/locales/de/users.json index 25b6858c8b..60f9f64423 100644 --- a/scm-ui/ui-webapp/public/locales/de/users.json +++ b/scm-ui/ui-webapp/public/locales/de/users.json @@ -45,8 +45,7 @@ "subtitle": "Erstellen eines neuen Benutzers" }, "deleteUser": { - "subtitle": "Benutzer löschen", - "button": "Löschen", + "button": "Benutzer löschen", "confirmAlert": { "title": "Benutzer löschen", "message": "Soll der Benutzer wirklich gelöscht werden?", diff --git a/scm-ui/ui-webapp/public/locales/en/admin.json b/scm-ui/ui-webapp/public/locales/en/admin.json index c315d1d142..d1360846f7 100644 --- a/scm-ui/ui-webapp/public/locales/en/admin.json +++ b/scm-ui/ui-webapp/public/locales/en/admin.json @@ -11,7 +11,7 @@ "communityTitle": "Community Support", "communityIconAlt": "Community Support Icon", "communityInfo": "Contact the SCM-Manager support team for questions about SCM-Manager, to report bugs or to request features through the official channels.", - "communityButton": "Contact our team", + "communityButton": "Contact our Team", "enterpriseTitle": "Enterprise Support", "enterpriseIconAlt": "Enterprise Support Icon", "enterpriseInfo": "You require support with the integration of SCM-Manager into your processes, with the customization of the tool or simply a service level agreement (SLA)?", @@ -76,8 +76,8 @@ "createSubtitle": "Create Permission Role", "editSubtitle": "Edit Permission Role", "overview": { - "title": "Overview of all permission roles", - "noPermissionRoles": "No permission roles found.", + "title": "Overview of all Permission Roles", + "noPermissionRoles": "No Permission Roles found.", "createButton": "Create Permission Role" }, "editButton": "Edit", @@ -91,10 +91,9 @@ "submit": "Save" }, "delete": { - "button": "Delete", - "subtitle": "Delete permission role", + "button": "Delete Permission Role", "confirmAlert": { - "title": "Delete permission role", + "title": "Delete Permission Role", "message": "Do you really want to delete this permission role? All users will lose their corresponding permissions.", "submit": "Yes", "cancel": "No" diff --git a/scm-ui/ui-webapp/public/locales/en/groups.json b/scm-ui/ui-webapp/public/locales/en/groups.json index 0153f30d30..6911f897f8 100644 --- a/scm-ui/ui-webapp/public/locales/en/groups.json +++ b/scm-ui/ui-webapp/public/locales/en/groups.json @@ -60,8 +60,7 @@ } }, "deleteGroup": { - "subtitle": "Delete Group", - "button": "Delete", + "button": "Delete Group", "confirmAlert": { "title": "Delete Group", "message": "Do you really want to delete the group?", diff --git a/scm-ui/ui-webapp/public/locales/en/repos.json b/scm-ui/ui-webapp/public/locales/en/repos.json index e2ccf8326e..103e30b825 100644 --- a/scm-ui/ui-webapp/public/locales/en/repos.json +++ b/scm-ui/ui-webapp/public/locales/en/repos.json @@ -114,7 +114,7 @@ "size": "Size" }, "noSources": "No sources found for this branch.", - "extension" : { + "extension": { "notBound": "No extension bound." } }, @@ -166,8 +166,7 @@ } }, "deleteRepo": { - "subtitle": "Delete Repository", - "button": "Delete", + "button": "Delete Repository", "confirmAlert": { "title": "Delete repository", "message": "Do you really want to delete the repository?", @@ -178,7 +177,7 @@ "diff": { "changes": { "add": "added", - "delete": "deleted", + "delete": "deleted", "modify": "modified", "rename": "renamed", "copy": "copied" diff --git a/scm-ui/ui-webapp/public/locales/en/users.json b/scm-ui/ui-webapp/public/locales/en/users.json index b492923a3f..0fab330e6f 100644 --- a/scm-ui/ui-webapp/public/locales/en/users.json +++ b/scm-ui/ui-webapp/public/locales/en/users.json @@ -45,17 +45,16 @@ "subtitle": "Create a new user" }, "deleteUser": { - "subtitle": "Delete User", - "button": "Delete", + "button": "Delete User", "confirmAlert": { - "title": "Delete user", + "title": "Delete User", "message": "Do you really want to delete the user?", "submit": "Yes", "cancel": "No" } }, "singleUserPassword": { - "button": "Set password", + "button": "Set Password", "setPasswordSuccessful": "Password successfully set" }, "userForm": { diff --git a/scm-ui/ui-webapp/public/locales/es/admin.json b/scm-ui/ui-webapp/public/locales/es/admin.json index 155313ed99..4c78d32620 100644 --- a/scm-ui/ui-webapp/public/locales/es/admin.json +++ b/scm-ui/ui-webapp/public/locales/es/admin.json @@ -86,8 +86,7 @@ "submit": "Guardar" }, "delete": { - "button": "Borrar", - "subtitle": "Eliminar el rol", + "button": "Eliminar el rol", "confirmAlert": { "title": "Eliminar el rol", "message": "¿Realmente desea borrar el rol? Todos los usuarios de este rol perderń sus permisos.", diff --git a/scm-ui/ui-webapp/public/locales/es/groups.json b/scm-ui/ui-webapp/public/locales/es/groups.json index 0ce3e7765a..f62cfc62cb 100644 --- a/scm-ui/ui-webapp/public/locales/es/groups.json +++ b/scm-ui/ui-webapp/public/locales/es/groups.json @@ -60,8 +60,7 @@ } }, "deleteGroup": { - "subtitle": "Borrar grupo", - "button": "Borrar", + "button": "Borrar grupo", "confirmAlert": { "title": "Borrar grupo", "message": "¿Realmente desea borrar el grupo?", diff --git a/scm-ui/ui-webapp/public/locales/es/repos.json b/scm-ui/ui-webapp/public/locales/es/repos.json index c3bf57c630..3b2451cceb 100644 --- a/scm-ui/ui-webapp/public/locales/es/repos.json +++ b/scm-ui/ui-webapp/public/locales/es/repos.json @@ -114,7 +114,7 @@ "size": "tamaño" }, "noSources": "No se han encontrado fuentes para esta rama.", - "extension" : { + "extension": { "notBound": "Sin extensión conectada." } }, @@ -166,8 +166,7 @@ } }, "deleteRepo": { - "subtitle": "Borrar repositorio", - "button": "Borrar", + "button": "Borrar repositorio", "confirmAlert": { "title": "Borrar repositorio", "message": "¿Realmente desea borrar el repositorio?", @@ -178,7 +177,7 @@ "diff": { "changes": { "add": "añadido", - "delete": "borrado", + "delete": "borrado", "modify": "modificado", "rename": "renombrado", "copy": "copiado" diff --git a/scm-ui/ui-webapp/public/locales/es/users.json b/scm-ui/ui-webapp/public/locales/es/users.json index d5ea97b95a..7c8fa4d35e 100644 --- a/scm-ui/ui-webapp/public/locales/es/users.json +++ b/scm-ui/ui-webapp/public/locales/es/users.json @@ -45,8 +45,7 @@ "subtitle": "Crear un nuevo usuario" }, "deleteUser": { - "subtitle": "Borrar usuario", - "button": "Borrar", + "button": "Borrar usuario", "confirmAlert": { "title": "Borrar usuario", "message": "¿Realmente desea borrar el usuario?", diff --git a/scm-ui/ui-webapp/src/admin/components/form/ConfigForm.tsx b/scm-ui/ui-webapp/src/admin/components/form/ConfigForm.tsx index f7f8f67659..6c87f4359b 100644 --- a/scm-ui/ui-webapp/src/admin/components/form/ConfigForm.tsx +++ b/scm-ui/ui-webapp/src/admin/components/form/ConfigForm.tsx @@ -1,7 +1,7 @@ import React from "react"; import { WithTranslation, withTranslation } from "react-i18next"; import { NamespaceStrategies, Config } from "@scm-manager/ui-types"; -import { SubmitButton, Notification } from "@scm-manager/ui-components"; +import { Level, SubmitButton, Notification } from "@scm-manager/ui-components"; import ProxySettings from "./ProxySettings"; import GeneralSettings from "./GeneralSettings"; import BaseUrlSettings from "./BaseUrlSettings"; @@ -151,10 +151,14 @@ class ConfigForm extends React.Component { hasUpdatePermission={configUpdatePermission} />
- + } /> ); diff --git a/scm-ui/ui-webapp/src/admin/roles/components/AvailableVerbs.tsx b/scm-ui/ui-webapp/src/admin/roles/components/AvailableVerbs.tsx index b230444de5..ec0e1fda29 100644 --- a/scm-ui/ui-webapp/src/admin/roles/components/AvailableVerbs.tsx +++ b/scm-ui/ui-webapp/src/admin/roles/components/AvailableVerbs.tsx @@ -13,15 +13,13 @@ class AvailableVerbs extends React.Component { let verbs = null; if (role.verbs.length > 0) { verbs = ( - - -
    - {role.verbs.map(verb => { - return
  • {t("verbs.repository." + verb + ".displayName")}
  • ; - })} -
- - + +
    + {role.verbs.map((verb, key) => { + return
  • {t("verbs.repository." + verb + ".displayName")}
  • ; + })} +
+ ); } return verbs; diff --git a/scm-ui/ui-webapp/src/admin/roles/components/PermissionRoleDetails.tsx b/scm-ui/ui-webapp/src/admin/roles/components/PermissionRoleDetails.tsx index e4a2a0f05c..f6e0bf35d6 100644 --- a/scm-ui/ui-webapp/src/admin/roles/components/PermissionRoleDetails.tsx +++ b/scm-ui/ui-webapp/src/admin/roles/components/PermissionRoleDetails.tsx @@ -2,7 +2,7 @@ import React from "react"; import { WithTranslation, withTranslation } from "react-i18next"; import { ExtensionPoint } from "@scm-manager/ui-extensions"; import { RepositoryRole } from "@scm-manager/ui-types"; -import { Button } from "@scm-manager/ui-components"; +import { Level, Button } from "@scm-manager/ui-components"; import PermissionRoleDetailsTable from "./PermissionRoleDetailsTable"; type Props = WithTranslation & { @@ -14,7 +14,12 @@ class PermissionRoleDetails extends React.Component { renderEditButton() { const { t, url } = this.props; if (!!this.props.role._links.update) { - return
); diff --git a/scm-ui/ui-webapp/src/permissions/components/PermissionCheckbox.tsx b/scm-ui/ui-webapp/src/permissions/components/PermissionCheckbox.tsx index 505d65d7d1..3223336099 100644 --- a/scm-ui/ui-webapp/src/permissions/components/PermissionCheckbox.tsx +++ b/scm-ui/ui-webapp/src/permissions/components/PermissionCheckbox.tsx @@ -3,24 +3,34 @@ import { WithTranslation, withTranslation } from "react-i18next"; import { Checkbox } from "@scm-manager/ui-components"; type Props = WithTranslation & { - permission: string; + name: string; checked: boolean; - onChange: (value: boolean, name: string) => void; + onChange?: (value: boolean, name?: string) => void; disabled: boolean; + role?: boolean; }; class PermissionCheckbox extends React.Component { render() { - const { t, permission, checked, onChange, disabled } = this.props; - const key = permission.split(":").join("."); + const { name, checked, onChange, disabled, role, t } = this.props; + + const key = name.split(":").join("."); + const label = role + ? t("verbs.repository." + name + ".displayName") + : this.translateOrDefault("permissions." + key + ".displayName", key); + const helpText = role + ? t("verbs.repository." + name + ".description") + : this.translateOrDefault("permissions." + key + ".description", t("permissions.unknown")); + return ( ); } diff --git a/scm-ui/ui-webapp/src/permissions/components/PermissionsWrapper.tsx b/scm-ui/ui-webapp/src/permissions/components/PermissionsWrapper.tsx new file mode 100644 index 0000000000..c5d0a90ae0 --- /dev/null +++ b/scm-ui/ui-webapp/src/permissions/components/PermissionsWrapper.tsx @@ -0,0 +1,63 @@ +import React from "react"; +import classNames from "classnames"; +import styled from "styled-components"; +import PermissionCheckbox from "./PermissionCheckbox"; +import { Loading } from "@scm-manager/ui-components"; + +type Props = { + permissions: { + [key: string]: boolean; + }; + onChange: (value: boolean, name: string) => void; + disabled: boolean; + role?: boolean; +}; + +const StyledWrapper = styled.div` + padding-bottom: 0; + + & .field .control { + width: 100%; + word-wrap: break-word; + } +`; + +export default class PermissionsWrapper extends React.Component { + render() { + const { permissions, onChange, disabled, role } = this.props; + + if (!permissions) { + return ; + } + + const permissionArray = Object.keys(permissions); + return ( +
+ + {permissionArray.slice(0, permissionArray.length / 2 + 1).map(p => ( + + ))} + + + {permissionArray.slice(permissionArray.length / 2 + 1, permissionArray.length).map(p => ( + + ))} + +
+ ); + } +} diff --git a/scm-ui/ui-webapp/src/permissions/components/SetPermissions.tsx b/scm-ui/ui-webapp/src/permissions/components/SetPermissions.tsx index e9db6cac17..83c3b2e284 100644 --- a/scm-ui/ui-webapp/src/permissions/components/SetPermissions.tsx +++ b/scm-ui/ui-webapp/src/permissions/components/SetPermissions.tsx @@ -1,13 +1,11 @@ import React from "react"; import { connect } from "react-redux"; import { WithTranslation, withTranslation } from "react-i18next"; -import classNames from "classnames"; -import styled from "styled-components"; import { Link } from "@scm-manager/ui-types"; -import { Notification, ErrorNotification, SubmitButton } from "@scm-manager/ui-components"; +import { Notification, ErrorNotification, SubmitButton, Level } from "@scm-manager/ui-components"; import { getLink } from "../../modules/indexResource"; import { loadPermissionsForEntity, setPermissions } from "./handlePermissions"; -import PermissionCheckbox from "./PermissionCheckbox"; +import PermissionsWrapper from "./PermissionsWrapper"; type Props = WithTranslation & { availablePermissionLink: string; @@ -25,15 +23,6 @@ type State = { overwritePermissionsLink?: Link; }; -const PermissionsWrapper = styled.div` - padding-bottom: 0; - - & .field .control { - width: 100%; - word-wrap: break-word; - } -`; - class SetPermissions extends React.Component { constructor(props: Props) { super(props); @@ -43,7 +32,6 @@ class SetPermissions extends React.Component { loading: true, permissionsChanged: false, permissionsSubmitted: false, - modifiable: false, overwritePermissionsLink: undefined }; } @@ -125,39 +113,23 @@ class SetPermissions extends React.Component {
{message} {this.renderPermissions()} - + + } + /> ); } renderPermissions = () => { const { overwritePermissionsLink, permissions } = this.state; - const permissionArray = Object.keys(permissions); return ( -
- - {permissionArray.slice(0, permissionArray.length / 2 + 1).map(p => ( - - ))} - - - {permissionArray.slice(permissionArray.length / 2 + 1, permissionArray.length).map(p => ( - - ))} - -
+ ); }; diff --git a/scm-ui/ui-webapp/src/repos/components/form/RepositoryForm.tsx b/scm-ui/ui-webapp/src/repos/components/form/RepositoryForm.tsx index 681b2c91f2..37fd072880 100644 --- a/scm-ui/ui-webapp/src/repos/components/form/RepositoryForm.tsx +++ b/scm-ui/ui-webapp/src/repos/components/form/RepositoryForm.tsx @@ -2,7 +2,7 @@ import React from "react"; import { WithTranslation, withTranslation } from "react-i18next"; import { ExtensionPoint } from "@scm-manager/ui-extensions"; import { Repository, RepositoryType } from "@scm-manager/ui-types"; -import { Subtitle, InputField, Select, SubmitButton, Textarea } from "@scm-manager/ui-components"; +import { Subtitle, InputField, Select, Textarea, Level, SubmitButton } from "@scm-manager/ui-components"; import * as validator from "./repositoryValidation"; type Props = WithTranslation & { @@ -52,9 +52,8 @@ class RepositoryForm extends React.Component { } } - isFalsy(value) { + isFalsy(value: string) { return !value; - } isValid = () => { @@ -91,7 +90,7 @@ class RepositoryForm extends React.Component { const disabled = !this.isModifiable() && !this.isCreateMode(); const submitButton = disabled ? null : ( - + } /> ); let subtitle = null; diff --git a/scm-ui/ui-webapp/src/repos/containers/DeleteRepo.tsx b/scm-ui/ui-webapp/src/repos/containers/DeleteRepo.tsx index 83220b97b8..a8b8c97f84 100644 --- a/scm-ui/ui-webapp/src/repos/containers/DeleteRepo.tsx +++ b/scm-ui/ui-webapp/src/repos/containers/DeleteRepo.tsx @@ -4,7 +4,7 @@ import { withRouter } from "react-router-dom"; import { WithTranslation, withTranslation } from "react-i18next"; import { History } from "history"; import { Repository } from "@scm-manager/ui-types"; -import { Subtitle, DeleteButton, confirmAlert, ErrorNotification } from "@scm-manager/ui-components"; +import { Level, DeleteButton, confirmAlert, ErrorNotification } from "@scm-manager/ui-components"; import { deleteRepo, getDeleteRepoFailure, isDeleteRepoPending } from "../modules/repos"; type Props = WithTranslation & { @@ -65,13 +65,8 @@ class DeleteRepo extends React.Component { return ( <>
- -
-
- -
-
+ } /> ); } diff --git a/scm-ui/ui-webapp/src/repos/permissions/components/PermissionCheckbox.tsx b/scm-ui/ui-webapp/src/repos/permissions/components/PermissionCheckbox.tsx deleted file mode 100644 index 2f677d4deb..0000000000 --- a/scm-ui/ui-webapp/src/repos/permissions/components/PermissionCheckbox.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react"; -import { WithTranslation, withTranslation } from "react-i18next"; -import { Checkbox } from "@scm-manager/ui-components"; - -type Props = WithTranslation & { - disabled: boolean; - name: string; - checked: boolean; - onChange?: (value: boolean, name?: string) => void; -}; - -class PermissionCheckbox extends React.Component { - render() { - const { t } = this.props; - return ( - - ); - } -} - -export default withTranslation("plugins")(PermissionCheckbox); diff --git a/scm-ui/ui-webapp/src/repos/permissions/containers/AdvancedPermissionsDialog.tsx b/scm-ui/ui-webapp/src/repos/permissions/containers/AdvancedPermissionsDialog.tsx index aa4d7aaa07..5ab3461638 100644 --- a/scm-ui/ui-webapp/src/repos/permissions/containers/AdvancedPermissionsDialog.tsx +++ b/scm-ui/ui-webapp/src/repos/permissions/containers/AdvancedPermissionsDialog.tsx @@ -1,7 +1,7 @@ import React from "react"; import { WithTranslation, withTranslation } from "react-i18next"; import { ButtonGroup, Button, SubmitButton, Modal } from "@scm-manager/ui-components"; -import PermissionCheckbox from "../components/PermissionCheckbox"; +import PermissionCheckbox from "../../../permissions/components/PermissionCheckbox"; type Props = WithTranslation & { readOnly: boolean; @@ -33,7 +33,14 @@ class AdvancedPermissionsDialog extends React.Component { const { verbs } = this.state; const verbSelectBoxes = Object.entries(verbs).map(e => ( - + )); const submitButton = !readOnly ? : null; diff --git a/scm-ui/ui-webapp/src/repos/permissions/containers/CreatePermissionForm.tsx b/scm-ui/ui-webapp/src/repos/permissions/containers/CreatePermissionForm.tsx index ed9c79b65f..447ef5ec68 100644 --- a/scm-ui/ui-webapp/src/repos/permissions/containers/CreatePermissionForm.tsx +++ b/scm-ui/ui-webapp/src/repos/permissions/containers/CreatePermissionForm.tsx @@ -6,6 +6,7 @@ import { GroupAutocomplete, LabelWithHelpIcon, Radio, + Level, SubmitButton, Subtitle, UserAutocomplete @@ -141,8 +142,8 @@ class CreatePermissionForm extends React.Component {
-
{this.renderAutocompletionField()}
-
+
{this.renderAutocompletionField()}
+
{
-
-
+ -
-
+ } + /> ); diff --git a/scm-ui/ui-webapp/src/repos/sources/components/content/FileButtonAddons.tsx b/scm-ui/ui-webapp/src/repos/sources/components/content/FileButtonAddons.tsx index dd52604611..dd0183d51d 100644 --- a/scm-ui/ui-webapp/src/repos/sources/components/content/FileButtonAddons.tsx +++ b/scm-ui/ui-webapp/src/repos/sources/components/content/FileButtonAddons.tsx @@ -18,7 +18,7 @@ class FileButtonAddons extends React.Component { }; color = (selected: boolean) => { - return selected ? "link is-selected" : null; + return selected ? "link is-selected" : ""; }; render() { @@ -27,14 +27,14 @@ class FileButtonAddons extends React.Component { return (
-
-
-
-
- -
-
+ } /> ); diff --git a/scm-ui/ui-webapp/src/users/containers/DeleteUser.tsx b/scm-ui/ui-webapp/src/users/containers/DeleteUser.tsx index 15beba3c49..6feafaaf91 100644 --- a/scm-ui/ui-webapp/src/users/containers/DeleteUser.tsx +++ b/scm-ui/ui-webapp/src/users/containers/DeleteUser.tsx @@ -4,7 +4,7 @@ import { withRouter } from "react-router-dom"; import { WithTranslation, withTranslation } from "react-i18next"; import { History } from "history"; import { User } from "@scm-manager/ui-types"; -import { Subtitle, DeleteButton, confirmAlert, ErrorNotification } from "@scm-manager/ui-components"; +import { Level, DeleteButton, confirmAlert, ErrorNotification } from "@scm-manager/ui-components"; import { deleteUser, getDeleteUserFailure, isDeleteUserPending } from "../modules/users"; type Props = WithTranslation & { @@ -64,13 +64,9 @@ class DeleteUser extends React.Component { return ( <> - +
-
-
- -
-
+ } /> ); } diff --git a/scm-ui/ui-webapp/src/users/containers/EditUser.tsx b/scm-ui/ui-webapp/src/users/containers/EditUser.tsx index e2594caa44..81f639535c 100644 --- a/scm-ui/ui-webapp/src/users/containers/EditUser.tsx +++ b/scm-ui/ui-webapp/src/users/containers/EditUser.tsx @@ -41,7 +41,6 @@ class EditUser extends React.Component {
this.modifyUser(user)} user={user} loading={loading} /> -
); diff --git a/scm-webapp/src/main/java/sonia/scm/lifecycle/BootstrapContextListener.java b/scm-webapp/src/main/java/sonia/scm/lifecycle/BootstrapContextListener.java index 5b9f40dbc2..e3fd5528eb 100644 --- a/scm-webapp/src/main/java/sonia/scm/lifecycle/BootstrapContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/lifecycle/BootstrapContextListener.java @@ -88,14 +88,16 @@ public class BootstrapContextListener extends GuiceServletContextListener { protected Injector getInjector() { Throwable startupError = SCMContext.getContext().getStartupError(); if (startupError != null) { + LOG.error("received unrecoverable error during startup", startupError); return createStageOneInjector(SingleView.error(startupError)); } else if (Versions.isTooOld()) { - LOG.error("Existing version is too old and cannot be migrated to new version. Please update to version {} first", Versions.MIN_VERSION); + LOG.error("existing version is too old and cannot be migrated to new version. Please update to version {} first", Versions.MIN_VERSION); return createStageOneInjector(SingleView.view("/templates/too-old.mustache", HttpServletResponse.SC_CONFLICT)); } else { try { return createStageTwoInjector(); } catch (Exception ex) { + LOG.error("failed to create stage two injector", ex); return createStageOneInjector(SingleView.error(ex)); } } diff --git a/scm-webapp/src/main/java/sonia/scm/net/ahc/DefaultAdvancedHttpClient.java b/scm-webapp/src/main/java/sonia/scm/net/ahc/DefaultAdvancedHttpClient.java index df6c93515b..161abf54c6 100644 --- a/scm-webapp/src/main/java/sonia/scm/net/ahc/DefaultAdvancedHttpClient.java +++ b/scm-webapp/src/main/java/sonia/scm/net/ahc/DefaultAdvancedHttpClient.java @@ -38,39 +38,27 @@ import com.google.common.base.Strings; import com.google.common.collect.Multimap; import com.google.common.io.Closeables; import com.google.inject.Inject; - import org.apache.shiro.codec.Base64; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.config.ScmConfiguration; import sonia.scm.net.Proxies; import sonia.scm.net.TrustAllHostnameVerifier; import sonia.scm.net.TrustAllTrustManager; import sonia.scm.util.HttpUtil; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; -import java.io.OutputStream; - -import java.net.HttpURLConnection; -import java.net.InetSocketAddress; -import java.net.ProtocolException; -import java.net.Proxy; -import java.net.SocketAddress; -import java.net.URL; - -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; - -import java.util.Set; import javax.inject.Provider; - import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; +import java.io.IOException; +import java.io.OutputStream; +import java.net.*; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.Set; + +//~--- JDK imports ------------------------------------------------------------ /** * Default implementation of the {@link AdvancedHttpClient}. The default @@ -324,11 +312,7 @@ public class DefaultAdvancedHttpClient extends AdvancedHttpClient sc.init(null, trustAllCerts, new java.security.SecureRandom()); connection.setSSLSocketFactory(sc.getSocketFactory()); } - catch (KeyManagementException ex) - { - logger.error("could not disable certificate validation", ex); - } - catch (NoSuchAlgorithmException ex) + catch (KeyManagementException | NoSuchAlgorithmException ex) { logger.error("could not disable certificate validation", ex); } diff --git a/scm-webapp/src/main/java/sonia/scm/net/ahc/XmlContentTransformer.java b/scm-webapp/src/main/java/sonia/scm/net/ahc/XmlContentTransformer.java index 84dcda3593..71fbb489b1 100644 --- a/scm-webapp/src/main/java/sonia/scm/net/ahc/XmlContentTransformer.java +++ b/scm-webapp/src/main/java/sonia/scm/net/ahc/XmlContentTransformer.java @@ -34,20 +34,17 @@ package sonia.scm.net.ahc; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.io.ByteSource; - import sonia.scm.plugin.Extension; import sonia.scm.util.IOUtil; -//~--- JDK imports ------------------------------------------------------------ - +import javax.ws.rs.core.MediaType; +import javax.xml.bind.DataBindingException; +import javax.xml.bind.JAXB; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import javax.ws.rs.core.MediaType; - -import javax.xml.bind.DataBindingException; -import javax.xml.bind.JAXB; +//~--- JDK imports ------------------------------------------------------------ /** * {@link ContentTransformer} for xml. The {@link XmlContentTransformer} uses @@ -96,15 +93,10 @@ public class XmlContentTransformer implements ContentTransformer stream = content.openBufferedStream(); object = JAXB.unmarshal(stream, type); } - catch (IOException ex) + catch (IOException | DataBindingException ex) { throw new ContentTransformerException("could not unmarshall content", ex); - } - catch (DataBindingException ex) - { - throw new ContentTransformerException("could not unmarshall content", ex); - } - finally + } finally { IOUtil.close(stream); } diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java index b74b17cd88..f57d932e1e 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java @@ -248,6 +248,7 @@ public class DefaultPluginManager implements PluginManager { try { Thread.sleep(200); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); } eventBus.post(new RestartEvent(PluginManager.class, cause)); }).start(); diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/MultiParentClassLoader.java b/scm-webapp/src/main/java/sonia/scm/plugin/MultiParentClassLoader.java index 5881652ec4..ebd8b6e24e 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/MultiParentClassLoader.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/MultiParentClassLoader.java @@ -74,7 +74,7 @@ public class MultiParentClassLoader extends ClassLoader public MultiParentClassLoader(Collection parents) { super(null); - this.parents = new CopyOnWriteArrayList(parents); + this.parents = new CopyOnWriteArrayList<>(parents); } //~--- get methods ---------------------------------------------------------- diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/PluginCenterDto.java b/scm-webapp/src/main/java/sonia/scm/plugin/PluginCenterDto.java index 1a18d696d5..d7b11b5ade 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/PluginCenterDto.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/PluginCenterDto.java @@ -53,7 +53,7 @@ public final class PluginCenterDto implements Serializable { private String category; private String author; private String avatarUrl; - private String sha256; + private String sha256sum; @XmlElement(name = "conditions") private Condition conditions; diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/PluginCenterDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/plugin/PluginCenterDtoMapper.java index 1b84bca147..56a27a73af 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/PluginCenterDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/PluginCenterDtoMapper.java @@ -19,7 +19,7 @@ public abstract class PluginCenterDtoMapper { for (PluginCenterDto.Plugin plugin : pluginCenterDto.getEmbedded().getPlugins()) { String url = plugin.getLinks().get("download").getHref(); AvailablePluginDescriptor descriptor = new AvailablePluginDescriptor( - map(plugin), map(plugin.getConditions()), plugin.getDependencies(), url, plugin.getSha256() + map(plugin), map(plugin.getConditions()), plugin.getDependencies(), url, plugin.getSha256sum() ); plugins.add(new AvailablePlugin(descriptor)); } diff --git a/scm-webapp/src/main/java/sonia/scm/repository/HealthCheckContextListener.java b/scm-webapp/src/main/java/sonia/scm/repository/HealthCheckContextListener.java index a0918c3e64..146382771e 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/HealthCheckContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/HealthCheckContextListener.java @@ -128,15 +128,7 @@ public class HealthCheckContextListener implements ServletContextListener { // excute health checks for all repsitories asynchronous - SecurityUtils.getSubject().execute(new Runnable() - { - - @Override - public void run() - { - healthChecker.checkAll(); - } - }); + SecurityUtils.getSubject().execute(healthChecker::checkAll); } //~--- fields ------------------------------------------------------------- diff --git a/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java b/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java index 54cf7991c5..f0396741aa 100644 --- a/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java +++ b/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java @@ -35,18 +35,14 @@ package sonia.scm.cache; //~--- non-JDK imports -------------------------------------------------------- -import com.google.common.base.Predicate; - import org.junit.After; +import org.junit.Assume; import org.junit.Before; import org.junit.Test; - import sonia.scm.util.IOUtil; -import static org.hamcrest.Matchers.*; - +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.junit.Assert.*; -import org.junit.Assume; /** * @@ -166,14 +162,7 @@ public abstract class CacheTestBase cache.put("a-1", "test123"); cache.put("a-2", "test123"); - Iterable previous = cache.removeAll(new Predicate() - { - @Override - public boolean apply(String item) - { - return item.startsWith("test"); - } - }); + Iterable previous = cache.removeAll(item -> item != null && item.startsWith("test")); assertThat(previous, containsInAnyOrder("test123", "test456")); assertNull(cache.get("test-1")); @@ -188,8 +177,8 @@ public abstract class CacheTestBase // skip test if implementation does not support stats Assume.assumeTrue( stats != null ); assertEquals("test", stats.getName()); - assertEquals(0l, stats.getHitCount()); - assertEquals(0l, stats.getMissCount()); + assertEquals(0L, stats.getHitCount()); + assertEquals(0L, stats.getMissCount()); cache.put("test-1", "test123"); cache.put("test-2", "test456"); cache.get("test-1"); @@ -197,11 +186,11 @@ public abstract class CacheTestBase cache.get("test-1"); cache.get("test-3"); // check that stats have not changed - assertEquals(0l, stats.getHitCount()); - assertEquals(0l, stats.getMissCount()); + assertEquals(0L, stats.getHitCount()); + assertEquals(0L, stats.getMissCount()); stats = cache.getStatistics(); - assertEquals(3l, stats.getHitCount()); - assertEquals(1l, stats.getMissCount()); + assertEquals(3L, stats.getHitCount()); + assertEquals(1L, stats.getMissCount()); assertEquals(0.75d, stats.getHitRate(), 0.0d); assertEquals(0.25d, stats.getMissRate(), 0.0d); } diff --git a/scm-webapp/src/test/java/sonia/scm/cache/GuavaConfigurationReaderTest.java b/scm-webapp/src/test/java/sonia/scm/cache/GuavaConfigurationReaderTest.java index 7f7be94203..ff8b59cfc3 100644 --- a/scm-webapp/src/test/java/sonia/scm/cache/GuavaConfigurationReaderTest.java +++ b/scm-webapp/src/test/java/sonia/scm/cache/GuavaConfigurationReaderTest.java @@ -63,7 +63,7 @@ public class GuavaConfigurationReaderTest GuavaCacheConfiguration cfg = readConfiguration("gcache.001.xml").getDefaultCache(); - assertCacheValues(cfg, 200l, 1200l, 2400l); + assertCacheValues(cfg, 200L, 1200L, 2400L); } /** @@ -82,10 +82,10 @@ public class GuavaConfigurationReaderTest //J+ // cache sonia.test.cache.001 override by cache.004.xml - assertCacheValues(getCache(gcm, "sonia.test.cache.001"), 6l, 2l, 8l); - assertCacheValues(getCache(gcm, "sonia.test.cache.002"), 1000l, 120l, 60l); - assertCacheValues(getCache(gcm, "sonia.test.cache.003"), 3000l, 120l, - 2400l); + assertCacheValues(getCache(gcm, "sonia.test.cache.001"), 6L, 2L, 8L); + assertCacheValues(getCache(gcm, "sonia.test.cache.002"), 1000L, 120L, 60L); + assertCacheValues(getCache(gcm, "sonia.test.cache.003"), 3000L, 120L, + 2400L); } /** @@ -100,8 +100,8 @@ public class GuavaConfigurationReaderTest // check default - assertCacheValues(getCache(gcm, "sonia.test.cache.001"), 1000l, 60l, 30l); - assertCacheValues(getCache(gcm, "sonia.test.cache.002"), 1000l, 120l, 60l); + assertCacheValues(getCache(gcm, "sonia.test.cache.001"), 1000L, 60L, 30L); + assertCacheValues(getCache(gcm, "sonia.test.cache.002"), 1000L, 120L, 60L); } /** @@ -115,10 +115,10 @@ public class GuavaConfigurationReaderTest Iterators.forArray("gcache.002.xml", "gcache.003.xml")); - assertCacheValues(getCache(gcm, "sonia.test.cache.001"), 1000l, 60l, 30l); - assertCacheValues(getCache(gcm, "sonia.test.cache.002"), 1000l, 120l, 60l); - assertCacheValues(getCache(gcm, "sonia.test.cache.003"), 3000l, 120l, - 2400l); + assertCacheValues(getCache(gcm, "sonia.test.cache.001"), 1000L, 60L, 30L); + assertCacheValues(getCache(gcm, "sonia.test.cache.002"), 1000L, 120L, 60L); + assertCacheValues(getCache(gcm, "sonia.test.cache.003"), 3000L, 120L, + 2400L); } /** @@ -131,7 +131,7 @@ public class GuavaConfigurationReaderTest GuavaCacheConfiguration cfg = readConfiguration("gcache.001.xml").getCaches().get(0); - assertCacheValues(cfg, 1000l, 60l, 30l); + assertCacheValues(cfg, 1000L, 60L, 30L); } /** @@ -144,7 +144,7 @@ public class GuavaConfigurationReaderTest GuavaCacheConfiguration cfg = readConfiguration("gcache.002.xml").getCaches().get(0); - assertCacheValues(cfg, 1000l, 120l, 60l); + assertCacheValues(cfg, 1000L, 120L, 60L); } /** diff --git a/scm-webapp/src/test/java/sonia/scm/security/ConfigurableLoginAttemptHandlerTest.java b/scm-webapp/src/test/java/sonia/scm/security/ConfigurableLoginAttemptHandlerTest.java index 714438b8fe..01c4766396 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/ConfigurableLoginAttemptHandlerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/ConfigurableLoginAttemptHandlerTest.java @@ -74,7 +74,7 @@ public class ConfigurableLoginAttemptHandlerTest { handler.onUnsuccessfulAuthentication(token, new SimpleAuthenticationInfo()); handler.beforeAuthentication(token); handler.onUnsuccessfulAuthentication(token, new SimpleAuthenticationInfo()); - Thread.sleep(TimeUnit.MILLISECONDS.toMillis(1200l)); + Thread.sleep(TimeUnit.MILLISECONDS.toMillis(1200L)); handler.beforeAuthentication(token); } @@ -111,4 +111,4 @@ public class ConfigurableLoginAttemptHandlerTest { return new ConfigurableLoginAttemptHandler(configuration); } -} \ No newline at end of file +} diff --git a/scm-webapp/src/test/java/sonia/scm/security/DefaultKeyGeneratorTest.java b/scm-webapp/src/test/java/sonia/scm/security/DefaultKeyGeneratorTest.java index edec43098c..57b038d5f1 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/DefaultKeyGeneratorTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/DefaultKeyGeneratorTest.java @@ -35,22 +35,15 @@ package sonia.scm.security; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.collect.Sets; - import org.junit.Test; +import java.util.Set; +import java.util.concurrent.*; + import static org.junit.Assert.*; //~--- JDK imports ------------------------------------------------------------ -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - /** * * @author Sebastian Sdorra @@ -96,28 +89,22 @@ public class DefaultKeyGeneratorTest for (int i = 0; i < 10; i++) { - Future> future = executor.submit(new Callable>() - { + Future> future = executor.submit(() -> { + Set keys = Sets.newHashSet(); - @Override - public Set call() + for (int i1 = 0; i1 < 1000; i1++) { - Set keys = Sets.newHashSet(); + String key = generator.createKey(); - for (int i = 0; i < 1000; i++) + if (keys.contains(key)) { - String key = generator.createKey(); - - if (keys.contains(key)) - { - fail("dublicate key"); - } - - keys.add(key); + fail("dublicate key"); } - return keys; + keys.add(key); } + + return keys; }); futureSet.add(future); diff --git a/scm-webapp/src/test/java/sonia/scm/template/MustacheTemplateTest.java b/scm-webapp/src/test/java/sonia/scm/template/MustacheTemplateTest.java index 186b809367..bfac40b4df 100644 --- a/scm-webapp/src/test/java/sonia/scm/template/MustacheTemplateTest.java +++ b/scm-webapp/src/test/java/sonia/scm/template/MustacheTemplateTest.java @@ -89,15 +89,8 @@ public class MustacheTemplateTest extends TemplateTestBase @Override protected void prepareEnv(Map env) { - env.put("test", new Function() - { - - @Override - public String apply(String input) - { - throw new UnsupportedOperationException("Not supported yet."); - } - + env.put("test", (Function) input -> { + throw new UnsupportedOperationException("Not supported yet."); }); }