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 aa63b76e6c..8ae14ddd69 100644 --- a/scm-core/src/main/java/sonia/scm/search/SearchUtil.java +++ b/scm-core/src/main/java/sonia/scm/search/SearchUtil.java @@ -68,7 +68,7 @@ public class SearchUtil { for (String o : other) { - if (!o.matches(query)) + if ((o == null) ||!o.matches(query)) { result = false; @@ -103,7 +103,7 @@ public class SearchUtil { for (String o : other) { - if (o.matches(query)) + if ((o != null) && o.matches(query)) { result = true; diff --git a/scm-core/src/main/java/sonia/scm/user/UserManager.java b/scm-core/src/main/java/sonia/scm/user/UserManager.java index fe6c55067a..55d054729a 100644 --- a/scm-core/src/main/java/sonia/scm/user/UserManager.java +++ b/scm-core/src/main/java/sonia/scm/user/UserManager.java @@ -37,13 +37,15 @@ package sonia.scm.user; import sonia.scm.ListenerSupport; import sonia.scm.Manager; +import sonia.scm.search.Searchable; /** * * @author Sebastian Sdorra */ public interface UserManager - extends Manager, ListenerSupport + extends Manager, Searchable, + ListenerSupport { /** diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index c35cee3cde..317c673bae 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -95,6 +95,12 @@ ${ehcache.version} + + com.google.collections + google-collections + 1.0 + + diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/SearchResult.java b/scm-webapp/src/main/java/sonia/scm/api/rest/SearchResult.java new file mode 100644 index 0000000000..b26fdee547 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/SearchResult.java @@ -0,0 +1,117 @@ +/** + * 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.api.rest; + +/** + * + * @author Sebastian Sdorra + */ +public class SearchResult +{ + + /** + * Constructs ... + * + */ + public SearchResult() {} + + /** + * Constructs ... + * + * + * @param value + * @param label + */ + public SearchResult(String value, String label) + { + this.value = value; + this.label = label; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getLabel() + { + return label; + } + + /** + * Method description + * + * + * @return + */ + public String getValue() + { + return value; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param label + */ + public void setLabel(String label) + { + this.label = label; + } + + /** + * Method description + * + * + * @param value + */ + public void setValue(String value) + { + this.value = value; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String label; + + /** Field description */ + private String value; +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/SearchResults.java b/scm-webapp/src/main/java/sonia/scm/api/rest/SearchResults.java new file mode 100644 index 0000000000..4a6e1dfa68 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/SearchResults.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.api.rest; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Collection; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Sebastian Sdorra + */ +@XmlRootElement(name = "search-results") +public class SearchResults extends RestActionResult +{ + + /** + * Constructs ... + * + */ + public SearchResults() {} + + /** + * Constructs ... + * + * + * @param success + */ + public SearchResults(boolean success) + { + super(success); + } + + /** + * Constructs ... + * + * + * @param results + */ + public SearchResults(Collection results) + { + super(true); + this.results = results; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public Collection getResults() + { + return results; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param results + */ + public void setResults(Collection results) + { + this.results = results; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Collection results; +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SearchResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SearchResource.java new file mode 100644 index 0000000000..b8cdc5ad48 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SearchResource.java @@ -0,0 +1,142 @@ +/** + * 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.api.rest.resources; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.base.Function; +import com.google.common.collect.Collections2; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; + +import sonia.scm.api.rest.SearchResult; +import sonia.scm.api.rest.SearchResults; +import sonia.scm.search.SearchRequest; +import sonia.scm.user.User; +import sonia.scm.user.UserManager; +import sonia.scm.util.SecurityUtil; +import sonia.scm.util.Util; +import sonia.scm.web.security.WebSecurityContext; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Collection; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response.Status; + +/** + * + * @author Sebastian Sdorra + */ +@Singleton +@Path("search") +public class SearchResource +{ + + /** + * Constructs ... + * + * + * @param securityContextProvider + * @param userManager + */ + @Inject + public SearchResource(Provider securityContextProvider, + UserManager userManager) + { + this.securityContextProvider = securityContextProvider; + this.userManager = userManager; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param queryString + * + * @return + */ + @GET + @Path("users") + public SearchResults searchUsers(@QueryParam("query") String queryString) + { + SecurityUtil.assertIsNotAnonymous(securityContextProvider); + + if (Util.isEmpty(queryString)) + { + throw new WebApplicationException(Status.BAD_REQUEST); + } + + SearchRequest request = new SearchRequest(queryString, true); + + request.setMaxResults(5); + + Collection users = userManager.search(request); + SearchResults result = new SearchResults(); + + if (Util.isNotEmpty(users)) + { + Collection resultCollection = Collections2.transform(users, + new Function() + { + @Override + public SearchResult apply(User user) + { + return new SearchResult(user.getName(), user.getDisplayName()); + } + }); + + result.setSuccess(true); + result.setResults(resultCollection); + } + + return result; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Provider securityContextProvider; + + /** Field description */ + private UserManager userManager; +} diff --git a/scm-webapp/src/main/java/sonia/scm/user/xml/XmlUserManager.java b/scm-webapp/src/main/java/sonia/scm/user/xml/XmlUserManager.java index 2ff8301f11..76dbceba06 100644 --- a/scm-webapp/src/main/java/sonia/scm/user/xml/XmlUserManager.java +++ b/scm-webapp/src/main/java/sonia/scm/user/xml/XmlUserManager.java @@ -44,6 +44,8 @@ import org.slf4j.LoggerFactory; import sonia.scm.HandlerEvent; import sonia.scm.SCMContextProvider; +import sonia.scm.search.SearchRequest; +import sonia.scm.search.SearchUtil; import sonia.scm.security.ScmSecurityException; import sonia.scm.store.Store; import sonia.scm.store.StoreFactory; @@ -62,8 +64,11 @@ import sonia.scm.web.security.WebSecurityContext; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; @@ -319,6 +324,47 @@ public class XmlUserManager extends AbstractUserManager fresh.copyProperties(user); } + /** + * Method description + * + * + * @param searchRequest + * + * @return + */ + @Override + public Collection search(final SearchRequest searchRequest) + { + List users = new ArrayList(); + int index = 0; + int counter = 0; + Iterator it = userDB.values().iterator(); + + while (it.hasNext()) + { + User user = it.next(); + + if (SearchUtil.matchesOne(searchRequest, user.getName(), + user.getDisplayName(), user.getMail())) + { + index++; + + if (searchRequest.getStartWith() <= index) + { + users.add(user.clone()); + counter++; + + if (searchRequest.getMaxResults() <= counter) + { + break; + } + } + } + } + + return users; + } + //~--- get methods ---------------------------------------------------------- /**