diff --git a/scm-plugin-backend/pom.xml b/scm-plugin-backend/pom.xml index 018feebe88..9da97a4fa8 100644 --- a/scm-plugin-backend/pom.xml +++ b/scm-plugin-backend/pom.xml @@ -68,6 +68,12 @@ ehcache-core ${ehcache.version} + + + com.thebuzzmedia + imgscalr-lib + 3.2 + @@ -115,4 +121,11 @@ + + + The Buzz Media Maven Repository + http://maven.thebuzzmedia.com + + + diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/PluginUtil.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/PluginUtil.java new file mode 100644 index 0000000000..e4e09c89a3 --- /dev/null +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/PluginUtil.java @@ -0,0 +1,174 @@ +/** + * 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 sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Sebastian Sdorra + */ +public class PluginUtil +{ + + /** + * Method description + * + * + * @param plugins + * + * @return + */ + public static List filterSameVersions( + List plugins) + { + List filteredPlugins = + new ArrayList(); + String version = ""; + + for (PluginInformation plugin : plugins) + { + if (!version.equals(plugin.getVersion())) + { + version = plugin.getVersion(); + filteredPlugins.add(plugin); + } + } + + return filteredPlugins; + } + + /** + * Method description + * + * + * @param allVersions + * + * @return + */ + public static List filterSnapshots( + List allVersions) + { + List filtered = new ArrayList(); + + for (PluginInformation plugin : allVersions) + { + if (!plugin.getVersion().contains("SNAPSHOT")) + { + filtered.add(plugin); + } + } + + return filtered; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param backend + * @param groupId + * @param artifactId + * + * @return + */ + public static List getFilteredPluginVersions( + PluginBackend backend, String groupId, String artifactId) + { + List pluginVersions = + PluginUtil.getPluginVersions(backend, groupId, artifactId); + + if (Util.isNotEmpty(pluginVersions)) + { + Collections.sort(pluginVersions, PluginInformationNameComparator.INSTANCE); + pluginVersions = PluginUtil.filterSameVersions(pluginVersions); + } + + return pluginVersions; + } + + /** + * Method description + * + * + * @param backend + * @param groupId + * @param artifactId + * + * @return + */ + public static PluginInformation getLatestPluginVersion(PluginBackend backend, + String groupId, String artifactId) + { + return getFilteredPluginVersions(backend, groupId, artifactId).get(0); + } + + /** + * Method description + * + * + * + * @param backend + * @param groupId + * @param artifactId + * + * @return + */ + public static List getPluginVersions( + PluginBackend backend, final String groupId, final String artifactId) + { + List pluginVersions = + backend.getPlugins(new PluginFilter() + { + @Override + public boolean accept(PluginInformation plugin) + { + return groupId.equals(plugin.getGroupId()) + && artifactId.equals(plugin.getArtifactId()); + } + }); + + return pluginVersions; + } +} diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/DetailResource.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/DetailResource.java index 85be9c70e7..575d9d1088 100644 --- a/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/DetailResource.java +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/DetailResource.java @@ -38,16 +38,14 @@ package sonia.scm.plugin.rest; import com.google.inject.Inject; import sonia.scm.plugin.PluginBackend; -import sonia.scm.plugin.PluginFilter; import sonia.scm.plugin.PluginInformation; +import sonia.scm.plugin.PluginUtil; import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ import com.sun.jersey.api.view.Viewable; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -102,22 +100,19 @@ public class DetailResource extends ViewableResource @DefaultValue("false") @QueryParam("snapshot") boolean snapshot) { - List pluginVersions = getPluginVersions(groupId, - artifactId); - - if (Util.isEmpty(pluginVersions)) + List pluginVersions = PluginUtil.getFilteredPluginVersions( + backend, groupId, artifactId); + + if (Util.isEmpty(pluginVersions)) { throw new WebApplicationException(Status.NOT_FOUND); } - Collections.sort(pluginVersions, PluginInformationComparator.INSTANCE); - pluginVersions = filterSameVersions(pluginVersions); - PluginInformation latest = pluginVersions.get(0); if (!snapshot) { - pluginVersions = filterSnapshots(pluginVersions); + pluginVersions = PluginUtil.filterSnapshots(pluginVersions); } Map vars = createVarMap(latest.getName()); @@ -128,87 +123,6 @@ public class DetailResource extends ViewableResource return new Viewable("/detail", vars); } - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param plugins - * - * @return - */ - private List filterSameVersions( - List plugins) - { - List filteredPlugins = - new ArrayList(); - String version = ""; - - for (PluginInformation plugin : plugins) - { - if (!version.equals(plugin.getVersion())) - { - version = plugin.getVersion(); - filteredPlugins.add(plugin); - } - } - - return filteredPlugins; - } - - /** - * Method description - * - * - * @param allVersions - * - * @return - */ - private List filterSnapshots( - List allVersions) - { - List filtered = new ArrayList(); - - for (PluginInformation plugin : allVersions) - { - if (!plugin.getVersion().contains("SNAPSHOT")) - { - filtered.add(plugin); - } - } - - return filtered; - } - - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @param groupId - * @param artifactId - * - * @return - */ - private List getPluginVersions(final String groupId, - final String artifactId) - { - List pluginVersions = - backend.getPlugins(new PluginFilter() - { - @Override - public boolean accept(PluginInformation plugin) - { - return groupId.equals(plugin.getGroupId()) - && artifactId.equals(plugin.getArtifactId()); - } - }); - - return pluginVersions; - } - //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/ScreenshotResource.java b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/ScreenshotResource.java new file mode 100644 index 0000000000..4b6a02c25d --- /dev/null +++ b/scm-plugin-backend/src/main/java/sonia/scm/plugin/rest/ScreenshotResource.java @@ -0,0 +1,215 @@ +/** + * 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.rest; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Inject; + +import com.thebuzzmedia.imgscalr.Scalr; + +import sonia.scm.plugin.PluginBackend; +import sonia.scm.plugin.PluginInformation; +import sonia.scm.plugin.PluginUtil; +import sonia.scm.util.ChecksumUtil; +import sonia.scm.util.IOUtil; +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; + +import java.io.File; +import java.io.IOException; + +import java.net.URL; + +import java.util.List; + +import javax.imageio.ImageIO; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +/** + * + * @author Sebastian Sdorra + */ +@Path("/screenshot/{groupId}/{artifactId}/{number}/{size}.jpg") +public class ScreenshotResource +{ + + /** Field description */ + public static final String EXTENSION_IMAGE = ".jpg"; + + /** Field description */ + public static final String FORMAT = "jpg"; + + /** Field description */ + public static final String PATH_IMAGE = "images"; + + /** Field description */ + public static final int SIZE_LARGE = 640; + + /** Field description */ + public static final int SIZE_MEDIUM = 320; + + /** Field description */ + public static final int SIZE_SMALL = 200; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param backend + */ + @Inject + public ScreenshotResource(PluginBackend backend) + { + this.backend = backend; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param groupId + * @param artifactId + * @param number + * @param size + * + * @return + * + * @throws IOException + */ + @GET + @Produces("image/jpeg") + public Response getScreenshot(@PathParam("groupId") String groupId, + @PathParam("artifactId") String artifactId, + @PathParam("number") int number, + @PathParam("size") String size) + throws IOException + { + PluginInformation plugin = PluginUtil.getLatestPluginVersion(backend, + groupId, artifactId); + + if (plugin == null) + { + throw new WebApplicationException(Status.NOT_FOUND); + } + + List screenshots = plugin.getScreenshots(); + + if (Util.isEmpty(screenshots)) + { + throw new WebApplicationException(Status.NOT_FOUND); + } + + String screenshot = screenshots.get(number); + + if (Util.isEmpty(screenshot)) + { + throw new WebApplicationException(Status.NOT_FOUND); + } + + String checksum = ChecksumUtil.createChecksum(screenshot); + StringBuilder path = new StringBuilder(PATH_IMAGE); + + path.append(File.separator).append(groupId); + path.append(File.separator).append(artifactId).append(File.separator); + path.append(String.valueOf(number)).append(File.separator); + path.append(size).append(File.separator).append(checksum); + path.append(EXTENSION_IMAGE); + + File file = new File(backend.getBaseDirectory(), path.toString()); + + if (!file.exists()) + { + createThumbnail(file, screenshot, size.toCharArray()[0]); + } + + return Response.ok(file).build(); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param file + * @param screenshot + * @param size + * + * @throws IOException + */ + private void createThumbnail(File file, String screenshot, char size) + throws IOException + { + IOUtil.mkdirs(file.getParentFile()); + + int width = SIZE_SMALL; + + switch (size) + { + case 'l' : + width = SIZE_LARGE; + + break; + + case 'm' : + width = SIZE_MEDIUM; + } + + BufferedImage image = ImageIO.read(new URL(screenshot)); + + image = Scalr.resize(image, Scalr.Method.QUALITY, width); + ImageIO.write(image, FORMAT, file); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private PluginBackend backend; +} diff --git a/scm-plugin-backend/src/main/webapp/detail.html b/scm-plugin-backend/src/main/webapp/detail.html index e8d6a7878f..00ea7db399 100644 --- a/scm-plugin-backend/src/main/webapp/detail.html +++ b/scm-plugin-backend/src/main/webapp/detail.html @@ -45,6 +45,32 @@ +<#if latest.screenshots??> + + <#list latest.screenshots as screenshot> + + <#if latest.screenshots?size == 1> + <#assign size="l"> + <#elseif latest.screenshots?size == 2> + <#assign size="m"> + <#else> + <#assign size="s"> + #if> + + + #list> + + + + + + +#if> + Plugin Versions