From 562e4e6bb49fffac66b89c79fe621644e5ae3c33 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 25 Feb 2014 08:04:31 +0100 Subject: [PATCH 01/46] allow retrieving repositories by using type/name instead of repository id --- .../scm/cli/cmd/GetRepositorySubCommand.java | 19 +++++++++++++++++-- .../resources/sonia/resources/i18n.properties | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GetRepositorySubCommand.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GetRepositorySubCommand.java index c7c497bacf..2e8227fa60 100644 --- a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GetRepositorySubCommand.java +++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GetRepositorySubCommand.java @@ -98,7 +98,22 @@ public class GetRepositorySubCommand extends TemplateSubCommand protected void run() { ScmClientSession session = createSession(); - Repository repository = session.getRepositoryHandler().get(id); + + Repository repository; + + int index = id.indexOf("/"); + + if (index > 0) + { + String type = id.substring(0, index); + String name = id.substring(index + 1); + + repository = session.getRepositoryHandler().get(type, name); + } + else + { + repository = session.getRepositoryHandler().get(id); + } if (repository != null) { @@ -117,7 +132,7 @@ public class GetRepositorySubCommand extends TemplateSubCommand /** Field description */ @Argument( - usage = "optionRepositoryId", + usage = "optionRepositoryIdOrTypeAndName", metaVar = "repositoryid", required = true ) diff --git a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties index e80757638b..a094e88efc 100644 --- a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties +++ b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties @@ -44,6 +44,7 @@ optionLoggingLevel = Logging level (DEBUG, INFO, WARN, ERROR) optionTemplate = Template optionTemplateFile = Template file optionRepositoryId = Repository Id +optionRepositoryIdOrTypeAndName = Repository Id or type/name optionRepositoryName = Repository name optionRepositoryType = Repository name optionRepositoryContact = Repository contact From a175d736ae139d1d51a34f3eb109933fb053c55a Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 25 Feb 2014 08:37:54 +0100 Subject: [PATCH 02/46] fix changing passwords which a shorter than 5 chars, see issue #535 --- .../resources/js/action/sonia.action.changepasswordwindow.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scm-webapp/src/main/webapp/resources/js/action/sonia.action.changepasswordwindow.js b/scm-webapp/src/main/webapp/resources/js/action/sonia.action.changepasswordwindow.js index 35ba82adb2..b1c0a5372f 100644 --- a/scm-webapp/src/main/webapp/resources/js/action/sonia.action.changepasswordwindow.js +++ b/scm-webapp/src/main/webapp/resources/js/action/sonia.action.changepasswordwindow.js @@ -64,9 +64,7 @@ Sonia.action.ChangePasswordWindow = Ext.extend(Ext.Window,{ name: 'old-password', fieldLabel: this.oldPasswordText, inputType: 'password', - allowBlank: false, - minLength: 6, - maxLength: 32 + allowBlank: false },{ id: 'new-password', name: 'new-password', From 53514b9b34b3394c3b6684319f5e96053e6e82a7 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 8 Mar 2014 13:05:23 +0100 Subject: [PATCH 03/46] update jersey to version 1.18.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cdd8d13a67..64284d7a8c 100644 --- a/pom.xml +++ b/pom.xml @@ -421,7 +421,7 @@ 1.1.1 2.5 3.0 - 1.18 + 1.18.1 2.6.6 2.3.20 7.6.14.v20131031 From 29c08af782e91c0fedc3f200685ae3b1e23834e4 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 8 Mar 2014 13:06:30 +0100 Subject: [PATCH 04/46] update shiro to version 1.2.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 64284d7a8c..32b579e509 100644 --- a/pom.xml +++ b/pom.xml @@ -427,7 +427,7 @@ 7.6.14.v20131031 - 1.2.2 + 1.2.3 3.2.0.201312181205-r From 5873d81e0da1349f2911b5f801fde3b364646d88 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 8 Mar 2014 13:13:38 +0100 Subject: [PATCH 05/46] added missing since comments --- scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java | 2 ++ scm-core/src/main/java/sonia/scm/util/HttpUtil.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java b/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java index 35b13dd902..d9d1d8a119 100644 --- a/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java +++ b/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java @@ -370,6 +370,7 @@ public class ScmConfiguration * * * @return realm description + * @since 1.36 */ public String getRealmDescription() { @@ -741,6 +742,7 @@ public class ScmConfiguration * * * @param realmDescription + * @since 1.36 */ public void setRealmDescription(String realmDescription) { diff --git a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java index 69f913d74d..150d1a3ba4 100644 --- a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java @@ -443,6 +443,8 @@ public final class HttpUtil * @param realmDescription - realm description * * @throws IOException + * + * @since 1.36 */ public static void sendUnauthorized(HttpServletResponse response, String realmDescription) throws IOException From 39c9ec209077473b30f1cdac420701e3e5889310 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 8 Mar 2014 15:48:34 +0100 Subject: [PATCH 06/46] update jgit to 3.3.0.201403021825-r --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 32b579e509..96644bc882 100644 --- a/pom.xml +++ b/pom.xml @@ -430,7 +430,7 @@ 1.2.3 - 3.2.0.201312181205-r + 3.3.0.201403021825-r 1.8.3-scm1 From f41e0868258f31b542eb604f4fa06761a61b619b Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 8 Mar 2014 17:46:17 +0100 Subject: [PATCH 07/46] update svnkit to version 1.8.4-scm1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 96644bc882..57795b9cf6 100644 --- a/pom.xml +++ b/pom.xml @@ -431,7 +431,7 @@ 3.3.0.201403021825-r - 1.8.3-scm1 + 1.8.4-scm1 15.0 From dc0719404e13c8caed6433a3fa2eede432e9e438 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 8 Mar 2014 17:51:41 +0100 Subject: [PATCH 08/46] update args4j 2.0.26 --- scm-clients/scm-cli-client/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-clients/scm-cli-client/pom.xml b/scm-clients/scm-cli-client/pom.xml index c9568f2234..4a3721cc2a 100644 --- a/scm-clients/scm-cli-client/pom.xml +++ b/scm-clients/scm-cli-client/pom.xml @@ -41,7 +41,7 @@ args4j args4j - 2.0.25 + 2.0.26 From 4468382cc0f0d7dca8b4311acb687b5c651c9ee3 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 8 Mar 2014 20:29:18 +0100 Subject: [PATCH 09/46] solve classloading issues for plugin classes --- .../src/main/java/sonia/scm/io/DeepCopy.java | 21 ++- .../sonia/scm/io/ScmObjectInputStream.java | 123 ++++++++++++++++++ 2 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/io/ScmObjectInputStream.java diff --git a/scm-core/src/main/java/sonia/scm/io/DeepCopy.java b/scm-core/src/main/java/sonia/scm/io/DeepCopy.java index 0db3da01aa..a349b842fe 100644 --- a/scm-core/src/main/java/sonia/scm/io/DeepCopy.java +++ b/scm-core/src/main/java/sonia/scm/io/DeepCopy.java @@ -30,8 +30,13 @@ */ + package sonia.scm.io; +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.io.Closer; + //~--- JDK imports ------------------------------------------------------------ import java.io.IOException; @@ -69,12 +74,15 @@ public final class DeepCopy { T obj = null; + Closer closer = Closer.create(); + try { // Write the object out to a byte array - FastByteArrayOutputStream fbos = new FastByteArrayOutputStream(); - ObjectOutputStream out = new ObjectOutputStream(fbos); + FastByteArrayOutputStream fbos = + closer.register(new FastByteArrayOutputStream()); + ObjectOutputStream out = closer.register(new ObjectOutputStream(fbos)); out.writeObject(orig); out.flush(); @@ -82,7 +90,10 @@ public final class DeepCopy // Retrieve an input stream from the byte array and read // a copy of the object back in. - ObjectInputStream in = new ObjectInputStream(fbos.getInputStream()); + // use ScmObjectInputStream to solve ClassNotFoundException + // for plugin classes + ObjectInputStream in = + closer.register(new ScmObjectInputStream(fbos.getInputStream())); obj = (T) in.readObject(); } @@ -90,6 +101,10 @@ public final class DeepCopy { throw new IOException("could not copy object", ex); } + finally + { + closer.close(); + } return obj; } diff --git a/scm-core/src/main/java/sonia/scm/io/ScmObjectInputStream.java b/scm-core/src/main/java/sonia/scm/io/ScmObjectInputStream.java new file mode 100644 index 0000000000..603ac61c11 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/ScmObjectInputStream.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.io; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectStreamClass; + +/** + * {@link ObjectInputStream} implementation which uses the context class loader + * to resolve classes. + * + * @author Sebastian Sdorra + * @since 1.36 + */ +public class ScmObjectInputStream extends ObjectInputStream +{ + + /** + * the logger for ScmObjectInputStream + */ + private static final Logger logger = + LoggerFactory.getLogger(ScmObjectInputStream.class); + + //~--- constructors --------------------------------------------------------- + + /** + * {@inheritDoc} + */ + public ScmObjectInputStream(InputStream stream) throws IOException + { + super(stream); + } + + //~--- methods -------------------------------------------------------------- + + /** + * {@inheritDoc} + */ + @Override + protected Class resolveClass(ObjectStreamClass desc) + throws IOException, ClassNotFoundException + { + Class clazz = null; + ClassLoader classLoader = getClassLoader(); + + try + { + clazz = classLoader.loadClass(desc.getName()); + } + catch (ClassNotFoundException ex) + { + logger.warn("could not find class ".concat(desc.getName()), ex); + } + + if (clazz == null) + { + clazz = super.resolveClass(desc); + } + + return clazz; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Returns the context class loader if available. If the context class loader + * is not available the method will fall back to the class loader which has + * load this class. + * + * + * @return context class loader or default class loader + */ + private ClassLoader getClassLoader() + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + if (classLoader == null) + { + logger.debug("could not find context class loader, fall back to default"); + classLoader = ScmObjectInputStream.class.getClassLoader(); + } + + return classLoader; + } +} From 37c7f136a11c419e01b766d0790006c1b98059bf Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 8 Mar 2014 20:48:04 +0100 Subject: [PATCH 10/46] added unit test for DeepCopy --- .../test/java/sonia/scm/io/DeepCopyTest.java | 328 ++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 scm-core/src/test/java/sonia/scm/io/DeepCopyTest.java diff --git a/scm-core/src/test/java/sonia/scm/io/DeepCopyTest.java b/scm-core/src/test/java/sonia/scm/io/DeepCopyTest.java new file mode 100644 index 0000000000..f21c304d58 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/io/DeepCopyTest.java @@ -0,0 +1,328 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.io; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.base.Objects; + +import org.junit.Test; + +import static org.junit.Assert.*; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; +import java.io.Serializable; + +/** + * + * @author Sebastian Sdorra + */ +public class DeepCopyTest +{ + + /** + * Method description + * + * + * @throws IOException + */ + @Test + public void testDeepCopy() throws IOException + { + Person orig = new Person("Tricia", "McMillan", + new Address("Magrathea", "Mainstreet 3")); + Person copy = DeepCopy.copy(orig); + + assertNotSame(orig, copy); + assertEquals(orig, copy); + } + + /** + * Method description + * + * + * @throws IOException + */ + @Test(expected = IOException.class) + public void testDeepCopyNonSerializable() throws IOException + { + DeepCopy.copy(new NonSerializable()); + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 14/03/08 + * @author Enter your name here... + */ + private static class Address implements Serializable + { + + /** Field description */ + private static final long serialVersionUID = 3200816222378286310L; + + //~--- constructors ------------------------------------------------------- + + /** + * Constructs ... + * + */ + public Address() {} + + /** + * Constructs ... + * + * + * @param city + * @param street + */ + public Address(String city, String street) + { + this.city = city; + this.street = street; + } + + //~--- methods ------------------------------------------------------------ + + /** + * Method description + * + * + * @param obj + * + * @return + */ + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + final Address other = (Address) obj; + + return Objects.equal(city, other.city) + && Objects.equal(street, other.street); + } + + /** + * Method description + * + * + * @return + */ + @Override + public int hashCode() + { + return Objects.hashCode(city, street); + } + + //~--- get methods -------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getCity() + { + return city; + } + + /** + * Method description + * + * + * @return + */ + public String getStreet() + { + return street; + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private String city; + + /** Field description */ + private String street; + } + + + /** + * Class description + * + * + * @version Enter version here..., 14/03/08 + * @author Enter your name here... + */ + private static class NonSerializable {} + + + /** + * Class description + * + * + * @version Enter version here..., 14/03/08 + * @author Enter your name here... + */ + private static class Person implements Serializable + { + + /** Field description */ + private static final long serialVersionUID = -2098386757802626539L; + + //~--- constructors ------------------------------------------------------- + + /** + * Constructs ... + * + */ + public Person() {} + + /** + * Constructs ... + * + * + * @param firstname + * @param lastname + * @param address + */ + public Person(String firstname, String lastname, Address address) + { + this.firstname = firstname; + this.lastname = lastname; + this.address = address; + } + + //~--- methods ------------------------------------------------------------ + + /** + * Method description + * + * + * @param obj + * + * @return + */ + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + final Person other = (Person) obj; + + return Objects.equal(firstname, other.firstname) + && Objects.equal(lastname, other.lastname) + && Objects.equal(address, other.address); + } + + /** + * Method description + * + * + * @return + */ + @Override + public int hashCode() + { + return Objects.hashCode(firstname, lastname, address); + } + + //~--- get methods -------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public Address getAddress() + { + return address; + } + + /** + * Method description + * + * + * @return + */ + public String getFirstname() + { + return firstname; + } + + /** + * Method description + * + * + * @return + */ + public String getLastname() + { + return lastname; + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private Address address; + + /** Field description */ + private String firstname; + + /** Field description */ + private String lastname; + } +} From 64b44c5759ef78b80cac282bfa50c029375e58ca Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 8 Mar 2014 21:59:01 +0100 Subject: [PATCH 11/46] do not log class not found exceptions, because the parent method finds the class in most cases --- scm-core/src/main/java/sonia/scm/io/ScmObjectInputStream.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scm-core/src/main/java/sonia/scm/io/ScmObjectInputStream.java b/scm-core/src/main/java/sonia/scm/io/ScmObjectInputStream.java index 603ac61c11..a8ec919adf 100644 --- a/scm-core/src/main/java/sonia/scm/io/ScmObjectInputStream.java +++ b/scm-core/src/main/java/sonia/scm/io/ScmObjectInputStream.java @@ -87,7 +87,8 @@ public class ScmObjectInputStream extends ObjectInputStream } catch (ClassNotFoundException ex) { - logger.warn("could not find class ".concat(desc.getName()), ex); + // do not log the exception, because the class + // is mostly found by the parent method. } if (clazz == null) From c133464cdfa8e629f5d9a750c1eaa5311555a9a6 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 9 Mar 2014 13:52:30 +0100 Subject: [PATCH 12/46] update commons-beanutils to version 1.9.1 --- scm-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 7ff34b4c81..920b70c7d1 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -164,7 +164,7 @@ commons-beanutils commons-beanutils - 1.8.3 + 1.9.1 commons-logging From 9b7bc962820707a20a23a51d1960f45b7cc6dfd2 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 9 Mar 2014 14:20:43 +0100 Subject: [PATCH 13/46] fix bug with some special chars --- .../java/sonia/scm/search/SearchUtil.java | 100 ++++++++++++++++-- .../java/sonia/scm/search/SearchUtilTest.java | 6 ++ 2 files changed, 100 insertions(+), 6 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/search/SearchUtil.java b/scm-core/src/main/java/sonia/scm/search/SearchUtil.java index c65af09250..90c65e3456 100644 --- a/scm-core/src/main/java/sonia/scm/search/SearchUtil.java +++ b/scm-core/src/main/java/sonia/scm/search/SearchUtil.java @@ -35,6 +35,9 @@ package sonia.scm.search; //~--- non-JDK imports -------------------------------------------------------- +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import sonia.scm.TransformFilter; import sonia.scm.util.Util; @@ -45,7 +48,6 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Locale; -import java.util.regex.Pattern; /** * @@ -54,6 +56,14 @@ import java.util.regex.Pattern; public final class SearchUtil { + /** + * the logger for SearchUtil + */ + private static final Logger logger = + LoggerFactory.getLogger(SearchUtil.class); + + //~--- constructors --------------------------------------------------------- + /** * Constructs ... * @@ -181,6 +191,77 @@ public final class SearchUtil return items; } + /** + * Method description + * + * + * @param pattern + * @param c + */ + private static void appendChar(StringBuilder pattern, char c) + { + switch (c) + { + case '*' : + pattern.append(".*"); + + break; + + case '?' : + pattern.append("."); + + break; + + case '(' : + pattern.append("\\("); + + break; + + case ')' : + pattern.append("\\)"); + + break; + + case '{' : + pattern.append("\\{"); + + break; + + case '}' : + pattern.append("\\}"); + + break; + + case '[' : + pattern.append("\\["); + + break; + + case ']' : + pattern.append("\\]"); + + break; + + case '|' : + pattern.append("\\|"); + + break; + + case '.' : + pattern.append("\\."); + + break; + + case '\\' : + pattern.append("\\\\"); + + break; + + default : + pattern.append(c); + } + } + /** * Method description * @@ -193,19 +274,26 @@ public final class SearchUtil { String query = request.getQuery().trim(); + StringBuilder pattern = new StringBuilder(); + if (request.isIgnoreCase()) { + pattern.append("(?i)"); query = query.toLowerCase(Locale.ENGLISH); } - query = query.replace("\\", "\\\\").replace("*", ".*").replace("?", "."); - query = ".*".concat(query).concat(".*"); + pattern.append(".*"); - if (request.isIgnoreCase()) + for (char c : query.toCharArray()) { - query = "(?i)".concat(query); + appendChar(pattern, c); } - return query; + pattern.append(".*"); + + logger.trace("converted query \"{}\" to regex pattern \"{}\"", + request.getQuery(), pattern); + + return pattern.toString(); } } diff --git a/scm-core/src/test/java/sonia/scm/search/SearchUtilTest.java b/scm-core/src/test/java/sonia/scm/search/SearchUtilTest.java index 8aebfa9dbd..0588729a45 100644 --- a/scm-core/src/test/java/sonia/scm/search/SearchUtilTest.java +++ b/scm-core/src/test/java/sonia/scm/search/SearchUtilTest.java @@ -177,6 +177,12 @@ public class SearchUtilTest "testhansolo")); assertFalse(SearchUtil.matchesAll(new SearchRequest("test\\hansolo"), "test\\hnsolo")); + assertTrue(SearchUtil.matchesAll(new SearchRequest("{test,hansolo} tst"), + "{test,hansolo} tst")); + assertTrue(SearchUtil.matchesAll(new SearchRequest("(test,hansolo) tst"), + "(test,hansolo) tst")); + assertTrue(SearchUtil.matchesAll(new SearchRequest("[test,hansolo] tst"), + "[test,hansolo] tst")); } /** From 2cb3e668db698534ce607459bffef00f839b33d7 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 9 Mar 2014 14:48:43 +0100 Subject: [PATCH 14/46] fix mercurial out of scope exception on startup --- .../sonia/scm/repository/HgHookManager.java | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java index bd3e065bd4..6107e33d05 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java @@ -35,8 +35,11 @@ package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- +import com.google.common.base.Objects; import com.google.inject.Inject; +import com.google.inject.OutOfScopeException; import com.google.inject.Provider; +import com.google.inject.ProvisionException; import com.google.inject.Singleton; import org.slf4j.Logger; @@ -151,7 +154,7 @@ public class HgHookManager implements ConfigChangedListener if (url == null) { - HttpServletRequest request = httpServletRequestProvider.get(); + HttpServletRequest request = getHttpServletRequest(); if (request != null) { @@ -159,10 +162,10 @@ public class HgHookManager implements ConfigChangedListener } else { - logger.warn( - "created hook url {} without request, in some cases this could cause problems", - hookUrl); url = createConfiguredUrl(); + logger.warn( + "created url {} without request, in some cases this could cause problems", + url); } } @@ -268,8 +271,14 @@ public class HgHookManager implements ConfigChangedListener */ private String createConfiguredUrl() { + //J- return HttpUtil.getUriWithoutEndSeperator( - configuration.getBaseUrl()).concat("/hook/hg/"); + Objects.firstNonNull( + configuration.getBaseUrl(), + "http://localhost:8080/scm" + ) + ).concat("/hook/hg/"); + //J+ } /** @@ -308,6 +317,32 @@ public class HgHookManager implements ConfigChangedListener //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + private HttpServletRequest getHttpServletRequest() + { + HttpServletRequest request = null; + + try + { + request = httpServletRequestProvider.get(); + } + catch (ProvisionException ex) + { + logger.debug("http servlet request is not available"); + } + catch (OutOfScopeException ex) + { + logger.debug("http servlet request is not available"); + } + + return request; + } + /** * Method description * From 304200980f7305ce74eb1b5cdbc64b4f0d1f40b7 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 9 Mar 2014 15:13:21 +0100 Subject: [PATCH 15/46] [maven-release-plugin] prepare release 1.36 --- maven/pom.xml | 4 ++-- maven/scm-maven-plugin/pom.xml | 4 ++-- maven/scm-plugin-archetype/pom.xml | 4 ++-- pom.xml | 4 ++-- scm-clients/pom.xml | 6 +++--- scm-clients/scm-cli-client/pom.xml | 6 +++--- scm-clients/scm-client-api/pom.xml | 4 ++-- scm-clients/scm-client-impl/pom.xml | 8 ++++---- scm-core/pom.xml | 4 ++-- scm-dao-orientdb/pom.xml | 8 ++++---- scm-dao-xml/pom.xml | 8 ++++---- scm-plugin-backend/pom.xml | 6 +++--- scm-plugins/pom.xml | 8 ++++---- scm-plugins/scm-git-plugin/pom.xml | 6 +++--- scm-plugins/scm-hg-plugin/pom.xml | 6 +++--- scm-plugins/scm-svn-plugin/pom.xml | 6 +++--- scm-samples/pom.xml | 4 ++-- scm-samples/scm-sample-auth/pom.xml | 6 +++--- scm-samples/scm-sample-hello/pom.xml | 6 +++--- scm-server/pom.xml | 4 ++-- scm-test/pom.xml | 6 +++--- scm-webapp/pom.xml | 24 ++++++++++++------------ support/pom.xml | 4 ++-- support/scm-support-btrace/pom.xml | 6 +++--- 24 files changed, 76 insertions(+), 76 deletions(-) diff --git a/maven/pom.xml b/maven/pom.xml index baf3601aa3..e213897a31 100644 --- a/maven/pom.xml +++ b/maven/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36-SNAPSHOT + 1.36 sonia.scm.maven scm-maven-plugins pom - 1.36-SNAPSHOT + 1.36 scm-maven-plugins diff --git a/maven/scm-maven-plugin/pom.xml b/maven/scm-maven-plugin/pom.xml index 39a039494b..22f7dae69f 100644 --- a/maven/scm-maven-plugin/pom.xml +++ b/maven/scm-maven-plugin/pom.xml @@ -6,12 +6,12 @@ scm-maven-plugins sonia.scm.maven - 1.36-SNAPSHOT + 1.36 sonia.scm.maven scm-maven-plugin - 1.36-SNAPSHOT + 1.36 maven-plugin scm-maven-plugin diff --git a/maven/scm-plugin-archetype/pom.xml b/maven/scm-plugin-archetype/pom.xml index 12286a8e6a..b268d351b0 100644 --- a/maven/scm-plugin-archetype/pom.xml +++ b/maven/scm-plugin-archetype/pom.xml @@ -6,12 +6,12 @@ scm-maven-plugins sonia.scm.maven - 1.36-SNAPSHOT + 1.36 sonia.scm.maven scm-plugin-archetype - 1.36-SNAPSHOT + 1.36 scm-plugin-archetype diff --git a/pom.xml b/pom.xml index 57795b9cf6..a4132d497e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ sonia.scm scm pom - 1.36-SNAPSHOT + 1.36 The easiest way to share your Git, Mercurial and Subversion repositories over http. @@ -36,7 +36,7 @@ scm:hg:http://bitbucket.org/sdorra/scm-manager scm:hg:https://bitbucket.org/sdorra/scm-manager http://bitbucket.org/sdorra/scm-manager - HEAD + 1.36 diff --git a/scm-clients/pom.xml b/scm-clients/pom.xml index c0a92c75bf..6faec13f93 100644 --- a/scm-clients/pom.xml +++ b/scm-clients/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36-SNAPSHOT + 1.36 sonia.scm.clients scm-clients pom - 1.36-SNAPSHOT + 1.36 scm-clients @@ -32,7 +32,7 @@ scm-core sonia.scm jar - 1.36-SNAPSHOT + 1.36 shiro-core diff --git a/scm-clients/scm-cli-client/pom.xml b/scm-clients/scm-cli-client/pom.xml index 4a3721cc2a..3bf9ad6a5e 100644 --- a/scm-clients/scm-cli-client/pom.xml +++ b/scm-clients/scm-cli-client/pom.xml @@ -6,12 +6,12 @@ scm-clients sonia.scm.clients - 1.36-SNAPSHOT + 1.36 sonia.scm.clients scm-cli-client - 1.36-SNAPSHOT + 1.36 scm-cli-client @@ -35,7 +35,7 @@ sonia.scm.clients scm-client-impl - 1.36-SNAPSHOT + 1.36 diff --git a/scm-clients/scm-client-api/pom.xml b/scm-clients/scm-client-api/pom.xml index 13dbf028c5..3ecfde8eb5 100644 --- a/scm-clients/scm-client-api/pom.xml +++ b/scm-clients/scm-client-api/pom.xml @@ -6,13 +6,13 @@ sonia.scm.clients scm-clients - 1.36-SNAPSHOT + 1.36 sonia.scm.clients scm-client-api jar - 1.36-SNAPSHOT + 1.36 scm-client-api diff --git a/scm-clients/scm-client-impl/pom.xml b/scm-clients/scm-client-impl/pom.xml index d5fe1e44b8..813211c763 100644 --- a/scm-clients/scm-client-impl/pom.xml +++ b/scm-clients/scm-client-impl/pom.xml @@ -6,13 +6,13 @@ sonia.scm.clients scm-clients - 1.36-SNAPSHOT + 1.36 sonia.scm.clients scm-client-impl jar - 1.36-SNAPSHOT + 1.36 scm-client-impl @@ -36,7 +36,7 @@ sonia.scm.clients scm-client-api - 1.36-SNAPSHOT + 1.36 @@ -88,7 +88,7 @@ sonia.scm scm-test - 1.36-SNAPSHOT + 1.36 test diff --git a/scm-core/pom.xml b/scm-core/pom.xml index 79adc49179..39c230759c 100644 --- a/scm-core/pom.xml +++ b/scm-core/pom.xml @@ -6,12 +6,12 @@ scm sonia.scm - 1.36-SNAPSHOT + 1.36 sonia.scm scm-core - 1.36-SNAPSHOT + 1.36 scm-core diff --git a/scm-dao-orientdb/pom.xml b/scm-dao-orientdb/pom.xml index 669456a20b..0a6b52a727 100644 --- a/scm-dao-orientdb/pom.xml +++ b/scm-dao-orientdb/pom.xml @@ -6,12 +6,12 @@ sonia.scm scm - 1.36-SNAPSHOT + 1.36 sonia.scm scm-dao-orientdb - 1.36-SNAPSHOT + 1.36 scm-dao-orientdb @@ -26,7 +26,7 @@ sonia.scm scm-core - 1.36-SNAPSHOT + 1.36 @@ -52,7 +52,7 @@ sonia.scm scm-test - 1.36-SNAPSHOT + 1.36 test diff --git a/scm-dao-xml/pom.xml b/scm-dao-xml/pom.xml index 71706f02fb..a9a88c12e3 100644 --- a/scm-dao-xml/pom.xml +++ b/scm-dao-xml/pom.xml @@ -6,12 +6,12 @@ sonia.scm scm - 1.36-SNAPSHOT + 1.36 sonia.scm scm-dao-xml - 1.36-SNAPSHOT + 1.36 scm-dao-xml @@ -26,7 +26,7 @@ sonia.scm scm-core - 1.36-SNAPSHOT + 1.36 @@ -34,7 +34,7 @@ sonia.scm scm-test - 1.36-SNAPSHOT + 1.36 test diff --git a/scm-plugin-backend/pom.xml b/scm-plugin-backend/pom.xml index 6fbc3edf46..0774f112a6 100644 --- a/scm-plugin-backend/pom.xml +++ b/scm-plugin-backend/pom.xml @@ -6,13 +6,13 @@ scm sonia.scm - 1.36-SNAPSHOT + 1.36 sonia.scm scm-plugin-backend war - 1.36-SNAPSHOT + 1.36 ${project.artifactId} @@ -62,7 +62,7 @@ sonia.scm scm-core - 1.36-SNAPSHOT + 1.36 diff --git a/scm-plugins/pom.xml b/scm-plugins/pom.xml index b4b51c11a1..e6e4f9472e 100644 --- a/scm-plugins/pom.xml +++ b/scm-plugins/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36-SNAPSHOT + 1.36 sonia.scm.plugins scm-plugins pom - 1.36-SNAPSHOT + 1.36 scm-plugins @@ -26,7 +26,7 @@ sonia.scm scm-core - 1.36-SNAPSHOT + 1.36 @@ -59,7 +59,7 @@ sonia.scm.maven scm-maven-plugin - 1.36-SNAPSHOT + 1.36 process-resources diff --git a/scm-plugins/scm-git-plugin/pom.xml b/scm-plugins/scm-git-plugin/pom.xml index 547a82d22f..3ee82d3a12 100644 --- a/scm-plugins/scm-git-plugin/pom.xml +++ b/scm-plugins/scm-git-plugin/pom.xml @@ -6,12 +6,12 @@ scm-plugins sonia.scm.plugins - 1.36-SNAPSHOT + 1.36 sonia.scm.plugins scm-git-plugin - 1.36-SNAPSHOT + 1.36 scm-git-plugin https://bitbucket.org/sdorra/scm-manager Plugin for the version control system Git @@ -48,7 +48,7 @@ sonia.scm scm-test - 1.36-SNAPSHOT + 1.36 test diff --git a/scm-plugins/scm-hg-plugin/pom.xml b/scm-plugins/scm-hg-plugin/pom.xml index 2e1ea51963..8df951b23a 100644 --- a/scm-plugins/scm-hg-plugin/pom.xml +++ b/scm-plugins/scm-hg-plugin/pom.xml @@ -6,12 +6,12 @@ sonia.scm.plugins scm-plugins - 1.36-SNAPSHOT + 1.36 sonia.scm.plugins scm-hg-plugin - 1.36-SNAPSHOT + 1.36 scm-hg-plugin https://bitbucket.org/sdorra/scm-manager Plugin for the version control system Mercurial @@ -36,7 +36,7 @@ sonia.scm scm-test - 1.36-SNAPSHOT + 1.36 test diff --git a/scm-plugins/scm-svn-plugin/pom.xml b/scm-plugins/scm-svn-plugin/pom.xml index b9de854c65..f8cdd3f3dd 100644 --- a/scm-plugins/scm-svn-plugin/pom.xml +++ b/scm-plugins/scm-svn-plugin/pom.xml @@ -6,12 +6,12 @@ scm-plugins sonia.scm.plugins - 1.36-SNAPSHOT + 1.36 sonia.scm.plugins scm-svn-plugin - 1.36-SNAPSHOT + 1.36 scm-svn-plugin https://bitbucket.org/sdorra/scm-manager Plugin for the version control system Subversion @@ -48,7 +48,7 @@ sonia.scm scm-test - 1.36-SNAPSHOT + 1.36 test diff --git a/scm-samples/pom.xml b/scm-samples/pom.xml index 506d86aea2..60a1bb27db 100644 --- a/scm-samples/pom.xml +++ b/scm-samples/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36-SNAPSHOT + 1.36 sonia.scm.samples scm-samples pom - 1.36-SNAPSHOT + 1.36 scm-samples diff --git a/scm-samples/scm-sample-auth/pom.xml b/scm-samples/scm-sample-auth/pom.xml index d9976eda71..246e32a72b 100644 --- a/scm-samples/scm-sample-auth/pom.xml +++ b/scm-samples/scm-sample-auth/pom.xml @@ -6,12 +6,12 @@ scm-samples sonia.scm.samples - 1.36-SNAPSHOT + 1.36 sonia.scm.sample scm-sample-auth - 1.36-SNAPSHOT + 1.36 scm-sample-auth Sample Authentication Plugin https://bitbucket.org/sdorra/scm-manager @@ -28,7 +28,7 @@ sonia.scm scm-core - 1.36-SNAPSHOT + 1.36 diff --git a/scm-samples/scm-sample-hello/pom.xml b/scm-samples/scm-sample-hello/pom.xml index 22d8e7cd62..eddae48fcb 100644 --- a/scm-samples/scm-sample-hello/pom.xml +++ b/scm-samples/scm-sample-hello/pom.xml @@ -6,12 +6,12 @@ scm-samples sonia.scm.samples - 1.36-SNAPSHOT + 1.36 sonia.scm.sample scm-sample-hello - 1.36-SNAPSHOT + 1.36 scm-sample-hello A simple hello world plugin https://bitbucket.org/sdorra/scm-manager @@ -28,7 +28,7 @@ sonia.scm scm-core - 1.36-SNAPSHOT + 1.36 diff --git a/scm-server/pom.xml b/scm-server/pom.xml index 4139b2f03e..e85abfa99b 100644 --- a/scm-server/pom.xml +++ b/scm-server/pom.xml @@ -6,12 +6,12 @@ scm sonia.scm - 1.36-SNAPSHOT + 1.36 sonia.scm scm-server - 1.36-SNAPSHOT + 1.36 scm-server jar diff --git a/scm-test/pom.xml b/scm-test/pom.xml index d4a75af899..7a59b4d4d1 100644 --- a/scm-test/pom.xml +++ b/scm-test/pom.xml @@ -6,12 +6,12 @@ scm sonia.scm - 1.36-SNAPSHOT + 1.36 sonia.scm scm-test - 1.36-SNAPSHOT + 1.36 scm-test @@ -25,7 +25,7 @@ sonia.scm scm-core - 1.36-SNAPSHOT + 1.36 diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 920b70c7d1..9c9487c8fd 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36-SNAPSHOT + 1.36 sonia.scm scm-webapp war - 1.36-SNAPSHOT + 1.36 scm-webapp @@ -38,31 +38,31 @@ sonia.scm scm-core - 1.36-SNAPSHOT + 1.36 sonia.scm scm-dao-xml - 1.36-SNAPSHOT + 1.36 sonia.scm.plugins scm-hg-plugin - 1.36-SNAPSHOT + 1.36 sonia.scm.plugins scm-svn-plugin - 1.36-SNAPSHOT + 1.36 sonia.scm.plugins scm-git-plugin - 1.36-SNAPSHOT + 1.36 @@ -267,7 +267,7 @@ sonia.scm scm-test - 1.36-SNAPSHOT + 1.36 test @@ -280,7 +280,7 @@ sonia.scm.plugins scm-git-plugin - 1.36-SNAPSHOT + 1.36 tests test @@ -288,7 +288,7 @@ sonia.scm.plugins scm-hg-plugin - 1.36-SNAPSHOT + 1.36 tests test @@ -296,7 +296,7 @@ sonia.scm.plugins scm-svn-plugin - 1.36-SNAPSHOT + 1.36 tests test @@ -517,7 +517,7 @@ sonia.scm scm-dao-orientdb - 1.36-SNAPSHOT + 1.36 diff --git a/support/pom.xml b/support/pom.xml index f71fa31721..98ccac4f4a 100644 --- a/support/pom.xml +++ b/support/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36-SNAPSHOT + 1.36 sonia.scm.support scm-support pom - 1.36-SNAPSHOT + 1.36 scm-support diff --git a/support/scm-support-btrace/pom.xml b/support/scm-support-btrace/pom.xml index 9777753d33..dfa0bd7210 100644 --- a/support/scm-support-btrace/pom.xml +++ b/support/scm-support-btrace/pom.xml @@ -4,12 +4,12 @@ sonia.scm.support scm-support - 1.36-SNAPSHOT + 1.36 sonia.scm scm-support-btrace - 1.36-SNAPSHOT + 1.36 jar scm-support-btrace @@ -18,7 +18,7 @@ sonia.scm scm-core - 1.36-SNAPSHOT + 1.36 From efae937b0c1e789196b770b945e5ad2679362599 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 9 Mar 2014 15:13:22 +0100 Subject: [PATCH 16/46] [maven-release-plugin] copy for tag 1.36 From 014220a45bbe67010fc796c551007e8077bcf108 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 9 Mar 2014 15:13:22 +0100 Subject: [PATCH 17/46] [maven-release-plugin] prepare for next development iteration --- maven/pom.xml | 4 ++-- maven/scm-maven-plugin/pom.xml | 4 ++-- maven/scm-plugin-archetype/pom.xml | 4 ++-- pom.xml | 4 ++-- scm-clients/pom.xml | 6 +++--- scm-clients/scm-cli-client/pom.xml | 6 +++--- scm-clients/scm-client-api/pom.xml | 4 ++-- scm-clients/scm-client-impl/pom.xml | 8 ++++---- scm-core/pom.xml | 4 ++-- scm-dao-orientdb/pom.xml | 8 ++++---- scm-dao-xml/pom.xml | 8 ++++---- scm-plugin-backend/pom.xml | 6 +++--- scm-plugins/pom.xml | 8 ++++---- scm-plugins/scm-git-plugin/pom.xml | 6 +++--- scm-plugins/scm-hg-plugin/pom.xml | 6 +++--- scm-plugins/scm-svn-plugin/pom.xml | 6 +++--- scm-samples/pom.xml | 4 ++-- scm-samples/scm-sample-auth/pom.xml | 6 +++--- scm-samples/scm-sample-hello/pom.xml | 6 +++--- scm-server/pom.xml | 4 ++-- scm-test/pom.xml | 6 +++--- scm-webapp/pom.xml | 24 ++++++++++++------------ support/pom.xml | 4 ++-- support/scm-support-btrace/pom.xml | 6 +++--- 24 files changed, 76 insertions(+), 76 deletions(-) diff --git a/maven/pom.xml b/maven/pom.xml index e213897a31..3952c1819a 100644 --- a/maven/pom.xml +++ b/maven/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36 + 1.37-SNAPSHOT sonia.scm.maven scm-maven-plugins pom - 1.36 + 1.37-SNAPSHOT scm-maven-plugins diff --git a/maven/scm-maven-plugin/pom.xml b/maven/scm-maven-plugin/pom.xml index 22f7dae69f..b5356e4146 100644 --- a/maven/scm-maven-plugin/pom.xml +++ b/maven/scm-maven-plugin/pom.xml @@ -6,12 +6,12 @@ scm-maven-plugins sonia.scm.maven - 1.36 + 1.37-SNAPSHOT sonia.scm.maven scm-maven-plugin - 1.36 + 1.37-SNAPSHOT maven-plugin scm-maven-plugin diff --git a/maven/scm-plugin-archetype/pom.xml b/maven/scm-plugin-archetype/pom.xml index b268d351b0..5903587970 100644 --- a/maven/scm-plugin-archetype/pom.xml +++ b/maven/scm-plugin-archetype/pom.xml @@ -6,12 +6,12 @@ scm-maven-plugins sonia.scm.maven - 1.36 + 1.37-SNAPSHOT sonia.scm.maven scm-plugin-archetype - 1.36 + 1.37-SNAPSHOT scm-plugin-archetype diff --git a/pom.xml b/pom.xml index a4132d497e..fc9e90eee7 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ sonia.scm scm pom - 1.36 + 1.37-SNAPSHOT The easiest way to share your Git, Mercurial and Subversion repositories over http. @@ -36,7 +36,7 @@ scm:hg:http://bitbucket.org/sdorra/scm-manager scm:hg:https://bitbucket.org/sdorra/scm-manager http://bitbucket.org/sdorra/scm-manager - 1.36 + HEAD diff --git a/scm-clients/pom.xml b/scm-clients/pom.xml index 6faec13f93..1846f03a5b 100644 --- a/scm-clients/pom.xml +++ b/scm-clients/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36 + 1.37-SNAPSHOT sonia.scm.clients scm-clients pom - 1.36 + 1.37-SNAPSHOT scm-clients @@ -32,7 +32,7 @@ scm-core sonia.scm jar - 1.36 + 1.37-SNAPSHOT shiro-core diff --git a/scm-clients/scm-cli-client/pom.xml b/scm-clients/scm-cli-client/pom.xml index 3bf9ad6a5e..6a1d82925d 100644 --- a/scm-clients/scm-cli-client/pom.xml +++ b/scm-clients/scm-cli-client/pom.xml @@ -6,12 +6,12 @@ scm-clients sonia.scm.clients - 1.36 + 1.37-SNAPSHOT sonia.scm.clients scm-cli-client - 1.36 + 1.37-SNAPSHOT scm-cli-client @@ -35,7 +35,7 @@ sonia.scm.clients scm-client-impl - 1.36 + 1.37-SNAPSHOT diff --git a/scm-clients/scm-client-api/pom.xml b/scm-clients/scm-client-api/pom.xml index 3ecfde8eb5..ed4329d54c 100644 --- a/scm-clients/scm-client-api/pom.xml +++ b/scm-clients/scm-client-api/pom.xml @@ -6,13 +6,13 @@ sonia.scm.clients scm-clients - 1.36 + 1.37-SNAPSHOT sonia.scm.clients scm-client-api jar - 1.36 + 1.37-SNAPSHOT scm-client-api diff --git a/scm-clients/scm-client-impl/pom.xml b/scm-clients/scm-client-impl/pom.xml index 813211c763..ed9d2e3fc0 100644 --- a/scm-clients/scm-client-impl/pom.xml +++ b/scm-clients/scm-client-impl/pom.xml @@ -6,13 +6,13 @@ sonia.scm.clients scm-clients - 1.36 + 1.37-SNAPSHOT sonia.scm.clients scm-client-impl jar - 1.36 + 1.37-SNAPSHOT scm-client-impl @@ -36,7 +36,7 @@ sonia.scm.clients scm-client-api - 1.36 + 1.37-SNAPSHOT @@ -88,7 +88,7 @@ sonia.scm scm-test - 1.36 + 1.37-SNAPSHOT test diff --git a/scm-core/pom.xml b/scm-core/pom.xml index 39c230759c..dec20d4924 100644 --- a/scm-core/pom.xml +++ b/scm-core/pom.xml @@ -6,12 +6,12 @@ scm sonia.scm - 1.36 + 1.37-SNAPSHOT sonia.scm scm-core - 1.36 + 1.37-SNAPSHOT scm-core diff --git a/scm-dao-orientdb/pom.xml b/scm-dao-orientdb/pom.xml index 0a6b52a727..91465e3a61 100644 --- a/scm-dao-orientdb/pom.xml +++ b/scm-dao-orientdb/pom.xml @@ -6,12 +6,12 @@ sonia.scm scm - 1.36 + 1.37-SNAPSHOT sonia.scm scm-dao-orientdb - 1.36 + 1.37-SNAPSHOT scm-dao-orientdb @@ -26,7 +26,7 @@ sonia.scm scm-core - 1.36 + 1.37-SNAPSHOT @@ -52,7 +52,7 @@ sonia.scm scm-test - 1.36 + 1.37-SNAPSHOT test diff --git a/scm-dao-xml/pom.xml b/scm-dao-xml/pom.xml index a9a88c12e3..84ad64c60a 100644 --- a/scm-dao-xml/pom.xml +++ b/scm-dao-xml/pom.xml @@ -6,12 +6,12 @@ sonia.scm scm - 1.36 + 1.37-SNAPSHOT sonia.scm scm-dao-xml - 1.36 + 1.37-SNAPSHOT scm-dao-xml @@ -26,7 +26,7 @@ sonia.scm scm-core - 1.36 + 1.37-SNAPSHOT @@ -34,7 +34,7 @@ sonia.scm scm-test - 1.36 + 1.37-SNAPSHOT test diff --git a/scm-plugin-backend/pom.xml b/scm-plugin-backend/pom.xml index 0774f112a6..0e55747fa4 100644 --- a/scm-plugin-backend/pom.xml +++ b/scm-plugin-backend/pom.xml @@ -6,13 +6,13 @@ scm sonia.scm - 1.36 + 1.37-SNAPSHOT sonia.scm scm-plugin-backend war - 1.36 + 1.37-SNAPSHOT ${project.artifactId} @@ -62,7 +62,7 @@ sonia.scm scm-core - 1.36 + 1.37-SNAPSHOT diff --git a/scm-plugins/pom.xml b/scm-plugins/pom.xml index e6e4f9472e..f75ff77268 100644 --- a/scm-plugins/pom.xml +++ b/scm-plugins/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36 + 1.37-SNAPSHOT sonia.scm.plugins scm-plugins pom - 1.36 + 1.37-SNAPSHOT scm-plugins @@ -26,7 +26,7 @@ sonia.scm scm-core - 1.36 + 1.37-SNAPSHOT @@ -59,7 +59,7 @@ sonia.scm.maven scm-maven-plugin - 1.36 + 1.37-SNAPSHOT process-resources diff --git a/scm-plugins/scm-git-plugin/pom.xml b/scm-plugins/scm-git-plugin/pom.xml index 3ee82d3a12..59ea4618d2 100644 --- a/scm-plugins/scm-git-plugin/pom.xml +++ b/scm-plugins/scm-git-plugin/pom.xml @@ -6,12 +6,12 @@ scm-plugins sonia.scm.plugins - 1.36 + 1.37-SNAPSHOT sonia.scm.plugins scm-git-plugin - 1.36 + 1.37-SNAPSHOT scm-git-plugin https://bitbucket.org/sdorra/scm-manager Plugin for the version control system Git @@ -48,7 +48,7 @@ sonia.scm scm-test - 1.36 + 1.37-SNAPSHOT test diff --git a/scm-plugins/scm-hg-plugin/pom.xml b/scm-plugins/scm-hg-plugin/pom.xml index 8df951b23a..f85f15417d 100644 --- a/scm-plugins/scm-hg-plugin/pom.xml +++ b/scm-plugins/scm-hg-plugin/pom.xml @@ -6,12 +6,12 @@ sonia.scm.plugins scm-plugins - 1.36 + 1.37-SNAPSHOT sonia.scm.plugins scm-hg-plugin - 1.36 + 1.37-SNAPSHOT scm-hg-plugin https://bitbucket.org/sdorra/scm-manager Plugin for the version control system Mercurial @@ -36,7 +36,7 @@ sonia.scm scm-test - 1.36 + 1.37-SNAPSHOT test diff --git a/scm-plugins/scm-svn-plugin/pom.xml b/scm-plugins/scm-svn-plugin/pom.xml index f8cdd3f3dd..25901befa0 100644 --- a/scm-plugins/scm-svn-plugin/pom.xml +++ b/scm-plugins/scm-svn-plugin/pom.xml @@ -6,12 +6,12 @@ scm-plugins sonia.scm.plugins - 1.36 + 1.37-SNAPSHOT sonia.scm.plugins scm-svn-plugin - 1.36 + 1.37-SNAPSHOT scm-svn-plugin https://bitbucket.org/sdorra/scm-manager Plugin for the version control system Subversion @@ -48,7 +48,7 @@ sonia.scm scm-test - 1.36 + 1.37-SNAPSHOT test diff --git a/scm-samples/pom.xml b/scm-samples/pom.xml index 60a1bb27db..e15a418290 100644 --- a/scm-samples/pom.xml +++ b/scm-samples/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36 + 1.37-SNAPSHOT sonia.scm.samples scm-samples pom - 1.36 + 1.37-SNAPSHOT scm-samples diff --git a/scm-samples/scm-sample-auth/pom.xml b/scm-samples/scm-sample-auth/pom.xml index 246e32a72b..3a198d68b0 100644 --- a/scm-samples/scm-sample-auth/pom.xml +++ b/scm-samples/scm-sample-auth/pom.xml @@ -6,12 +6,12 @@ scm-samples sonia.scm.samples - 1.36 + 1.37-SNAPSHOT sonia.scm.sample scm-sample-auth - 1.36 + 1.37-SNAPSHOT scm-sample-auth Sample Authentication Plugin https://bitbucket.org/sdorra/scm-manager @@ -28,7 +28,7 @@ sonia.scm scm-core - 1.36 + 1.37-SNAPSHOT diff --git a/scm-samples/scm-sample-hello/pom.xml b/scm-samples/scm-sample-hello/pom.xml index eddae48fcb..fc6dcf5e42 100644 --- a/scm-samples/scm-sample-hello/pom.xml +++ b/scm-samples/scm-sample-hello/pom.xml @@ -6,12 +6,12 @@ scm-samples sonia.scm.samples - 1.36 + 1.37-SNAPSHOT sonia.scm.sample scm-sample-hello - 1.36 + 1.37-SNAPSHOT scm-sample-hello A simple hello world plugin https://bitbucket.org/sdorra/scm-manager @@ -28,7 +28,7 @@ sonia.scm scm-core - 1.36 + 1.37-SNAPSHOT diff --git a/scm-server/pom.xml b/scm-server/pom.xml index e85abfa99b..9b5b666208 100644 --- a/scm-server/pom.xml +++ b/scm-server/pom.xml @@ -6,12 +6,12 @@ scm sonia.scm - 1.36 + 1.37-SNAPSHOT sonia.scm scm-server - 1.36 + 1.37-SNAPSHOT scm-server jar diff --git a/scm-test/pom.xml b/scm-test/pom.xml index 7a59b4d4d1..15ff5ffea0 100644 --- a/scm-test/pom.xml +++ b/scm-test/pom.xml @@ -6,12 +6,12 @@ scm sonia.scm - 1.36 + 1.37-SNAPSHOT sonia.scm scm-test - 1.36 + 1.37-SNAPSHOT scm-test @@ -25,7 +25,7 @@ sonia.scm scm-core - 1.36 + 1.37-SNAPSHOT diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 9c9487c8fd..9064b4c571 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36 + 1.37-SNAPSHOT sonia.scm scm-webapp war - 1.36 + 1.37-SNAPSHOT scm-webapp @@ -38,31 +38,31 @@ sonia.scm scm-core - 1.36 + 1.37-SNAPSHOT sonia.scm scm-dao-xml - 1.36 + 1.37-SNAPSHOT sonia.scm.plugins scm-hg-plugin - 1.36 + 1.37-SNAPSHOT sonia.scm.plugins scm-svn-plugin - 1.36 + 1.37-SNAPSHOT sonia.scm.plugins scm-git-plugin - 1.36 + 1.37-SNAPSHOT @@ -267,7 +267,7 @@ sonia.scm scm-test - 1.36 + 1.37-SNAPSHOT test @@ -280,7 +280,7 @@ sonia.scm.plugins scm-git-plugin - 1.36 + 1.37-SNAPSHOT tests test @@ -288,7 +288,7 @@ sonia.scm.plugins scm-hg-plugin - 1.36 + 1.37-SNAPSHOT tests test @@ -296,7 +296,7 @@ sonia.scm.plugins scm-svn-plugin - 1.36 + 1.37-SNAPSHOT tests test @@ -517,7 +517,7 @@ sonia.scm scm-dao-orientdb - 1.36 + 1.37-SNAPSHOT diff --git a/support/pom.xml b/support/pom.xml index 98ccac4f4a..d0b687e9a9 100644 --- a/support/pom.xml +++ b/support/pom.xml @@ -6,13 +6,13 @@ sonia.scm scm - 1.36 + 1.37-SNAPSHOT sonia.scm.support scm-support pom - 1.36 + 1.37-SNAPSHOT scm-support diff --git a/support/scm-support-btrace/pom.xml b/support/scm-support-btrace/pom.xml index dfa0bd7210..e73bdc67c1 100644 --- a/support/scm-support-btrace/pom.xml +++ b/support/scm-support-btrace/pom.xml @@ -4,12 +4,12 @@ sonia.scm.support scm-support - 1.36 + 1.37-SNAPSHOT sonia.scm scm-support-btrace - 1.36 + 1.37-SNAPSHOT jar scm-support-btrace @@ -18,7 +18,7 @@ sonia.scm scm-core - 1.36 + 1.37-SNAPSHOT From 05cb07e76e5ea2c9e9aa47f2f61f496027cde737 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 11 Mar 2014 18:21:27 +0100 Subject: [PATCH 18/46] resolve dependency resolution conflicts --- .../scm/plugin/AetherDependencyResolver.java | 26 +++++-------------- .../sonia/scm/plugin/AetherPluginHandler.java | 7 +---- 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/AetherDependencyResolver.java b/scm-webapp/src/main/java/sonia/scm/plugin/AetherDependencyResolver.java index 1e42d84637..67bf4e8a40 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/AetherDependencyResolver.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/AetherDependencyResolver.java @@ -30,6 +30,7 @@ */ + package sonia.scm.plugin; //~--- non-JDK imports -------------------------------------------------------- @@ -116,32 +117,17 @@ public class AetherDependencyResolver * * * @param dependency + * @param dependencies * * @throws DependencyCollectionException * @throws DependencyResolutionException */ - public void resolveLocalDependency(Dependency dependency) + public void resolveDependencies(Dependency dependency, + List dependencies) throws DependencyCollectionException, DependencyResolutionException { - CollectRequest request = new CollectRequest(); - - request.setRoot(dependency); - resolveDependency(request); - } - - /** - * Method description - * - * - * @param dependency - * - * @throws DependencyCollectionException - * @throws DependencyResolutionException - */ - public void resolveRemoteDependency(Dependency dependency) - throws DependencyCollectionException, DependencyResolutionException - { - resolveDependency(new CollectRequest(dependency, remoteRepositories)); + resolveDependency(new CollectRequest(dependency, dependencies, + remoteRepositories)); } /** diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/AetherPluginHandler.java b/scm-webapp/src/main/java/sonia/scm/plugin/AetherPluginHandler.java index f35a6b4976..7de5397a23 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/AetherPluginHandler.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/AetherPluginHandler.java @@ -199,12 +199,7 @@ public class AetherPluginHandler new AetherDependencyResolver(configuration, repositorySystem, localRepository, remoteRepositories); - resolver.resolveRemoteDependency(dependency); - - for (Dependency localDependency : localDependencies) - { - resolver.resolveLocalDependency(localDependency); - } + resolver.resolveDependencies(dependency, localDependencies); if (classpath == null) { From 7c1f746def9f3c082d8c0f8fb5997eb84b4b13ae Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 11 Mar 2014 18:58:18 +0100 Subject: [PATCH 19/46] fix basic authentication for urls which contain a username, but no password --- .../web/filter/BasicAuthenticationFilter.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java index 44801de4d2..ee2d9649a7 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java @@ -84,6 +84,8 @@ public class BasicAuthenticationFilter extends AutoLoginFilter /** Field description */ public static final String HEADER_AUTHORIZATION = "Authorization"; + + private static final String ATTRIBUTE_FAILED_AUTH = "sonia.scm.auth.failed"; /** the logger for BasicAuthenticationFilter */ private static final Logger logger = @@ -195,9 +197,8 @@ public class BasicAuthenticationFilter extends AutoLoginFilter } /** - * Sends status code 401 back to client, if no authorization header was found, - * if a authorization is present and the authentication failed the method will - * send status code 403. + * Sends status code 403 back to client, if the authentication has failed. + * In all other cases the method will send status code 403 back to client. * * @param request servlet request * @param response servlet response @@ -212,15 +213,15 @@ public class BasicAuthenticationFilter extends AutoLoginFilter HttpServletResponse response, FilterChain chain) throws IOException, ServletException { - String authentication = request.getHeader(HEADER_AUTHORIZATION); - - if (Strings.isNullOrEmpty(authentication)) + // send only forbidden, if the authentication has failed. + // see https://bitbucket.org/sdorra/scm-manager/issue/545/git-clone-with-username-in-url-does-not + if (Boolean.TRUE.equals(request.getAttribute(ATTRIBUTE_FAILED_AUTH))) { - HttpUtil.sendUnauthorized(request, response, configuration.getRealmDescription()); + response.sendError(HttpServletResponse.SC_FORBIDDEN); } else { - response.sendError(HttpServletResponse.SC_FORBIDDEN); + HttpUtil.sendUnauthorized(request, response, configuration.getRealmDescription()); } } @@ -242,7 +243,7 @@ public class BasicAuthenticationFilter extends AutoLoginFilter String token = authentication.substring(6); token = new String(Base64.decode(token.getBytes())); - + int index = token.indexOf(CREDENTIAL_SEPARATOR); User user = null; @@ -267,6 +268,8 @@ public class BasicAuthenticationFilter extends AutoLoginFilter } catch (AuthenticationException ex) { + // add a marker to the request that the authentication has failed + request.setAttribute(ATTRIBUTE_FAILED_AUTH, Boolean.TRUE); if (logger.isTraceEnabled()) { logger.trace("authentication failed for user ".concat(username), From 27f3286e9d6c36ff21c19cc77f033b34a682f0c8 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 11 Mar 2014 18:59:59 +0100 Subject: [PATCH 20/46] indent, javadoc and removed unused import --- .../scm/web/filter/BasicAuthenticationFilter.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java index ee2d9649a7..fe1aed181a 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java @@ -35,7 +35,6 @@ package sonia.scm.web.filter; //~--- non-JDK imports -------------------------------------------------------- -import com.google.common.base.Strings; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; @@ -84,7 +83,8 @@ public class BasicAuthenticationFilter extends AutoLoginFilter /** Field description */ public static final String HEADER_AUTHORIZATION = "Authorization"; - + + /** marker for failed authentication */ private static final String ATTRIBUTE_FAILED_AUTH = "sonia.scm.auth.failed"; /** the logger for BasicAuthenticationFilter */ @@ -197,7 +197,7 @@ public class BasicAuthenticationFilter extends AutoLoginFilter } /** - * Sends status code 403 back to client, if the authentication has failed. + * Sends status code 403 back to client, if the authentication has failed. * In all other cases the method will send status code 403 back to client. * * @param request servlet request @@ -213,6 +213,7 @@ public class BasicAuthenticationFilter extends AutoLoginFilter HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + // send only forbidden, if the authentication has failed. // see https://bitbucket.org/sdorra/scm-manager/issue/545/git-clone-with-username-in-url-does-not if (Boolean.TRUE.equals(request.getAttribute(ATTRIBUTE_FAILED_AUTH))) @@ -221,7 +222,8 @@ public class BasicAuthenticationFilter extends AutoLoginFilter } else { - HttpUtil.sendUnauthorized(request, response, configuration.getRealmDescription()); + HttpUtil.sendUnauthorized(request, response, + configuration.getRealmDescription()); } } @@ -243,7 +245,7 @@ public class BasicAuthenticationFilter extends AutoLoginFilter String token = authentication.substring(6); token = new String(Base64.decode(token.getBytes())); - + int index = token.indexOf(CREDENTIAL_SEPARATOR); User user = null; @@ -268,8 +270,10 @@ public class BasicAuthenticationFilter extends AutoLoginFilter } catch (AuthenticationException ex) { + // add a marker to the request that the authentication has failed request.setAttribute(ATTRIBUTE_FAILED_AUTH, Boolean.TRUE); + if (logger.isTraceEnabled()) { logger.trace("authentication failed for user ".concat(username), From c10ed1e121af2d01c2e47256d7fd81dc6dd9fb7b Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 12 Mar 2014 08:37:04 +0100 Subject: [PATCH 21/46] update svnkit to version 1.8.4-scm2-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fc9e90eee7..f4392aae9f 100644 --- a/pom.xml +++ b/pom.xml @@ -431,7 +431,7 @@ 3.3.0.201403021825-r - 1.8.4-scm1 + 1.8.4-scm2-SNAPSHOT 15.0 From e963a528797bd524c91600bd7521879acedd1f41 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 13 Mar 2014 10:43:49 +0100 Subject: [PATCH 22/46] close branch issue-541 From 526a0effe4ccada13b605dd160300a2339aa2a6e Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 13 Mar 2014 11:27:13 +0100 Subject: [PATCH 23/46] use release version of svnkit 1.8.4-scm2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f4392aae9f..58e5a92213 100644 --- a/pom.xml +++ b/pom.xml @@ -431,7 +431,7 @@ 3.3.0.201403021825-r - 1.8.4-scm2-SNAPSHOT + 1.8.4-scm2 15.0 From 7aafc533a9c7fd3956a2e05ac3a8397188e8e24b Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 13 Mar 2014 11:27:46 +0100 Subject: [PATCH 24/46] close branch issue-547 From cd1a78c5b15fa917b746c0e41d17ed3fa18d92a1 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 13 Mar 2014 20:19:08 +0100 Subject: [PATCH 25/46] define global exclude for commons-logging and log4j --- scm-webapp/pom.xml | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 9064b4c571..4df3111dc8 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -165,12 +165,6 @@ commons-beanutils commons-beanutils 1.9.1 - - - commons-logging - commons-logging - - @@ -306,12 +300,6 @@ selenium-java ${selenium.version} test - - - commons-logging - commons-logging - - @@ -333,12 +321,22 @@ jersey-apache-client ${jersey.version} test - - - commons-logging - commons-logging - - + + + + + + commons-logging + commons-logging + 1.1.3 + provided + + + + log4j + log4j + 1.2.17 + provided From 33b9bec2421518cc526ca4b03ea7fc92f4b965ce Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 13 Mar 2014 20:23:16 +0100 Subject: [PATCH 26/46] include version 1.8 of commons-codec to fix htpasswd-plugin --- scm-webapp/pom.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 4df3111dc8..f6f21431d6 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -173,6 +173,17 @@ 3.2.1 + + + + commons-codec + commons-codec + 1.8 + + asm asm From 9d70a5aa09ce09dbb860771ff093da930019d824 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 13 Mar 2014 20:57:02 +0100 Subject: [PATCH 27/46] implement plugin dependency blacklist --- ...ter.java => AbstractDependencyFilter.java} | 119 ++++++++---------- .../main/java/sonia/scm/plugin/Aether.java | 8 +- .../scm/plugin/BlacklistDependencyFilter.java | 65 ++++++++++ .../scm/plugin/CoreDependencyFilter.java | 65 ++++++++++ .../sonia/scm/plugin/DependencyFilters.java | 110 ++++++++++++++++ .../src/main/resources/config/blacklist.list | 10 ++ 6 files changed, 309 insertions(+), 68 deletions(-) rename scm-webapp/src/main/java/sonia/scm/plugin/{AetherDependencyFilter.java => AbstractDependencyFilter.java} (73%) create mode 100644 scm-webapp/src/main/java/sonia/scm/plugin/BlacklistDependencyFilter.java create mode 100644 scm-webapp/src/main/java/sonia/scm/plugin/CoreDependencyFilter.java create mode 100644 scm-webapp/src/main/java/sonia/scm/plugin/DependencyFilters.java create mode 100644 scm-webapp/src/main/resources/config/blacklist.list diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/AetherDependencyFilter.java b/scm-webapp/src/main/java/sonia/scm/plugin/AbstractDependencyFilter.java similarity index 73% rename from scm-webapp/src/main/java/sonia/scm/plugin/AetherDependencyFilter.java rename to scm-webapp/src/main/java/sonia/scm/plugin/AbstractDependencyFilter.java index 1d89ddec7a..d448358b64 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/AetherDependencyFilter.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/AbstractDependencyFilter.java @@ -35,42 +35,47 @@ package sonia.scm.plugin; //~--- non-JDK imports -------------------------------------------------------- +import com.google.common.base.Throwables; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.sonatype.aether.artifact.Artifact; import org.sonatype.aether.graph.DependencyFilter; import org.sonatype.aether.graph.DependencyNode; -import sonia.scm.util.Util; - //~--- JDK imports ------------------------------------------------------------ -import java.util.HashSet; +import java.io.IOException; + import java.util.List; -import java.util.Scanner; import java.util.Set; /** * * @author Sebastian Sdorra */ -public class AetherDependencyFilter implements DependencyFilter +public abstract class AbstractDependencyFilter implements DependencyFilter { - /** Field description */ - public static final String EXCLUDE_LIST = "/config/dependencies.list"; - - //~--- constructors --------------------------------------------------------- - /** - * Constructs ... - * + * the logger for AbstractDependencyFilter */ - public AetherDependencyFilter() - { - loadExcludes(); - } + private static final Logger logger = + LoggerFactory.getLogger(AbstractDependencyFilter.class); //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @return + * + * @throws IOException + */ + protected abstract Set loadExcludeSet() throws IOException; + /** * Method description * @@ -91,63 +96,45 @@ public class AetherDependencyFilter implements DependencyFilter if (artifact != null) { - result = !exludeSet.contains(getId(artifact)); + String id = getId(artifact); + + result = !getExludeSet().contains(id); + + if (!result && logger.isDebugEnabled()) + { + logger.debug("exlcude dependency {} because it is blacklisted", id); + } } } return result; } - /** - * Method description - * - */ - private void loadExcludes() - { - Scanner scanner = null; - - try - { - scanner = new Scanner( - AetherDependencyFilter.class.getResourceAsStream(EXCLUDE_LIST)); - - while (scanner.hasNextLine()) - { - parseLine(scanner.nextLine()); - } - } - finally - { - if (scanner != null) - { - scanner.close(); - } - } - } - - /** - * Method description - * - * - * @param line - */ - private void parseLine(String line) - { - line = line.trim(); - - if (Util.isNotEmpty(line)) - { - String[] parts = line.split(":"); - - if (parts.length >= 2) - { - exludeSet.add(parts[0].concat(":").concat(parts[1])); - } - } - } - //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + private Set getExludeSet() + { + if (exludeSet == null) + { + try + { + exludeSet = loadExcludeSet(); + } + catch (IOException ex) + { + throw Throwables.propagate(ex); + } + } + + return exludeSet; + } + /** * Method description * @@ -164,5 +151,5 @@ public class AetherDependencyFilter implements DependencyFilter //~--- fields --------------------------------------------------------------- /** Field description */ - private Set exludeSet = new HashSet(); + private Set exludeSet; } diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/Aether.java b/scm-webapp/src/main/java/sonia/scm/plugin/Aether.java index 80f99cd918..6a27d5758f 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/Aether.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/Aether.java @@ -57,6 +57,7 @@ import org.sonatype.aether.resolution.DependencyRequest; import org.sonatype.aether.resolution.DependencyResolutionException; import org.sonatype.aether.util.artifact.DefaultArtifact; import org.sonatype.aether.util.artifact.JavaScopes; +import org.sonatype.aether.util.filter.AndDependencyFilter; import org.sonatype.aether.util.filter.DependencyFilterUtils; import org.sonatype.aether.util.graph.transformer .ChainedDependencyGraphTransformer; @@ -77,7 +78,11 @@ public final class Aether { /** Field description */ - private static final DependencyFilter FILTER = new AetherDependencyFilter(); + private static final DependencyFilter FILTER = + new AndDependencyFilter( + new CoreDependencyFilter(), + new BlacklistDependencyFilter() + ); /** * the logger for Aether @@ -167,7 +172,6 @@ public final class Aether * * * @param system - * @param repositoryManager * @param localRepository * @param configuration * diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/BlacklistDependencyFilter.java b/scm-webapp/src/main/java/sonia/scm/plugin/BlacklistDependencyFilter.java new file mode 100644 index 0000000000..b01da86a32 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/plugin/BlacklistDependencyFilter.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.util.Set; + +/** + * + * @author Sebastian Sdorra + */ +public class BlacklistDependencyFilter extends AbstractDependencyFilter +{ + + /** Field description */ + private static final String BLACKLIST = "/config/blacklist.list"; + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + * + * @throws IOException + */ + @Override + protected Set loadExcludeSet() throws IOException + { + return DependencyFilters.loadDependencySet(BLACKLIST); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/CoreDependencyFilter.java b/scm-webapp/src/main/java/sonia/scm/plugin/CoreDependencyFilter.java new file mode 100644 index 0000000000..528cc19ef5 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/plugin/CoreDependencyFilter.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.util.Set; + +/** + * + * @author Sebastian Sdorra + */ +public class CoreDependencyFilter extends AbstractDependencyFilter +{ + + /** Field description */ + private static final String CORE_DEPENDENCIES = "/config/dependencies.list"; + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + * + * @throws IOException + */ + @Override + protected Set loadExcludeSet() throws IOException + { + return DependencyFilters.loadDependencySet(CORE_DEPENDENCIES); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/DependencyFilters.java b/scm-webapp/src/main/java/sonia/scm/plugin/DependencyFilters.java new file mode 100644 index 0000000000..a2088f07b2 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/plugin/DependencyFilters.java @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.base.Charsets; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.io.Resources; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.net.URL; + +import java.util.List; +import java.util.Set; + +/** + * + * @author Sebastian Sdorra + */ +public final class DependencyFilters +{ + + /** + * Method description + * + * + * @param path + * + * @return + * + * @throws IOException + */ + public static Set loadDependencySet(String path) throws IOException + { + URL url = Resources.getResource(DependencyFilters.class, path); + + if (url == null) + { + throw new IllegalArgumentException( + "could not find dependency set at ".concat(path)); + } + + Builder builder = ImmutableSet.builder(); + List lines = Resources.readLines(url, Charsets.UTF_8); + + for (String line : lines) + { + parseAndAppendLine(builder, line); + } + + return builder.build(); + } + + /** + * Method description + * + * + * @param builder + * @param line + */ + private static void parseAndAppendLine(Builder builder, String line) + { + line = line.trim(); + + if (!Strings.isNullOrEmpty(line)) + { + String[] parts = line.split(":"); + + if (parts.length >= 2) + { + builder.add(parts[0].concat(":").concat(parts[1])); + } + } + } +} diff --git a/scm-webapp/src/main/resources/config/blacklist.list b/scm-webapp/src/main/resources/config/blacklist.list new file mode 100644 index 0000000000..e6fb1b0be7 --- /dev/null +++ b/scm-webapp/src/main/resources/config/blacklist.list @@ -0,0 +1,10 @@ + +The following dependencies are blacklisted + commons-logging:commons-logging + log4j:log4j + junit:junit + org.mockito:mockito-core + org.mockito:mockito-all + org.mockito:mockito-junit + org.testng:testng + org.powermock:powermock \ No newline at end of file From 8664abb1b62224ecb035935e92306fbc416b4f94 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 13 Mar 2014 21:11:34 +0100 Subject: [PATCH 28/46] enable animal-sniffer-maven-plugin on goal compile --- pom.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pom.xml b/pom.xml index 58e5a92213..0a24ba0c4c 100644 --- a/pom.xml +++ b/pom.xml @@ -156,6 +156,14 @@ 1.0 + + + compile + + check + + + From 43481a70eef1a2431c3ecb00ab94d5de25cef6c4 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 13 Mar 2014 21:11:48 +0100 Subject: [PATCH 29/46] fix animal-sniffer problem --- .../main/java/sonia/scm/store/JAXBConfigurationEntryStore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStore.java b/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStore.java index 3fafd26e6d..fea2c7220a 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStore.java +++ b/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStore.java @@ -409,7 +409,7 @@ public class JAXBConfigurationEntryStore { //J- writer = new IndentXMLStreamWriter( - XMLOutputFactory.newFactory().createXMLStreamWriter( + XMLOutputFactory.newInstance().createXMLStreamWriter( createWriter() ) ); From 98f1ba44d6dd6134bc5256ac6871ee5cefb7e222 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 15 Mar 2014 13:47:26 +0100 Subject: [PATCH 30/46] close branch issue-545 From 1d9dcfda63aebcbf278f6eb0a853b4538df30fcb Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 15 Mar 2014 14:06:54 +0100 Subject: [PATCH 31/46] added protected methods for error handling --- .../web/filter/BasicAuthenticationFilter.java | 42 ++++++++++++-- .../scm/web/filter/PermissionFilter.java | 55 +++++++++++++++---- 2 files changed, 81 insertions(+), 16 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java index fe1aed181a..b184e2b4ae 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java @@ -218,15 +218,47 @@ public class BasicAuthenticationFilter extends AutoLoginFilter // see https://bitbucket.org/sdorra/scm-manager/issue/545/git-clone-with-username-in-url-does-not if (Boolean.TRUE.equals(request.getAttribute(ATTRIBUTE_FAILED_AUTH))) { - response.sendError(HttpServletResponse.SC_FORBIDDEN); + sendFailedAuthenticationError(request, response); } else { - HttpUtil.sendUnauthorized(request, response, - configuration.getRealmDescription()); + sendUnauthorizedError(request, response); } } + /** + * Sends an error for a failed authentication back to client. + * + * + * @param request http request + * @param response http response + * + * @throws IOException + */ + protected void sendFailedAuthenticationError(HttpServletRequest request, + HttpServletResponse response) + throws IOException + { + response.sendError(HttpServletResponse.SC_FORBIDDEN); + } + + /** + * Sends an unauthorized error back to client. + * + * + * @param request http request + * @param response http response + * + * @throws IOException + */ + protected void sendUnauthorizedError(HttpServletRequest request, + HttpServletResponse response) + throws IOException + { + HttpUtil.sendUnauthorized(request, response, + configuration.getRealmDescription()); + } + /** * Method description * @@ -300,6 +332,6 @@ public class BasicAuthenticationFilter extends AutoLoginFilter //~--- fields --------------------------------------------------------------- - /** Field description */ - private ScmConfiguration configuration; + /** scm main configuration */ + protected ScmConfiguration configuration; } diff --git a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java index 07051e5154..defa83a1b7 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java @@ -50,6 +50,7 @@ import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.PermissionType; import sonia.scm.repository.PermissionUtil; import sonia.scm.repository.Repository; +import sonia.scm.security.Role; import sonia.scm.security.ScmSecurityException; import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; @@ -65,7 +66,6 @@ import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import sonia.scm.security.Role; /** * Abstract http filter to check repository permissions. @@ -98,7 +98,7 @@ public abstract class PermissionFilter extends HttpFilter * * @param configuration global scm-manager configuration * @param securityContextProvider security context provider - * + * * @deprecated {@link #PermissionFilter(ScmConfiguration)} instead */ @Deprecated @@ -133,11 +133,11 @@ public abstract class PermissionFilter extends HttpFilter //~--- methods -------------------------------------------------------------- /** - * Checks the permission for the requested repository. If the user has enough + * Checks the permission for the requested repository. If the user has enough * permission, then the filter chain is called. * * - * @param request http request + * @param request http request * @param response http response * @param chain filter chain * @@ -179,7 +179,7 @@ public abstract class PermissionFilter extends HttpFilter getUserName(subject)); } - sendAccessDenied(response, subject); + sendAccessDenied(request, response, subject); } } else @@ -216,11 +216,43 @@ public abstract class PermissionFilter extends HttpFilter subject.getPrincipal()); } - sendAccessDenied(response, subject); + sendAccessDenied(request, response, subject); } } + /** + * Sends a "not enough privileges" error back to client. + * + * + * @param request http request + * @param response http response + * + * @throws IOException + */ + protected void sendNotEnoughPrivilegesError(HttpServletRequest request, + HttpServletResponse response) + throws IOException + { + response.sendError(HttpServletResponse.SC_FORBIDDEN); + } + + /** + * Sends an unauthorized error back to client. + * + * + * @param request http request + * @param response http response + * + * @throws IOException + */ + protected void sendUnauthorizedError(HttpServletRequest request, + HttpServletResponse response) + throws IOException + { + HttpUtil.sendUnauthorized(response, configuration.getRealmDescription()); + } + /** * Extracts the type of the repositroy from url. * @@ -247,22 +279,23 @@ public abstract class PermissionFilter extends HttpFilter /** * Send access denied to the servlet response. * - * + * @param request current http request object * @param response current http response object * @param subject user subject * * @throws IOException */ - private void sendAccessDenied(HttpServletResponse response, Subject subject) + private void sendAccessDenied(HttpServletRequest request, + HttpServletResponse response, Subject subject) throws IOException { if (subject.hasRole(Role.USER)) { - response.sendError(HttpServletResponse.SC_FORBIDDEN); + sendNotEnoughPrivilegesError(request, response); } else { - HttpUtil.sendUnauthorized(response, configuration.getRealmDescription()); + sendUnauthorizedError(request, response); } } @@ -351,5 +384,5 @@ public abstract class PermissionFilter extends HttpFilter //~--- fields --------------------------------------------------------------- /** scm-manager global configuration */ - private ScmConfiguration configuration; + private final ScmConfiguration configuration; } From 371e4e4de6a19d09beab161ec754d4faeb939203 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 15 Mar 2014 14:14:46 +0100 Subject: [PATCH 32/46] improved git error messages for failed authentication and not enough permissions --- .../java/sonia/scm/repository/GitUtil.java | 24 ++++ .../scm/web/GitBasicAuthenticationFilter.java | 109 ++++++++++++++++++ .../sonia/scm/web/GitPermissionFilter.java | 54 +++++++-- .../java/sonia/scm/web/GitServletModule.java | 3 +- 4 files changed, 178 insertions(+), 12 deletions(-) create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index 6dd4996b47..29ebf9d6e7 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -36,6 +36,7 @@ package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Strings; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; @@ -66,9 +67,12 @@ import sonia.scm.util.Util; import java.io.File; import java.io.IOException; +import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; +import javax.servlet.http.HttpServletRequest; + /** * * @author Sebastian Sdorra @@ -94,6 +98,9 @@ public final class GitUtil /** Field description */ private static final String DIRECTORY_REFS = "refs"; + /** Field description */ + private static final String HEADER_USERAGENT = "User-Agent"; + /** Field description */ private static final String PREFIX_HEADS = "refs/heads/"; @@ -109,6 +116,9 @@ public final class GitUtil /** Field description */ private static final int TIMEOUT = 5; + /** Field description */ + private static final String USERAGENT_GIT = "git/"; + /** the logger for GitUtil */ private static final Logger logger = LoggerFactory.getLogger(GitUtil.class); @@ -652,6 +662,20 @@ public final class GitUtil return name; } + /** + * Returns true if the request comes from a git client. + * + * + * @param request servlet request + * + * @return true if the client is git + */ + public static boolean isGitClient(HttpServletRequest request) + { + return Strings.nullToEmpty(request.getHeader(HEADER_USERAGENT)).toLowerCase( + Locale.ENGLISH).startsWith(USERAGENT_GIT); + } + /** * Method description * diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java new file mode 100644 index 0000000000..b69ce418c4 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.web; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import org.eclipse.jgit.http.server.GitSmartHttpTools; + +import sonia.scm.config.ScmConfiguration; +import sonia.scm.repository.GitUtil; +import sonia.scm.web.filter.AutoLoginModule; +import sonia.scm.web.filter.BasicAuthenticationFilter; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Sebastian Sdorra + */ +@Singleton +public class GitBasicAuthenticationFilter extends BasicAuthenticationFilter +{ + + /** Field description */ + private static final String MESSAGE_FAILED_AUTHENTICATION = + "Invalid username or password."; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param configuration + * @param autoLoginModules + */ + @Inject + public GitBasicAuthenticationFilter(ScmConfiguration configuration, + Set autoLoginModules) + { + super(configuration, autoLoginModules); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param request + * @param response + * + * @throws IOException + */ + @Override + protected void sendFailedAuthenticationError(HttpServletRequest request, + HttpServletResponse response) + throws IOException + { + if (GitUtil.isGitClient(request)) + { + GitSmartHttpTools.sendError(request, response, + HttpServletResponse.SC_FORBIDDEN, MESSAGE_FAILED_AUTHENTICATION); + } + else + { + super.sendFailedAuthenticationError(request, response); + } + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java index c277c0cf7f..88c6f52d21 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java @@ -38,13 +38,19 @@ package sonia.scm.web; import com.google.inject.Inject; import com.google.inject.Singleton; +import org.eclipse.jgit.http.server.GitSmartHttpTools; + +import sonia.scm.config.ScmConfiguration; +import sonia.scm.repository.GitUtil; import sonia.scm.repository.RepositoryProvider; import sonia.scm.web.filter.ProviderPermissionFilter; //~--- JDK imports ------------------------------------------------------------ +import java.io.IOException; + import javax.servlet.http.HttpServletRequest; -import sonia.scm.config.ScmConfiguration; +import javax.servlet.http.HttpServletResponse; /** * @@ -66,24 +72,52 @@ public class GitPermissionFilter extends ProviderPermissionFilter /** Field description */ public static final String URI_REF_INFO = "/info/refs"; + /** Field description */ + private static final String MESSAGE_NOT_ENOUGH_PRIVILEGES = + "You do not have enough access privileges for this operation."; + //~--- constructors --------------------------------------------------------- /** * Constructs ... * - * - * - * @param securityContextProvider + * @param configuration * @param repositoryProvider */ @Inject - public GitPermissionFilter( - ScmConfiguration configuration, - RepositoryProvider repositoryProvider) + public GitPermissionFilter(ScmConfiguration configuration, + RepositoryProvider repositoryProvider) { super(configuration, repositoryProvider); } + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param request + * @param response + * + * @throws IOException + */ + @Override + protected void sendNotEnoughPrivilegesError(HttpServletRequest request, + HttpServletResponse response) + throws IOException + { + if (GitUtil.isGitClient(request)) + { + GitSmartHttpTools.sendError(request, response, + HttpServletResponse.SC_FORBIDDEN, MESSAGE_NOT_ENOUGH_PRIVILEGES); + } + else + { + super.sendNotEnoughPrivilegesError(request, response); + } + } + //~--- get methods ---------------------------------------------------------- /** @@ -100,8 +134,8 @@ public class GitPermissionFilter extends ProviderPermissionFilter String uri = request.getRequestURI(); return uri.endsWith(URI_RECEIVE_PACK) - || (uri.endsWith(URI_REF_INFO) - && PARAMETER_VALUE_RECEIVE.equals( - request.getParameter(PARAMETER_SERVICE))); + || (uri.endsWith(URI_REF_INFO) + && PARAMETER_VALUE_RECEIVE.equals( + request.getParameter(PARAMETER_SERVICE))); } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java index fd7300817b..fdb1ae52d9 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java @@ -40,7 +40,6 @@ import com.google.inject.servlet.ServletModule; import org.eclipse.jgit.transport.ScmTransportProtocol; import sonia.scm.plugin.ext.Extension; -import sonia.scm.web.filter.BasicAuthenticationFilter; /** * @@ -68,7 +67,7 @@ public class GitServletModule extends ServletModule bind(ScmTransportProtocol.class); // serlvelts and filters - filter(PATTERN_GIT).through(BasicAuthenticationFilter.class); + filter(PATTERN_GIT).through(GitBasicAuthenticationFilter.class); filter(PATTERN_GIT).through(GitPermissionFilter.class); serve(PATTERN_GIT).with(ScmGitServlet.class); } From 84d3cadb1292414b5f33e9866d97f757c246ce3b Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 15 Mar 2014 15:40:55 +0100 Subject: [PATCH 33/46] prompt authentication again for failed subversion authentication and improved error message for missing privileges --- .../main/java/sonia/scm/util/HttpUtil.java | 68 ++++++++++-- .../sonia/scm/repository/ScmSvnErrorCode.java | 71 ++++++++++++ .../java/sonia/scm/repository/SvnUtil.java | 103 +++++++++++++++++ .../scm/web/SvnBasicAuthenticationFilter.java | 105 ++++++++++++++++++ .../sonia/scm/web/SvnPermissionFilter.java | 46 ++++++-- .../java/sonia/scm/web/SvnServletModule.java | 2 +- 6 files changed, 377 insertions(+), 18 deletions(-) create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/ScmSvnErrorCode.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java diff --git a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java index 150d1a3ba4..c8717c1cb7 100644 --- a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java @@ -37,6 +37,7 @@ package sonia.scm.util; import com.google.common.base.CharMatcher; import com.google.common.base.Strings; +import com.google.common.io.ByteStreams; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,6 +47,7 @@ import sonia.scm.config.ScmConfiguration; //~--- JDK imports ------------------------------------------------------------ import java.io.IOException; +import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; @@ -158,6 +160,9 @@ public final class HttpUtil public static final String STATUS_UNAUTHORIZED_MESSAGE = "Authorization Required"; + /** Field description */ + private static final int SKIP_SIZE = 4096; + /** the logger for HttpUtil */ private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class); @@ -167,7 +172,7 @@ public final class HttpUtil */ private static final Pattern PATTERN_URLNORMALIZE = Pattern.compile("(?:(http://[^:]+):80(/.+)?|(https://[^:]+):443(/.+)?)"); - + /** * CharMatcher to select cr/lf and '%' characters * @since 1.28 @@ -197,10 +202,10 @@ public final class HttpUtil */ public static String append(String uri, String suffix) { - if ( uri.endsWith(SEPARATOR_PATH) && suffix.startsWith(SEPARATOR_PATH) ) + if (uri.endsWith(SEPARATOR_PATH) && suffix.startsWith(SEPARATOR_PATH)) { - uri = uri.substring( 0, uri.length() - 1 ); - } + uri = uri.substring(0, uri.length() - 1); + } else if (!uri.endsWith(SEPARATOR_PATH) &&!suffix.startsWith(SEPARATOR_PATH)) { uri = uri.concat(SEPARATOR_PATH); @@ -299,6 +304,38 @@ public final class HttpUtil return value; } + /** + * Skips to complete body of a request. + * + * + * @param request http request + * + * @since 1.37 + */ + public static void drainBody(HttpServletRequest request) + { + if (isChunked(request) || (request.getContentLength() > 0)) + { + InputStream in = null; + + try + { + in = request.getInputStream(); + + while ((0 < in.skip(SKIP_SIZE)) || (0 <= in.read())) + { + + // nothing + } + } + catch (IOException e) {} + finally + { + IOUtil.close(in); + } + } + } + /** * Method description * @@ -443,10 +480,11 @@ public final class HttpUtil * @param realmDescription - realm description * * @throws IOException - * + * * @since 1.36 */ - public static void sendUnauthorized(HttpServletResponse response, String realmDescription) + public static void sendUnauthorized(HttpServletResponse response, + String realmDescription) throws IOException { sendUnauthorized(null, response, realmDescription); @@ -465,8 +503,7 @@ public final class HttpUtil * @since 1.19 */ public static void sendUnauthorized(HttpServletRequest request, - HttpServletResponse response, - String realmDescription) + HttpServletResponse response, String realmDescription) throws IOException { if ((request == null) ||!isWUIRequest(request)) @@ -671,6 +708,21 @@ public final class HttpUtil return uri; } + /** + * Returns true if the body of the request is chunked. + * + * + * @param request http request + * + * @return true if the request is chunked + * + * @since 1.37 + */ + public static boolean isChunked(HttpServletRequest request) + { + return "chunked".equals(request.getHeader("Transfer-Encoding")); + } + /** * Returns true if the http request is send by the scm-manager web interface. * diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/ScmSvnErrorCode.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/ScmSvnErrorCode.java new file mode 100644 index 0000000000..58df07c7de --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/ScmSvnErrorCode.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.tmatesoft.svn.core.SVNErrorCode; + +/** + * + * @author Sebastian Sdorra + */ +public class ScmSvnErrorCode extends SVNErrorCode +{ + + /** Field description */ + public static final SVNErrorCode AUTHN_FAILED = + new ScmSvnErrorCode(AUTHN_CATEGORY, 4, "Authentication failed"); + + /** Field description */ + public static final SVNErrorCode AUTHZ_NOT_ENOUGH_PRIVILEGES = + new ScmSvnErrorCode(AUTHZ_CATEGORY, 4, + "You do not have enough access privileges for this operation."); + + /** Field description */ + private static final long serialVersionUID = -6864996390796610410L; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param category + * @param index + * @param description + */ + protected ScmSvnErrorCode(int category, int index, String description) + { + super(category, index, description); + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java index abe5689712..60521ccbd1 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java @@ -37,23 +37,37 @@ package sonia.scm.repository; import com.google.common.base.Strings; import com.google.common.collect.Lists; +import com.google.common.io.Closeables; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.SVNLogEntryPath; +import org.tmatesoft.svn.core.internal.io.dav.DAVElement; +import org.tmatesoft.svn.core.internal.server.dav.DAVXMLUtil; +import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil; +import org.tmatesoft.svn.core.internal.util.SVNXMLUtil; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.wc.SVNClientManager; import org.tmatesoft.svn.core.wc.admin.SVNChangeEntry; +import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ +import java.io.IOException; +import java.io.PrintWriter; + import java.util.List; +import java.util.Locale; import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + /** * * @author Sebastian Sdorra @@ -61,6 +75,12 @@ import java.util.Map; public final class SvnUtil { + /** Field description */ + public static final String XML_CONTENT_TYPE = "text/xml; charset=\"utf-8\""; + + /** Field description */ + private static final String HEADER_USERAGENT = "User-Agent"; + /** Field description */ private static final String ID_TRANSACTION_PREFIX = "-1:"; @@ -70,6 +90,9 @@ public final class SvnUtil */ private static final char TYPE_UPDATED = 'U'; + /** Field description */ + private static final String USERAGENT_SVN = "svn/"; + /** * the logger for SvnUtil */ @@ -232,6 +255,39 @@ public final class SvnUtil return changesets; } + /** + * Method description + * + * @param errorCode + * + * @return + */ + public static String createErrorBody(SVNErrorCode errorCode) + { + StringBuffer xmlBuffer = new StringBuffer(); + + SVNXMLUtil.addXMLHeader(xmlBuffer); + + List namespaces = Lists.newArrayList(DAVElement.DAV_NAMESPACE, + DAVElement.SVN_APACHE_PROPERTY_NAMESPACE); + + SVNXMLUtil.openNamespaceDeclarationTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, + DAVXMLUtil.SVN_DAV_ERROR_TAG, namespaces, SVNXMLUtil.PREFIX_MAP, + xmlBuffer); + + SVNXMLUtil.openXMLTag(SVNXMLUtil.SVN_APACHE_PROPERTY_PREFIX, + "human-readable", SVNXMLUtil.XML_STYLE_NORMAL, "errcode", + String.valueOf(errorCode.getCode()), xmlBuffer); + xmlBuffer.append( + SVNEncodingUtil.xmlEncodeCDATA(errorCode.getDescription())); + SVNXMLUtil.closeXMLTag(SVNXMLUtil.SVN_APACHE_PROPERTY_PREFIX, + "human-readable", xmlBuffer); + SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, + DAVXMLUtil.SVN_DAV_ERROR_TAG, xmlBuffer); + + return xmlBuffer.toString(); + } + /** * Method description * @@ -266,6 +322,39 @@ public final class SvnUtil } } + /** + * Method description + * + * + * @param request + * @param response + * @param statusCode + * @param errorCode + * + * @throws IOException + */ + public static void sendError(HttpServletRequest request, + HttpServletResponse response, int statusCode, SVNErrorCode errorCode) + throws IOException + { + HttpUtil.drainBody(request); + + response.setStatus(statusCode); + response.setContentType(XML_CONTENT_TYPE); + + PrintWriter writer = null; + + try + { + writer = response.getWriter(); + writer.println(createErrorBody(errorCode)); + } + finally + { + Closeables.close(writer, true); + } + } + //~--- get methods ---------------------------------------------------------- /** @@ -311,6 +400,20 @@ public final class SvnUtil return id.substring(ID_TRANSACTION_PREFIX.length()); } + /** + * Method description + * + * + * @param request + * + * @return + */ + public static boolean isSvnClient(HttpServletRequest request) + { + return Strings.nullToEmpty(request.getHeader(HEADER_USERAGENT)).toLowerCase( + Locale.ENGLISH).startsWith(USERAGENT_SVN); + } + /** * Method description * diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java new file mode 100644 index 0000000000..383d081ff5 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.web; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import org.tmatesoft.svn.core.SVNErrorCode; + +import sonia.scm.config.ScmConfiguration; +import sonia.scm.repository.ScmSvnErrorCode; +import sonia.scm.repository.SvnUtil; +import sonia.scm.web.filter.AutoLoginModule; +import sonia.scm.web.filter.BasicAuthenticationFilter; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import sonia.scm.util.HttpUtil; + +/** + * + * @author Sebastian Sdorra + */ +@Singleton +public class SvnBasicAuthenticationFilter extends BasicAuthenticationFilter +{ + + /** + * Constructs ... + * + * + * @param configuration + * @param autoLoginModules + */ + @Inject + public SvnBasicAuthenticationFilter(ScmConfiguration configuration, + Set autoLoginModules) + { + super(configuration, autoLoginModules); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Sends unauthorized instead of forbidden for svn clients, because the + * svn client prompts again for authentication. + * + * + * @param request http request + * @param response http response + * + * @throws IOException + */ + @Override + protected void sendFailedAuthenticationError(HttpServletRequest request, + HttpServletResponse response) + throws IOException + { + if (SvnUtil.isSvnClient(request)) + { + HttpUtil.sendUnauthorized(response, configuration.getRealmDescription()); + } + else + { + super.sendFailedAuthenticationError(request, response); + } + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java index 164ccfd173..2d41e5d8ae 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java @@ -39,15 +39,22 @@ import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import com.google.inject.Singleton; +import org.tmatesoft.svn.core.SVNErrorCode; + import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.RepositoryProvider; +import sonia.scm.repository.ScmSvnErrorCode; +import sonia.scm.repository.SvnUtil; import sonia.scm.web.filter.ProviderPermissionFilter; //~--- JDK imports ------------------------------------------------------------ +import java.io.IOException; + import java.util.Set; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; /** * @@ -58,22 +65,16 @@ public class SvnPermissionFilter extends ProviderPermissionFilter { /** Field description */ - private static Set WRITEMETHOD_SET = ImmutableSet.of("MKACTIVITY", - "PROPPATCH", "PUT", - "CHECKOUT", "MKCOL", "MOVE", - "COPY", "DELETE", "LOCK", - "UNLOCK", "MERGE"); + private static final Set WRITEMETHOD_SET = + ImmutableSet.of("MKACTIVITY", "PROPPATCH", "PUT", "CHECKOUT", "MKCOL", + "MOVE", "COPY", "DELETE", "LOCK", "UNLOCK", "MERGE"); //~--- constructors --------------------------------------------------------- /** * Constructs ... * - * - * - * * @param configuration - * @param securityContextProvider * @param repository */ @Inject @@ -83,6 +84,33 @@ public class SvnPermissionFilter extends ProviderPermissionFilter super(configuration, repository); } + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param request + * @param response + * + * @throws IOException + */ + @Override + protected void sendNotEnoughPrivilegesError(HttpServletRequest request, + HttpServletResponse response) + throws IOException + { + if (SvnUtil.isSvnClient(request)) + { + SvnUtil.sendError(request, response, HttpServletResponse.SC_FORBIDDEN, + ScmSvnErrorCode.AUTHZ_NOT_ENOUGH_PRIVILEGES); + } + else + { + super.sendNotEnoughPrivilegesError(request, response); + } + } + //~--- get methods ---------------------------------------------------------- /** diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java index 689af8851b..9eda6fe7dd 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java @@ -69,7 +69,7 @@ public class SvnServletModule extends ServletModule protected void configureServlets() { filter(PATTERN_SVN).through(SvnGZipFilter.class); - filter(PATTERN_SVN).through(BasicAuthenticationFilter.class); + filter(PATTERN_SVN).through(SvnBasicAuthenticationFilter.class); filter(PATTERN_SVN).through(SvnPermissionFilter.class); Map parameters = new HashMap(); From 54faa5cb566e954b2fbed2e010ca257dfd70df5d Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 15 Mar 2014 16:11:44 +0100 Subject: [PATCH 34/46] the default implementation of the basic authentication filter should prompt again for username and password, if the authentication fails --- .../java/sonia/scm/web/filter/BasicAuthenticationFilter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java index b184e2b4ae..38532ff3ac 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java @@ -239,7 +239,8 @@ public class BasicAuthenticationFilter extends AutoLoginFilter HttpServletResponse response) throws IOException { - response.sendError(HttpServletResponse.SC_FORBIDDEN); + HttpUtil.sendUnauthorized(request, response, + configuration.getRealmDescription()); } /** From b131d4b804bd254f165fbcb9c8a8fd0f1de1507b Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 15 Mar 2014 16:12:14 +0100 Subject: [PATCH 35/46] improve error handling for failed authentication and not enough privileges --- .../scm/web/HgBasicAuthenticationFilter.java | 101 ++++++++++++++++++ .../sonia/scm/web/HgPermissionFilter.java | 3 - .../java/sonia/scm/web/HgServletModule.java | 2 +- .../src/main/java/sonia/scm/web/HgUtil.java | 24 +++++ 4 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java new file mode 100644 index 0000000000..fb94a50061 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.web; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.io.Closeables; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import sonia.scm.config.ScmConfiguration; +import sonia.scm.web.filter.AutoLoginModule; +import sonia.scm.web.filter.BasicAuthenticationFilter; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; +import java.io.PrintWriter; + +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Sebastian Sdorra + */ +@Singleton +public class HgBasicAuthenticationFilter extends BasicAuthenticationFilter +{ + + /** + * Constructs ... + * + * + * @param configuration + * @param autoLoginModules + */ + @Inject + public HgBasicAuthenticationFilter(ScmConfiguration configuration, + Set autoLoginModules) + { + super(configuration, autoLoginModules); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param request + * @param response + * + * @throws IOException + */ + @Override + protected void sendFailedAuthenticationError(HttpServletRequest request, + HttpServletResponse response) + throws IOException + { + if (HgUtil.isHgClient(request)) + { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } + else + { + super.sendFailedAuthenticationError(request, response); + } + } +} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java index 73d20530ea..0a9d3e43b9 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java @@ -57,9 +57,6 @@ public class HgPermissionFilter extends ProviderPermissionFilter /** * Constructs ... * - * - * @param securityContextProvider - * * @param configuration * @param repositoryProvider */ diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java index 792bafe80b..5bf080860a 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java @@ -75,7 +75,7 @@ public class HgServletModule extends ServletModule serve(MAPPING_HOOK).with(HgHookCallbackServlet.class); // register hg cgi servlet - filter(MAPPING_HG).through(BasicAuthenticationFilter.class); + filter(MAPPING_HG).through(HgBasicAuthenticationFilter.class); filter(MAPPING_HG).through(HgPermissionFilter.class); serve(MAPPING_HG).with(HgCGIServlet.class); } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgUtil.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgUtil.java index 0d7150205f..2db7c12d40 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgUtil.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgUtil.java @@ -58,6 +58,10 @@ import java.io.File; import java.nio.charset.Charset; +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; + /** * * @author Sebastian Sdorra @@ -68,6 +72,12 @@ public final class HgUtil /** Field description */ public static final String REVISION_TIP = "tip"; + /** Field description */ + private static final String HEADER_USERAGENT = "User-Agent"; + + /** Field description */ + private static final String USERAGENT_HG = "mercurial/"; + /** * the logger for HgUtil */ @@ -180,4 +190,18 @@ public final class HgUtil ? REVISION_TIP : revision; } + + /** + * Returns true if the request comes from a mercurial client. + * + * + * @param request servlet request + * + * @return true if the client is mercurial + */ + public static boolean isHgClient(HttpServletRequest request) + { + return Strings.nullToEmpty(request.getHeader(HEADER_USERAGENT)).toLowerCase( + Locale.ENGLISH).startsWith(USERAGENT_HG); + } } From bd72a810191bb845a87e6c131f0e440b0b6a52f1 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 15 Mar 2014 17:01:31 +0100 Subject: [PATCH 36/46] added small i18n framework --- .../src/main/java/sonia/scm/i18n/Bundle.java | 29 +- .../src/main/java/sonia/scm/i18n/I18n.java | 60 ++++ .../java/sonia/scm/i18n/I18nException.java | 85 ++++++ .../java/sonia/scm/i18n/I18nMessages.java | 267 ++++++++++++++++++ .../java/sonia/scm/i18n/I18nMessagesTest.java | 95 +++++++ .../java/sonia/scm/i18n/TestMessages.java | 60 ++++ .../sonia/scm/i18n/TestMessages.properties | 30 ++ .../scm/i18n/TestMessages_de_DE.properties | 30 ++ 8 files changed, 655 insertions(+), 1 deletion(-) create mode 100644 scm-core/src/main/java/sonia/scm/i18n/I18n.java create mode 100644 scm-core/src/main/java/sonia/scm/i18n/I18nException.java create mode 100644 scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java create mode 100644 scm-core/src/test/java/sonia/scm/i18n/I18nMessagesTest.java create mode 100644 scm-core/src/test/java/sonia/scm/i18n/TestMessages.java create mode 100644 scm-core/src/test/resources/sonia/scm/i18n/TestMessages.properties create mode 100644 scm-core/src/test/resources/sonia/scm/i18n/TestMessages_de_DE.properties diff --git a/scm-core/src/main/java/sonia/scm/i18n/Bundle.java b/scm-core/src/main/java/sonia/scm/i18n/Bundle.java index be349fddb7..11429133d8 100644 --- a/scm-core/src/main/java/sonia/scm/i18n/Bundle.java +++ b/scm-core/src/main/java/sonia/scm/i18n/Bundle.java @@ -30,6 +30,7 @@ */ + package sonia.scm.i18n; //~--- non-JDK imports -------------------------------------------------------- @@ -41,6 +42,7 @@ import sonia.scm.util.Util; import java.text.MessageFormat; import java.util.Locale; +import java.util.MissingResourceException; import java.util.ResourceBundle; /** @@ -134,8 +136,33 @@ public class Bundle return msg; } + /** + * Returns the value of the key, formatted with {@link MessageFormat} or null + * if the key is not present in the bundle. + * + * + * @param key key in the properties file + * @param args format arguments + * + * @return formated message or null + * + * @since 1.37 + */ + public String getStringIfPresent(String key, Object... args) + { + String msg = null; + + try + { + msg = getString(key, args); + } + catch (MissingResourceException ex) {} + + return msg; + } + //~--- fields --------------------------------------------------------------- /** Field description */ - private ResourceBundle bundle; + private final ResourceBundle bundle; } diff --git a/scm-core/src/main/java/sonia/scm/i18n/I18n.java b/scm-core/src/main/java/sonia/scm/i18n/I18n.java new file mode 100644 index 0000000000..63d761fb17 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/i18n/I18n.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.i18n; + +//~--- JDK imports ------------------------------------------------------------ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The I18n annotation is used by the {@link I18nMessages} class to define the + * resource bundle key. + * + * @author Sebastian Sdorra + * @since 1.37 + */ +@Documented +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface I18n +{ + /** + * Returns the key for the resource bundle. + * + * @return resource bundle key + */ + String value(); +} diff --git a/scm-core/src/main/java/sonia/scm/i18n/I18nException.java b/scm-core/src/main/java/sonia/scm/i18n/I18nException.java new file mode 100644 index 0000000000..dc7d062de7 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/i18n/I18nException.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.i18n; + +/** + * + * @author Sebastian Sdorra + */ +public class I18nException extends RuntimeException +{ + + /** Field description */ + private static final long serialVersionUID = 1845326427312983227L; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + public I18nException() {} + + /** + * Constructs ... + * + * + * @param message + */ + public I18nException(String message) + { + super(message); + } + + /** + * Constructs ... + * + * + * @param cause + */ + public I18nException(Throwable cause) + { + super(cause); + } + + /** + * Constructs ... + * + * + * @param message + * @param cause + */ + public I18nException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java b/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java new file mode 100644 index 0000000000..97ba0cb0c2 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java @@ -0,0 +1,267 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.i18n; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.base.Objects; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + +//~--- JDK imports ------------------------------------------------------------ + +import java.lang.reflect.Field; + +import java.util.Locale; + +/** + * The I18nMessages class instantiates a class and initializes all {@link String} + * fields with values from a resource bundle. The resource bundle must have the + * same name as the class. Each field which should be initialized from the + * bundle, must match a key in the resource bundle or is annotated with a + * {@link I18n} annotation which holds the key. I18nMessages injects also the + * locale and the bundle if it founds a field with the corresponding type. + * + * @author Sebastian Sdorra + * @since 1.37 + */ +public final class I18nMessages +{ + + /** Field description */ + private static final Cache cache = + CacheBuilder.newBuilder().build(); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + private I18nMessages() {} + + //~--- get methods ---------------------------------------------------------- + + /** + * Same as {@link #get(java.lang.Class, java.util.Locale)}, with locale + * {@link Locale#ENGLISH}. + * + * @param msgClass message class + * @param type of message class + * + * @return instance of message class + */ + public static T get(Class msgClass) + { + return get(msgClass, Locale.ENGLISH); + } + + /** + * Returns a instance of the given message class with all message fields + * initialized. + * + * + * @param msgClass message class + * @param locale locale + * @param type of the message class + * + * @return instance of message class + */ + public synchronized static T get(Class msgClass, Locale locale) + { + CacheKey ck = new CacheKey(locale, msgClass); + T instance = (T) cache.getIfPresent(ck); + + if (instance == null) + { + instance = createInstance(msgClass, locale); + cache.put(ck, instance); + } + + return instance; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param msgClass + * @param locale + * @param + * + * @return + */ + private static T createInstance(Class msgClass, Locale locale) + { + Bundle bundle = Bundle.getBundle(msgClass.getName(), locale); + T instance = null; + + try + { + instance = msgClass.newInstance(); + initializeInstance(bundle, locale, msgClass, instance); + } + catch (Exception ex) + { + throw new I18nException("could not instantiate/initialize class", ex); + } + + return instance; + } + + /** + * Method description + * + * + * @param bundle + * @param locale + * @param msgClass + * @param instance + * + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + private static void initializeInstance(Bundle bundle, Locale locale, + Class msgClass, Object instance) + throws IllegalArgumentException, IllegalAccessException + { + for (Field field : msgClass.getFields()) + { + if (field.getType().isAssignableFrom(String.class)) + { + String key = field.getName(); + I18n i18n = field.getAnnotation(I18n.class); + + if (i18n != null) + { + key = i18n.value(); + } + + String value = bundle.getString(key); + + if (value != null) + { + field.setAccessible(true); + field.set(instance, value); + } + } + else if (field.getType().isAssignableFrom(Bundle.class)) + { + field.setAccessible(true); + field.set(instance, bundle); + } + else if (field.getType().isAssignableFrom(Locale.class)) + { + + field.setAccessible(true); + field.set(instance, locale); + } + } + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 14/03/15 + * @author Enter your name here... + */ + private static class CacheKey + { + + /** + * Constructs ... + * + * + * @param locale + * @param msgClass + */ + public CacheKey(Locale locale, Class msgClass) + { + this.locale = locale; + this.msgClass = msgClass; + } + + //~--- methods ------------------------------------------------------------ + + /** + * Method description + * + * + * @param obj + * + * @return + */ + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + final CacheKey other = (CacheKey) obj; + + return Objects.equal(locale, other.locale) + && Objects.equal(msgClass, other.msgClass); + } + + /** + * Method description + * + * + * @return + */ + @Override + public int hashCode() + { + return Objects.hashCode(locale, msgClass); + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private final Locale locale; + + /** Field description */ + private final Class msgClass; + } +} diff --git a/scm-core/src/test/java/sonia/scm/i18n/I18nMessagesTest.java b/scm-core/src/test/java/sonia/scm/i18n/I18nMessagesTest.java new file mode 100644 index 0000000000..0760c4efb6 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/i18n/I18nMessagesTest.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.i18n; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.junit.Test; + +import sonia.scm.repository.Changeset; + +import static org.junit.Assert.*; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Locale; +import java.util.MissingResourceException; + +/** + * + * @author Sebastian Sdorra + */ +public class I18nMessagesTest +{ + + /** + * Method description + * + */ + @Test + public void testI18n() + { + TestMessages msg = I18nMessages.get(TestMessages.class); + + assertEquals("Normal Key", msg.normalKey); + assertEquals("Key with Annotation", msg.keyWithAnnotation); + assertNull(msg.someObject); + assertNotNull(msg.bundle); + assertEquals(Locale.ENGLISH, msg.locale); + } + + /** + * Method description + * + */ + @Test + public void testI18nOtherLanguage() + { + TestMessages msg = I18nMessages.get(TestMessages.class, Locale.GERMANY); + + assertEquals("Normaler Schlüssel", msg.normalKey); + assertEquals("Schlüssel mit Annotation", msg.keyWithAnnotation); + assertNull(msg.someObject); + assertNotNull(msg.bundle); + assertEquals(Locale.GERMANY, msg.locale); + } + + /** + * Method description + * + */ + @Test(expected = MissingResourceException.class) + public void testMissingBundle() + { + Changeset msg = I18nMessages.get(Changeset.class); + } +} diff --git a/scm-core/src/test/java/sonia/scm/i18n/TestMessages.java b/scm-core/src/test/java/sonia/scm/i18n/TestMessages.java new file mode 100644 index 0000000000..e1901eace9 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/i18n/TestMessages.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.i18n; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Locale; + +/** + * + * @author Sebastian Sdorra + */ +public class TestMessages +{ + + /** Field description */ + public Bundle bundle; + + /** Field description */ + @I18n("key_with_annotation") + public String keyWithAnnotation; + + /** Field description */ + public Locale locale; + + /** Field description */ + public String normalKey; + + /** Field description */ + public Integer someObject; +} diff --git a/scm-core/src/test/resources/sonia/scm/i18n/TestMessages.properties b/scm-core/src/test/resources/sonia/scm/i18n/TestMessages.properties new file mode 100644 index 0000000000..06a80bcae0 --- /dev/null +++ b/scm-core/src/test/resources/sonia/scm/i18n/TestMessages.properties @@ -0,0 +1,30 @@ +# Copyright (c) 2010, Sebastian Sdorra +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of SCM-Manager; nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# http://bitbucket.org/sdorra/scm-manager +# +key_with_annotation = Key with Annotation +normalKey = Normal Key \ No newline at end of file diff --git a/scm-core/src/test/resources/sonia/scm/i18n/TestMessages_de_DE.properties b/scm-core/src/test/resources/sonia/scm/i18n/TestMessages_de_DE.properties new file mode 100644 index 0000000000..c370bc25d8 --- /dev/null +++ b/scm-core/src/test/resources/sonia/scm/i18n/TestMessages_de_DE.properties @@ -0,0 +1,30 @@ +# Copyright (c) 2010, Sebastian Sdorra +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of SCM-Manager; nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# http://bitbucket.org/sdorra/scm-manager +# +key_with_annotation = Schl\u00fcssel mit Annotation +normalKey = Normaler Schl\u00fcssel \ No newline at end of file From d9579c347344d02597350c2d5c701191556efdb7 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 15 Mar 2014 17:06:52 +0100 Subject: [PATCH 37/46] fix bug in user create form --- .../src/main/webapp/resources/js/override/ext.form.vtypes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js b/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js index df17eeaee7..91d5307577 100644 --- a/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js +++ b/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js @@ -75,7 +75,7 @@ Ext.apply(Ext.form.VTypes, { // username validator username: function(val){ - return name(val); + return this.name(val); }, usernameText: 'The username is invalid.' From e59eb6a458bccccb565fe45ac005d42cfe4557c4 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 16 Mar 2014 10:29:30 +0100 Subject: [PATCH 38/46] added method to get I18nMessages from servlet request --- .../java/sonia/scm/i18n/I18nMessages.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java b/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java index 97ba0cb0c2..a0d8adff3c 100644 --- a/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java +++ b/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java @@ -43,6 +43,8 @@ import java.lang.reflect.Field; import java.util.Locale; +import javax.servlet.http.HttpServletRequest; + /** * The I18nMessages class instantiates a class and initializes all {@link String} * fields with values from a resource bundle. The resource bundle must have the @@ -85,6 +87,22 @@ public final class I18nMessages return get(msgClass, Locale.ENGLISH); } + /** + * Same as {@link #get(java.lang.Class, java.util.Locale)}, with locale + * from servlet request ({@link HttpServletRequest#getLocale()}). + * + * + * @param msgClass message class + * @param request servlet request + * @param type of message class + * + * @return + */ + public static T get(Class msgClass, HttpServletRequest request) + { + return get(msgClass, request.getLocale()); + } + /** * Returns a instance of the given message class with all message fields * initialized. @@ -156,7 +174,7 @@ public final class I18nMessages Class msgClass, Object instance) throws IllegalArgumentException, IllegalAccessException { - for (Field field : msgClass.getFields()) + for (Field field : msgClass.getDeclaredFields()) { if (field.getType().isAssignableFrom(String.class)) { From b13722bdd6ec3bd56c5a575e30ddaa858877a404 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 16 Mar 2014 10:48:13 +0100 Subject: [PATCH 39/46] use context classloader to load resource bundles --- .../src/main/java/sonia/scm/i18n/Bundle.java | 39 ++++++++-- .../java/sonia/scm/i18n/I18nMessages.java | 5 +- .../java/sonia/scm/util/ClassLoaders.java | 72 +++++++++++++++++++ 3 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/util/ClassLoaders.java diff --git a/scm-core/src/main/java/sonia/scm/i18n/Bundle.java b/scm-core/src/main/java/sonia/scm/i18n/Bundle.java index 11429133d8..515ced9ef8 100644 --- a/scm-core/src/main/java/sonia/scm/i18n/Bundle.java +++ b/scm-core/src/main/java/sonia/scm/i18n/Bundle.java @@ -35,6 +35,7 @@ package sonia.scm.i18n; //~--- non-JDK imports -------------------------------------------------------- +import sonia.scm.util.ClassLoaders; import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ @@ -83,7 +84,7 @@ public class Bundle */ public static Bundle getBundle(String path) { - return new Bundle(ResourceBundle.getBundle(path)); + return getBundle(path, null, null); } /** @@ -97,7 +98,35 @@ public class Bundle */ public static Bundle getBundle(String path, Locale locale) { - return new Bundle(ResourceBundle.getBundle(path, locale)); + return getBundle(path, locale, null); + } + + /** + * Creates a new bundle instance + * + * + * @param path path to the properties file + * @param locale locale for the properties file + * @param classLoader classLoader to load + * + * @return new bundle instance + * + * @since 1.37 + */ + public static Bundle getBundle(String path, Locale locale, + ClassLoader classLoader) + { + if (locale == null) + { + locale = Locale.ENGLISH; + } + + if (classLoader == null) + { + classLoader = ClassLoaders.getContextClassLoader(Bundle.class); + } + + return new Bundle(ResourceBundle.getBundle(path, locale, classLoader)); } /** @@ -137,7 +166,7 @@ public class Bundle } /** - * Returns the value of the key, formatted with {@link MessageFormat} or null + * Returns the value of the key, formatted with {@link MessageFormat} or null * if the key is not present in the bundle. * * @@ -145,7 +174,7 @@ public class Bundle * @param args format arguments * * @return formated message or null - * + * * @since 1.37 */ public String getStringIfPresent(String key, Object... args) @@ -163,6 +192,6 @@ public class Bundle //~--- fields --------------------------------------------------------------- - /** Field description */ + /** resource bundle */ private final ResourceBundle bundle; } diff --git a/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java b/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java index a0d8adff3c..0c11066f82 100644 --- a/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java +++ b/scm-core/src/main/java/sonia/scm/i18n/I18nMessages.java @@ -37,6 +37,8 @@ import com.google.common.base.Objects; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import sonia.scm.util.ClassLoaders; + //~--- JDK imports ------------------------------------------------------------ import java.lang.reflect.Field; @@ -142,7 +144,8 @@ public final class I18nMessages */ private static T createInstance(Class msgClass, Locale locale) { - Bundle bundle = Bundle.getBundle(msgClass.getName(), locale); + Bundle bundle = Bundle.getBundle(msgClass.getName(), locale, + ClassLoaders.getContextClassLoader(msgClass)); T instance = null; try diff --git a/scm-core/src/main/java/sonia/scm/util/ClassLoaders.java b/scm-core/src/main/java/sonia/scm/util/ClassLoaders.java new file mode 100644 index 0000000000..80998ef693 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/util/ClassLoaders.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.util; + +/** + * Util methods for {@link ClassLoader}s. + * + * @author Sebastian Sdorra + * @since 1.37 + */ +public final class ClassLoaders +{ + + /** + * Constructs ... + * + */ + private ClassLoaders() {} + + //~--- get methods ---------------------------------------------------------- + + /** + * Returns the context {@link ClassLoader} from the current {@link Thread}, if + * the context {@link ClassLoader} is not available the {@link ClassLoader}, + * which has load the given context class, is used. + * + * + * @param contextClass context class + * + * @return context class loader + */ + public static ClassLoader getContextClassLoader(Class contextClass) + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + if (classLoader == null) + { + classLoader = contextClass.getClassLoader(); + } + + return classLoader; + } +} From 2f9e761644a1b974577fe0eed900d10458196b18 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 16 Mar 2014 11:26:20 +0100 Subject: [PATCH 40/46] added central class for client messages --- .../main/java/sonia/scm/ClientMessages.java | 103 ++++++++++++++++++ .../sonia/scm/ClientMessages.properties | 31 ++++++ 2 files changed, 134 insertions(+) create mode 100644 scm-core/src/main/java/sonia/scm/ClientMessages.java create mode 100644 scm-core/src/main/resources/sonia/scm/ClientMessages.properties diff --git a/scm-core/src/main/java/sonia/scm/ClientMessages.java b/scm-core/src/main/java/sonia/scm/ClientMessages.java new file mode 100644 index 0000000000..d03bb34fad --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/ClientMessages.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm; + +//~--- non-JDK imports -------------------------------------------------------- + +import javax.servlet.http.HttpServletRequest; +import sonia.scm.i18n.I18nMessages; + +//~--- JDK imports ------------------------------------------------------------ + + +/** + * I18n messages which are send back to client. + * + * @author Sebastian Sdorra + * @since 1.37 + */ +public final class ClientMessages +{ + + /** + * Constructs a new instance of ClientMessages. This constructor should not be + * used. Use the {@link #get(javax.servlet.http.HttpServletRequest)} method + * instead. + */ + public ClientMessages() {} + + //~--- methods -------------------------------------------------------------- + + /** + * Returns the localized string for a failed authentication. + * + * + * @return localized string + */ + public String failedAuthentication() + { + return failedAuthentication; + } + + /** + * Returns the localized string for "not enough privileges. + * + * + * @return localized string + */ + public String notEnoughPrivileges() + { + return notEnoughPrivileges; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Returns an instance {@link ClientMessages}. + * + * @param request servlet request + * + * @return instance of client messages + */ + public static ClientMessages get(HttpServletRequest request) + { + return I18nMessages.get(ClientMessages.class, request); + } + + //~--- fields --------------------------------------------------------------- + + /** failed authentication */ + private String failedAuthentication; + + /** not enough privileges */ + private String notEnoughPrivileges; +} diff --git a/scm-core/src/main/resources/sonia/scm/ClientMessages.properties b/scm-core/src/main/resources/sonia/scm/ClientMessages.properties new file mode 100644 index 0000000000..9141761056 --- /dev/null +++ b/scm-core/src/main/resources/sonia/scm/ClientMessages.properties @@ -0,0 +1,31 @@ +# Copyright (c) 2010, Sebastian Sdorra +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of SCM-Manager; nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# http://bitbucket.org/sdorra/scm-manager +# + +failedAuthentication = Invalid username or password. +notEnoughPrivileges = You do not have enough access privileges for this operation. \ No newline at end of file From 9db7284f2776859628ecd46e11b5f87b75e91a21 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 16 Mar 2014 11:28:09 +0100 Subject: [PATCH 41/46] use client messages --- .../scm/web/GitBasicAuthenticationFilter.java | 11 +++----- .../sonia/scm/web/GitPermissionFilter.java | 8 +++--- .../scm/web/HgBasicAuthenticationFilter.java | 2 -- .../sonia/scm/repository/ScmSvnErrorCode.java | 26 ++++++++++++------- .../scm/web/SvnBasicAuthenticationFilter.java | 5 +--- .../sonia/scm/web/SvnPermissionFilter.java | 15 ++++++++--- 6 files changed, 35 insertions(+), 32 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java index b69ce418c4..5f71cf4e48 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitBasicAuthenticationFilter.java @@ -38,6 +38,7 @@ import com.google.inject.Singleton; import org.eclipse.jgit.http.server.GitSmartHttpTools; +import sonia.scm.ClientMessages; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.GitUtil; import sonia.scm.web.filter.AutoLoginModule; @@ -60,12 +61,6 @@ import javax.servlet.http.HttpServletResponse; public class GitBasicAuthenticationFilter extends BasicAuthenticationFilter { - /** Field description */ - private static final String MESSAGE_FAILED_AUTHENTICATION = - "Invalid username or password."; - - //~--- constructors --------------------------------------------------------- - /** * Constructs ... * @@ -96,10 +91,12 @@ public class GitBasicAuthenticationFilter extends BasicAuthenticationFilter HttpServletResponse response) throws IOException { + System.out.println(ClientMessages.get(request).failedAuthentication()); if (GitUtil.isGitClient(request)) { GitSmartHttpTools.sendError(request, response, - HttpServletResponse.SC_FORBIDDEN, MESSAGE_FAILED_AUTHENTICATION); + HttpServletResponse.SC_FORBIDDEN, + ClientMessages.get(request).failedAuthentication()); } else { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java index 88c6f52d21..f682c355a6 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java @@ -40,6 +40,7 @@ import com.google.inject.Singleton; import org.eclipse.jgit.http.server.GitSmartHttpTools; +import sonia.scm.ClientMessages; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.GitUtil; import sonia.scm.repository.RepositoryProvider; @@ -72,10 +73,6 @@ public class GitPermissionFilter extends ProviderPermissionFilter /** Field description */ public static final String URI_REF_INFO = "/info/refs"; - /** Field description */ - private static final String MESSAGE_NOT_ENOUGH_PRIVILEGES = - "You do not have enough access privileges for this operation."; - //~--- constructors --------------------------------------------------------- /** @@ -110,7 +107,8 @@ public class GitPermissionFilter extends ProviderPermissionFilter if (GitUtil.isGitClient(request)) { GitSmartHttpTools.sendError(request, response, - HttpServletResponse.SC_FORBIDDEN, MESSAGE_NOT_ENOUGH_PRIVILEGES); + HttpServletResponse.SC_FORBIDDEN, + ClientMessages.get(request).notEnoughPrivileges()); } else { diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java index fb94a50061..afbef65557 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgBasicAuthenticationFilter.java @@ -33,7 +33,6 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- -import com.google.common.io.Closeables; import com.google.inject.Inject; import com.google.inject.Singleton; @@ -44,7 +43,6 @@ import sonia.scm.web.filter.BasicAuthenticationFilter; //~--- JDK imports ------------------------------------------------------------ import java.io.IOException; -import java.io.PrintWriter; import java.util.Set; diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/ScmSvnErrorCode.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/ScmSvnErrorCode.java index 58df07c7de..27d8523517 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/ScmSvnErrorCode.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/ScmSvnErrorCode.java @@ -39,18 +39,9 @@ import org.tmatesoft.svn.core.SVNErrorCode; * * @author Sebastian Sdorra */ -public class ScmSvnErrorCode extends SVNErrorCode +public final class ScmSvnErrorCode extends SVNErrorCode { - /** Field description */ - public static final SVNErrorCode AUTHN_FAILED = - new ScmSvnErrorCode(AUTHN_CATEGORY, 4, "Authentication failed"); - - /** Field description */ - public static final SVNErrorCode AUTHZ_NOT_ENOUGH_PRIVILEGES = - new ScmSvnErrorCode(AUTHZ_CATEGORY, 4, - "You do not have enough access privileges for this operation."); - /** Field description */ private static final long serialVersionUID = -6864996390796610410L; @@ -68,4 +59,19 @@ public class ScmSvnErrorCode extends SVNErrorCode { super(category, index, description); } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param description + * + * @return + */ + public static ScmSvnErrorCode authzNotEnoughPrivileges(String description) + { + return new ScmSvnErrorCode(AUTHZ_CATEGORY, 4, description); + } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java index 383d081ff5..b94b6b5d56 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnBasicAuthenticationFilter.java @@ -36,11 +36,9 @@ package sonia.scm.web; import com.google.inject.Inject; import com.google.inject.Singleton; -import org.tmatesoft.svn.core.SVNErrorCode; - import sonia.scm.config.ScmConfiguration; -import sonia.scm.repository.ScmSvnErrorCode; import sonia.scm.repository.SvnUtil; +import sonia.scm.util.HttpUtil; import sonia.scm.web.filter.AutoLoginModule; import sonia.scm.web.filter.BasicAuthenticationFilter; @@ -52,7 +50,6 @@ import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import sonia.scm.util.HttpUtil; /** * diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java index 2d41e5d8ae..bcaf854118 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java @@ -39,8 +39,7 @@ import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import com.google.inject.Singleton; -import org.tmatesoft.svn.core.SVNErrorCode; - +import sonia.scm.ClientMessages; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.ScmSvnErrorCode; @@ -102,8 +101,16 @@ public class SvnPermissionFilter extends ProviderPermissionFilter { if (SvnUtil.isSvnClient(request)) { - SvnUtil.sendError(request, response, HttpServletResponse.SC_FORBIDDEN, - ScmSvnErrorCode.AUTHZ_NOT_ENOUGH_PRIVILEGES); + //J- + SvnUtil.sendError( + request, + response, + HttpServletResponse.SC_FORBIDDEN, + ScmSvnErrorCode.authzNotEnoughPrivileges( + ClientMessages.get(request).notEnoughPrivileges() + ) + ); + //J+ } else { From d0c94963eeadc87233737f9d855a978bd6e36ae9 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 16 Mar 2014 11:45:43 +0100 Subject: [PATCH 42/46] added userAgentStartsWith method to HttpUtil --- .../main/java/sonia/scm/util/HttpUtil.java | 24 +++++++++++++++++++ .../java/sonia/scm/util/HttpUtilTest.java | 17 +++++++++++++ 2 files changed, 41 insertions(+) diff --git a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java index c8717c1cb7..244ac98719 100644 --- a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java @@ -53,6 +53,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; +import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -79,6 +80,9 @@ public final class HttpUtil */ public static final String HEADER_SCM_CLIENT = "X-SCM-Client"; + /** Field description */ + public static final String HEADER_USERAGENT = "User-Agent"; + /** authentication header */ public static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; @@ -522,6 +526,26 @@ public final class HttpUtil STATUS_UNAUTHORIZED_MESSAGE); } + /** + * Returns true if the User-Agent header of the current request starts with + * the given string. + * + * + * @param request http request + * @param userAgent string to test against the header + * + * @return true if the header starts with the given string + * + * @since 1.37 + */ + public static boolean userAgentStartsWith(HttpServletRequest request, + String userAgent) + { + return Strings.nullToEmpty(request.getHeader(HEADER_USERAGENT)).toLowerCase( + Locale.ENGLISH).startsWith( + Strings.nullToEmpty(userAgent).toLowerCase(Locale.ENGLISH)); + } + //~--- get methods ---------------------------------------------------------- /** diff --git a/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java b/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java index 4f88616662..585bc0e005 100644 --- a/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java +++ b/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java @@ -184,6 +184,23 @@ public class HttpUtilTest } + /** + * Method description + * + */ + @Test + public void userAgentStartsWithTest() + { + HttpServletRequest request = mock(HttpServletRequest.class); + + when(request.getHeader(HttpUtil.HEADER_USERAGENT)).thenReturn( + "git/1.7.10.5997.gaa4aa"); + assertTrue(HttpUtil.userAgentStartsWith(request, "git/")); + assertTrue(HttpUtil.userAgentStartsWith(request, "GIT/")); + assertFalse(HttpUtil.userAgentStartsWith(request, "git/a")); + assertFalse(HttpUtil.userAgentStartsWith(request, "sobbo/")); + } + //~--- get methods ---------------------------------------------------------- /** From 5c44df3e4c5b171e9f5c707e4f0473eb2aac21e8 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 16 Mar 2014 11:49:44 +0100 Subject: [PATCH 43/46] use userAgentStartsWith method for user agent check --- .../src/main/java/sonia/scm/repository/GitUtil.java | 7 ++----- .../src/main/java/sonia/scm/web/HgUtil.java | 9 ++------- .../src/main/java/sonia/scm/repository/SvnUtil.java | 7 +------ 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index 29ebf9d6e7..8bd530d5e9 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -60,6 +60,7 @@ import org.eclipse.jgit.util.FS; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ @@ -98,9 +99,6 @@ public final class GitUtil /** Field description */ private static final String DIRECTORY_REFS = "refs"; - /** Field description */ - private static final String HEADER_USERAGENT = "User-Agent"; - /** Field description */ private static final String PREFIX_HEADS = "refs/heads/"; @@ -672,8 +670,7 @@ public final class GitUtil */ public static boolean isGitClient(HttpServletRequest request) { - return Strings.nullToEmpty(request.getHeader(HEADER_USERAGENT)).toLowerCase( - Locale.ENGLISH).startsWith(USERAGENT_GIT); + return HttpUtil.userAgentStartsWith(request, USERAGENT_GIT); } /** diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgUtil.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgUtil.java index 2db7c12d40..ec35762de7 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgUtil.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgUtil.java @@ -50,6 +50,7 @@ import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgPythonScript; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.spi.javahg.HgFileviewExtension; +import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ @@ -58,8 +59,6 @@ import java.io.File; import java.nio.charset.Charset; -import java.util.Locale; - import javax.servlet.http.HttpServletRequest; /** @@ -72,9 +71,6 @@ public final class HgUtil /** Field description */ public static final String REVISION_TIP = "tip"; - /** Field description */ - private static final String HEADER_USERAGENT = "User-Agent"; - /** Field description */ private static final String USERAGENT_HG = "mercurial/"; @@ -201,7 +197,6 @@ public final class HgUtil */ public static boolean isHgClient(HttpServletRequest request) { - return Strings.nullToEmpty(request.getHeader(HEADER_USERAGENT)).toLowerCase( - Locale.ENGLISH).startsWith(USERAGENT_HG); + return HttpUtil.userAgentStartsWith(request, USERAGENT_HG); } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java index 60521ccbd1..6cc5eb5da9 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java @@ -62,7 +62,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.List; -import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; @@ -78,9 +77,6 @@ public final class SvnUtil /** Field description */ public static final String XML_CONTENT_TYPE = "text/xml; charset=\"utf-8\""; - /** Field description */ - private static final String HEADER_USERAGENT = "User-Agent"; - /** Field description */ private static final String ID_TRANSACTION_PREFIX = "-1:"; @@ -410,8 +406,7 @@ public final class SvnUtil */ public static boolean isSvnClient(HttpServletRequest request) { - return Strings.nullToEmpty(request.getHeader(HEADER_USERAGENT)).toLowerCase( - Locale.ENGLISH).startsWith(USERAGENT_SVN); + return HttpUtil.userAgentStartsWith(request, USERAGENT_SVN); } /** From 61f186129f49cfafb0b462a8f66618fcc7615570 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 16 Mar 2014 11:52:18 +0100 Subject: [PATCH 44/46] close branch issue-549 From 7d69937157600820cfeb0be9fe8e33fa49361cfe Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 16 Mar 2014 15:30:41 +0100 Subject: [PATCH 45/46] update commons-code to version 1.9 --- scm-webapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index f6f21431d6..d04ffa5d01 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -181,7 +181,7 @@ commons-codec commons-codec - 1.8 + 1.9 From 7aa08f0f463643ad56db118625abe57daf895c5b Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 16 Mar 2014 15:45:54 +0100 Subject: [PATCH 46/46] fix typo --- .../src/main/resources/sonia/resources/i18n.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties index a094e88efc..d5c707f090 100644 --- a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties +++ b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties @@ -57,7 +57,7 @@ optionPermissionName = Group or user name optionPermissionType = Permission type (READ,WRITE or OWNER) optionUserName = Username -optionUserDisplayName = "Diesplay name +optionUserDisplayName = Display name optionUserMail = E-Mail address optionUserPassword = Password optionUserType = Type