[haiku-depot-web] [haiku-depot-web-app] 3 new revisions pushed by haiku.li...@xxxxxxxxx on 2014-02-14 08:43 GMT

  • From: haiku-depot-web-app@xxxxxxxxxxxxxx
  • To: haiku-depot-web@xxxxxxxxxxxxx
  • Date: Fri, 14 Feb 2014 08:43:15 +0000

master moved from 68df28d58697 to 79eb8a4e32f8

3 new revisions:

Revision: 66f6fc428e9c
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Wed Feb 12 10:07:08 2014 UTC
Log:      + various small fixes...
http://code.google.com/p/haiku-depot-web-app/source/detail?r=66f6fc428e9c

Revision: b52dfe053b09
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Wed Feb 12 10:37:01 2014 UTC
Log:      + integration test for the pkg screenshot controller
http://code.google.com/p/haiku-depot-web-app/source/detail?r=b52dfe053b09

Revision: 79eb8a4e32f8
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Fri Feb 14 08:42:33 2014 UTC
Log:      + integration test for the pkg icon controller
http://code.google.com/p/haiku-depot-web-app/source/detail?r=79eb8a4e32f8

==============================================================================
Revision: 66f6fc428e9c
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Wed Feb 12 10:07:08 2014 UTC
Log:      + various small fixes
+ changes to support screenshot api + tests

http://code.google.com/p/haiku-depot-web-app/source/detail?r=66f6fc428e9c

Added:
/haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/GetPkgScreenshotsRequest.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/GetPkgScreenshotsResult.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemovePkgIconRequest.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemovePkgIconResult.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemovePkgScreenshotRequest.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemovePkgScreenshotResult.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/ReorderPkgScreenshotsRequest.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/ReorderPkgScreenshotsResult.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgScreenshotController.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/model/BadPkgScreenshotException.java
 /haikudepotserver-webapp/src/main/webapp/img/favicon.ico
 /haikudepotserver-webapp/src/test/resources/sample-320x240.png
Deleted:
/haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemoveIconRequest.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemoveIconResult.java
Modified:
/haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/PkgApi.java
 /haikudepotserver-docs/src/main/latex/docs/part-api.tex
 /haikudepotserver-parent/pom.xml
 /haikudepotserver-webapp/pom.xml
/haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/Pkg.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/PkgScreenshot.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgIconController.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/model/Permission.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/ImageHelper.java
 /haikudepotserver-webapp/src/main/resources/HaikuDepot.map.xml
 /haikudepotserver-webapp/src/main/resources/spring/servlet-context.xml
 /haikudepotserver-webapp/src/main/webapp/js/app/controller/more.html
/haikudepotserver-webapp/src/main/webapp/js/app/controller/morecontroller.js /haikudepotserver-webapp/src/main/webapp/js/app/controller/runtimeinformation.html /haikudepotserver-webapp/src/main/webapp/js/app/controller/viewpkgcontroller.js /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/PkgApiIT.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/support/IntegrationTestSupportService.java

=======================================
--- /dev/null
+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/GetPkgScreenshotsRequest.java Wed Feb 12 10:07:08 2014 UTC
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.api1.model.pkg;
+
+public class GetPkgScreenshotsRequest {
+
+    public String pkgName;
+
+    public GetPkgScreenshotsRequest() {
+    }
+
+    public GetPkgScreenshotsRequest(String pkgName) {
+        this.pkgName = pkgName;
+    }
+}
=======================================
--- /dev/null
+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/GetPkgScreenshotsResult.java Wed Feb 12 10:07:08 2014 UTC
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.api1.model.pkg;
+
+import java.util.List;
+
+public class GetPkgScreenshotsResult {
+
+    public List<PkgScreenshot> items;
+
+    public static class PkgScreenshot {
+        public String code;
+    }
+
+}
=======================================
--- /dev/null
+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemovePkgIconRequest.java Wed Feb 12 10:07:08 2014 UTC
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.api1.model.pkg;
+
+public class RemovePkgIconRequest {
+
+    /**
+ * <p>This is the name of the package that you wish to reset the icon for.</p>
+     */
+
+    public String name;
+
+    public RemovePkgIconRequest() {
+    }
+
+
+    public RemovePkgIconRequest(String name) {
+
+        if(null==name || 0==name.length()) {
+ throw new IllegalArgumentException("the name must be supplied when removing the icon for a package");
+        }
+
+        this.name = name;
+    }
+}
=======================================
--- /dev/null
+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemovePkgIconResult.java Wed Feb 12 10:07:08 2014 UTC
@@ -0,0 +1,4 @@
+package org.haikuos.haikudepotserver.api1.model.pkg;
+
+public class RemovePkgIconResult {
+}
=======================================
--- /dev/null
+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemovePkgScreenshotRequest.java Wed Feb 12 10:07:08 2014 UTC
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.api1.model.pkg;
+
+public class RemovePkgScreenshotRequest {
+
+    public String code;
+
+    public RemovePkgScreenshotRequest() {
+    }
+
+    public RemovePkgScreenshotRequest(String code) {
+        this.code = code;
+    }
+
+}
=======================================
--- /dev/null
+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemovePkgScreenshotResult.java Wed Feb 12 10:07:08 2014 UTC
@@ -0,0 +1,9 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.api1.model.pkg;
+
+public class RemovePkgScreenshotResult {
+}
=======================================
--- /dev/null
+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/ReorderPkgScreenshotsRequest.java Wed Feb 12 10:07:08 2014 UTC
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.api1.model.pkg;
+
+import java.util.List;
+
+public class ReorderPkgScreenshotsRequest {
+
+    public String pkgName;
+
+    /**
+ * <p>This is an ordered list of codes that describe the ordering desired for the screenshots of this package.</p>
+     */
+
+    public List<String> codes;
+
+    public ReorderPkgScreenshotsRequest() {
+    }
+
+ public ReorderPkgScreenshotsRequest(String pkgName, List<String> codes) {
+        this.pkgName = pkgName;
+        this.codes = codes;
+    }
+
+}
=======================================
--- /dev/null
+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/ReorderPkgScreenshotsResult.java Wed Feb 12 10:07:08 2014 UTC
@@ -0,0 +1,9 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.api1.model.pkg;
+
+public class ReorderPkgScreenshotsResult {
+}
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgScreenshotController.java Wed Feb 12 10:07:08 2014 UTC
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.pkg.controller;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import com.google.common.net.HttpHeaders;
+import com.google.common.net.MediaType;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.haikuos.haikudepotserver.dataobjects.Pkg;
+import org.haikuos.haikudepotserver.dataobjects.PkgScreenshot;
+import org.haikuos.haikudepotserver.dataobjects.User;
+import org.haikuos.haikudepotserver.pkg.PkgService;
+import org.haikuos.haikudepotserver.pkg.model.BadPkgScreenshotException;
+import org.haikuos.haikudepotserver.security.AuthorizationService;
+import org.haikuos.haikudepotserver.security.model.Permission;
+import org.haikuos.haikudepotserver.support.ByteCounterOutputStream;
+import org.haikuos.haikudepotserver.support.NoOpOutputStream;
+import org.haikuos.haikudepotserver.support.web.AbstractController;
+import org.haikuos.haikudepotserver.web.controller.WebResourceGroupController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Controller
+@RequestMapping("/pkgscreenshot")
+public class PkgScreenshotController extends AbstractController {
+
+ protected static Logger logger = LoggerFactory.getLogger(WebResourceGroupController.class);
+
+ public final static String HEADER_SCREENSHOTCODE = "X-HaikuDepotServer-ScreenshotCode";
+
+    public final static String KEY_PKGNAME = "pkgname";
+    public final static String KEY_SCREENSHOTCODE = "code";
+    public final static String KEY_FORMAT = "format";
+    public final static String KEY_TARGETWIDTH = "tw";
+    public final static String KEY_TARGETHEIGHT = "th";
+
+    protected static int SCREENSHOT_SIDE_LIMIT = 1500;
+
+    @Resource
+    ServerRuntime serverRuntime;
+
+    @Resource
+    PkgService pkgService;
+
+    @Resource
+    AuthorizationService authorizationService;
+
+ @RequestMapping(value = "/{"+KEY_SCREENSHOTCODE+"}.{"+KEY_FORMAT+"}", method = RequestMethod.HEAD)
+    public void fetchHead(
+            HttpServletRequest request,
+            HttpServletResponse response,
+            @RequestParam(value = KEY_TARGETWIDTH) Integer targetWidth,
+            @RequestParam(value = KEY_TARGETHEIGHT) Integer targetHeight,
+            @PathVariable(value = KEY_FORMAT) String format,
+ @PathVariable(value = KEY_SCREENSHOTCODE) String screenshotCode)
+            throws IOException {
+
+ if(null!=targetWidth && (targetWidth <= 0 || targetWidth > SCREENSHOT_SIDE_LIMIT)) {
+            throw new BadSize();
+        }
+
+ if(null!=targetHeight && (targetHeight <= 0 || targetHeight > SCREENSHOT_SIDE_LIMIT)) {
+            throw new BadSize();
+        }
+
+        if(null==targetHeight) {
+            targetHeight = SCREENSHOT_SIDE_LIMIT * 2;
+        }
+
+        if(null==targetWidth) {
+            targetWidth = SCREENSHOT_SIDE_LIMIT * 2;
+        }
+
+        if(Strings.isNullOrEmpty(screenshotCode)) {
+            throw new MissingScreenshotCode();
+        }
+
+        if(Strings.isNullOrEmpty(format) || !"png".equals(format)) {
+            throw new MissingOrBadFormat();
+        }
+
+        ObjectContext context = serverRuntime.getContext();
+ Optional<PkgScreenshot> screenshotOptional = PkgScreenshot.getByCode(context, screenshotCode);
+
+        if(!screenshotOptional.isPresent()) {
+            throw new ScreenshotNotFound();
+        }
+
+ ByteCounterOutputStream byteCounter = new ByteCounterOutputStream(new NoOpOutputStream());
+
+        pkgService.writePkgScreenshotImage(
+                byteCounter,
+                context,
+                screenshotOptional.get(),
+                targetWidth,
+                targetHeight);
+
+ response.setHeader(HttpHeaders.CONTENT_LENGTH, Long.toString(byteCounter.getCounter()));
+        response.setContentType(MediaType.PNG.toString());
+        response.setDateHeader(
+                HttpHeaders.LAST_MODIFIED,
+ screenshotOptional.get().getPkg().getModifyTimestampSecondAccuracy().getTime());
+
+    }
+
+ @RequestMapping(value = "/{"+KEY_SCREENSHOTCODE+"}.{"+KEY_FORMAT+"}", method = RequestMethod.GET)
+    public void fetchGet(
+            HttpServletRequest request,
+            HttpServletResponse response,
+ @RequestParam(value = KEY_TARGETWIDTH, required = true) int targetWidth, + @RequestParam(value = KEY_TARGETHEIGHT, required = true) int targetHeight,
+            @PathVariable(value = KEY_FORMAT) String format,
+ @PathVariable(value = KEY_SCREENSHOTCODE) String screenshotCode)
+            throws IOException {
+
+        if(targetWidth <= 0 || targetWidth > SCREENSHOT_SIDE_LIMIT) {
+            throw new BadSize();
+        }
+
+        if(targetHeight <= 0 || targetHeight > SCREENSHOT_SIDE_LIMIT) {
+            throw new BadSize();
+        }
+
+        if(Strings.isNullOrEmpty(screenshotCode)) {
+            throw new MissingScreenshotCode();
+        }
+
+        if(Strings.isNullOrEmpty(format) || !"png".equals(format)) {
+            throw new MissingOrBadFormat();
+        }
+
+        ObjectContext context = serverRuntime.getContext();
+ Optional<PkgScreenshot> screenshotOptional = PkgScreenshot.getByCode(context, screenshotCode);
+
+        if(!screenshotOptional.isPresent()) {
+            throw new ScreenshotNotFound();
+        }
+
+ ByteCounterOutputStream byteCounter = new ByteCounterOutputStream(new NoOpOutputStream());
+
+ response.setHeader(HttpHeaders.CONTENT_LENGTH, Long.toString(byteCounter.getCounter()));
+        response.setContentType(MediaType.PNG.toString());
+        response.setDateHeader(
+                HttpHeaders.LAST_MODIFIED,
+ screenshotOptional.get().getPkg().getModifyTimestampSecondAccuracy().getTime());
+
+        pkgService.writePkgScreenshotImage(
+                response.getOutputStream(),
+                context,
+                screenshotOptional.get(),
+                targetWidth,
+                targetHeight);
+    }
+
+    /**
+ * <p>This handler will take-up an HTTP PUT that provides a new screenshot for the package.</p>
+     */
+
+ @RequestMapping(value = "/{"+KEY_PKGNAME+"}.{"+KEY_FORMAT+"}", method = RequestMethod.PUT)
+    public void put(
+            HttpServletRequest request,
+            HttpServletResponse response,
+            @PathVariable(value = KEY_FORMAT) String format,
+ @PathVariable(value = KEY_PKGNAME) String pkgName) throws IOException {
+
+ if(Strings.isNullOrEmpty(pkgName) | | !Pkg.NAME_PATTERN.matcher(pkgName).matches()) {
+            throw new MissingPkgName();
+        }
+
+        if(Strings.isNullOrEmpty(format) || !"png".equals(format)) {
+            throw new MissingOrBadFormat();
+        }
+
+        ObjectContext context = serverRuntime.getContext();
+
+        Optional<Pkg> pkg = Pkg.getByName(context, pkgName);
+
+        if(!pkg.isPresent()) {
+            throw new PkgNotFound();
+        }
+
+        // check the authorization
+
+        Optional<User> user = tryObtainAuthenticatedUser(context);
+
+ if(!authorizationService.check(context, user.orNull(), pkg.get(), Permission.PKG_EDITSCREENSHOT)) { + logger.warn("attempt to add a pkg screenshot, but there is no user present or that user is not able to edit the pkg");
+            throw new PkgAuthorizationFailure();
+        }
+
+        String screenshotCode;
+
+        try {
+            screenshotCode = pkgService.storePkgScreenshotImage(
+                    request.getInputStream(),
+                    context,
+                    pkg.get()).getCode();
+        }
+        catch(BadPkgScreenshotException badIcon) {
+            throw new MissingOrBadFormat();
+        }
+
+        context.commitChanges();
+
+        response.setHeader(HEADER_SCREENSHOTCODE,screenshotCode);
+        response.setStatus(HttpServletResponse.SC_OK);
+    }
+
+ // these are the various errors that can arise in supplying or providing a package icon.
+
+ @ResponseStatus(value= HttpStatus.UNSUPPORTED_MEDIA_TYPE, reason="the target width or height must be greater than zero and less than the maximum")
+    public class BadSize extends RuntimeException {}
+
+ @ResponseStatus(value= HttpStatus.BAD_REQUEST, reason="the package name must be supplied")
+    public class MissingPkgName extends RuntimeException {}
+
+ @ResponseStatus(value= HttpStatus.BAD_REQUEST, reason="the screenshot code must be supplied")
+    public class MissingScreenshotCode extends RuntimeException {}
+
+ @ResponseStatus(value= HttpStatus.UNSUPPORTED_MEDIA_TYPE, reason="the format must be supplied and must (presently) be 'png'")
+    public class MissingOrBadFormat extends RuntimeException {}
+
+ @ResponseStatus(value= HttpStatus.NOT_FOUND, reason="the requested package was unable to found")
+    public class PkgNotFound extends RuntimeException {}
+
+ @ResponseStatus(value= HttpStatus.NOT_FOUND, reason="the requested screenshot was unable to found")
+    public class ScreenshotNotFound extends RuntimeException {}
+
+ @ResponseStatus(value= HttpStatus.UNAUTHORIZED, reason="the requested package cannot be edited by the authenticated user")
+    public class PkgAuthorizationFailure extends RuntimeException {}
+
+}
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/model/BadPkgScreenshotException.java Wed Feb 12 10:07:08 2014 UTC
@@ -0,0 +1,9 @@
+/*
+ * Copyright 2013, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.pkg.model;
+
+public class BadPkgScreenshotException extends Exception {
+}
=======================================
--- /dev/null   
+++ /haikudepotserver-webapp/src/main/webapp/img/favicon.ico Wed Feb 12 10:07:08 2014 UTC
Binary file, no diff available.
=======================================
--- /dev/null   
+++ /haikudepotserver-webapp/src/test/resources/sample-320x240.png Wed Feb 12 10:07:08 2014 UTC
Binary file, no diff available.
=======================================
--- /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemoveIconRequest.java Sat Jan 18 09:59:17 2014 UTC
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2014, Andrew Lindesay
- * Distributed under the terms of the MIT License.
- */
-
-package org.haikuos.haikudepotserver.api1.model.pkg;
-
-public class RemoveIconRequest {
-
-    /**
- * <p>This is the name of the package that you wish to reset the icon for.</p>
-     */
-
-    public String name;
-
-    public RemoveIconRequest() {
-    }
-
-
-    public RemoveIconRequest(String name) {
-
-        if(null==name || 0==name.length()) {
- throw new IllegalArgumentException("the name must be supplied when removing the icon for a package");
-        }
-
-        this.name = name;
-    }
-}
=======================================
--- /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/RemoveIconResult.java Thu Dec 5 09:23:22 2013 UTC
+++ /dev/null
@@ -1,4 +0,0 @@
-package org.haikuos.haikudepotserver.api1.model.pkg;
-
-public class RemoveIconResult {
-}
=======================================
--- /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/PkgApi.java Thu Dec 5 09:23:22 2013 UTC +++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/PkgApi.java Wed Feb 12 10:07:08 2014 UTC
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013, Andrew Lindesay
+ * Copyright 2013-2014, Andrew Lindesay
  * Distributed under the terms of the MIT License.
  */

@@ -34,6 +34,31 @@
      * <p>This request will remove any icons from the package.</p>
      */

- RemoveIconResult removeIcon(RemoveIconRequest request) throws ObjectNotFoundException; + RemovePkgIconResult removePkgIcon(RemovePkgIconRequest request) throws ObjectNotFoundException;
+
+    /**
+ * <p>This method will return an ordered list of the screenshots that are available for this package. It will + * throw an {@link org.haikuos.haikudepotserver.api1.support.ObjectNotFoundException} in the case where the
+     * nominated package is not able to be found.</p>
+     */
+
+ GetPkgScreenshotsResult getPkgScreenshots(GetPkgScreenshotsRequest getPkgScreenshotsRequest) throws ObjectNotFoundException;
+
+    /**
+ * <p>This method will remove the nominated screenshot from the package. If the screenshot is not able to be
+     * found using the code supplied, the method will throw an instance of
+ * {@link org.haikuos.haikudepotserver.api1.support.ObjectNotFoundException}.</p>
+     */
+
+ RemovePkgScreenshotResult removePkgScreenshot(RemovePkgScreenshotRequest removePkgScreenshotRequest) throws ObjectNotFoundException;
+
+    /**
+ * <p>This method will reorder the screenshots related to the nominated package. If any of the screenshots are + * not accounted for, they will be ordered at the end in an indeterminate manner. If the package is not able to be
+     * found given the name supplied, an instance of
+ * {@link org.haikuos.haikudepotserver.api1.support.ObjectNotFoundException} will be thrown.</p>
+     */
+
+ ReorderPkgScreenshotsResult reorderPkgScreenshots(ReorderPkgScreenshotsRequest reorderPkgScreenshotsRequest) throws ObjectNotFoundException;

 }
=======================================
--- /haikudepotserver-docs/src/main/latex/docs/part-api.tex Sun Feb 9 10:38:52 2014 UTC +++ /haikudepotserver-docs/src/main/latex/docs/part-api.tex Wed Feb 12 10:07:08 2014 UTC
@@ -166,7 +166,7 @@
   \end{itemize}
 \item Expected HTTP Status Codes
   \begin{itemize}
-  \item {\bf 200} : The icon is provided in the response
+  \item {\bf 200} : The icon is provided in the response (for GET)
   \item {\bf 415} : The path did not include ".png" or the size is invalid
   \item {\bf 400} : The package name was not supplied
   \item {\bf 404} : The package was not found
@@ -200,6 +200,57 @@
 An example URL is;

 \framebox{\tt http://localhost:8080/pkgicon/apr.png?size=32}
+
+\subsubsection{Get Screenshot Image}
+
+This API is able to produce an image for a screenshot that can be identified by its code. The request will return a {\tt Last-Modified} header. The timestamps here will correlate to the {\it modifyTimestamp} that is provided in API responses such as {\tt GetPkResult} and {\tt SearchPkgsResult}. The value for {\it modifyTimestamp} will be at millisecond resolution, but the HTTP headers will be at second resolution. Requests for screenshot image should be accompanied by a target width and height. These values must be within a range of 1..1500. The image will maintain its aspect ratio as it is scaled.
+
+\begin{itemize}
+\item HTTP Method : GET, HEAD
+\item Path : /pkgscreenshot/$<$screenshotcode$>$.png
+\item Response Content-Type : image/png
+\item Query Parameters
+  \begin{itemize}
+ \item {\bf tw} : An integer that describes the width that the image should be scaled to + \item {\bf th} : An integer that describes the height that the image should be scaled to
+  \end{itemize}
+\item Expected HTTP Status Codes
+  \begin{itemize}
+  \item {\bf 200} : The icon is provided in the response (for GET)
+ \item {\bf 415} : The path did not include ".png" or the target width or height is invalid
+  \item {\bf 400} : The screenshot code was not supplied
+  \item {\bf 404} : The screenshot was not found
+  \end{itemize}
+\end{itemize}
+
+An example URL is;
+
+\framebox{\tt http://localhost:8080/pkgscreenshot/a78hw20fh2p20fh122jd92.png?tw=640\&th=480}
+
+\subsubsection{Put Screenshot Image}
+
+This API is able to store an image for a screenshot for the nominated package. The screenshot will be ordered last. The payload of the PUT must be a PNG image.
+
+\begin{itemize}
+\item HTTP Method : PUT
+\item Path : /pkgscreenshot/$<$pkgname$>$.png
+\item Expected HTTP Status Codes
+  \begin{itemize}
+  \item {\bf 200} : The screenshot image was stored
+ \item {\bf 415} : The path did not include ".png" or the size of the image is invalid or the payload is not PNG image data. + \item {\bf 404} : The package identified in the path was not able to be found
+  \item {\bf 400} : The package name was not supplied
+  \end{itemize}
+\item Specific Response Headers
+  \begin{itemize}
+ \item {\bf X-HaikuDepotServer-ScreenshotCode} : Supplies the code of the newly created screenshot.
+  \end{itemize}
+\end{itemize}
+
+An example URL is;
+
+\framebox{\tt http://localhost:8080/pkgscreenshot/apr.png}
+



=======================================
--- /haikudepotserver-parent/pom.xml    Sat Feb  8 09:19:06 2014 UTC
+++ /haikudepotserver-parent/pom.xml    Wed Feb 12 10:07:08 2014 UTC
@@ -91,6 +91,13 @@
                 <version>7.0.39</version>
             </dependency>

+            <!-- MEDIA -->
+            <dependency>
+                <groupId>org.imgscalr</groupId>
+                <artifactId>imgscalr-lib</artifactId>
+                <version>4.2</version>
+            </dependency>
+
             <!-- SPRING -->
             <dependency>
                 <groupId>org.springframework</groupId>
=======================================
--- /haikudepotserver-webapp/pom.xml    Fri Jan 31 10:26:48 2014 UTC
+++ /haikudepotserver-webapp/pom.xml    Wed Feb 12 10:07:08 2014 UTC
@@ -112,6 +112,12 @@
             <artifactId>tomcat-jdbc</artifactId>
         </dependency>

+        <!-- MEDIA -->
+        <dependency>
+            <groupId>org.imgscalr</groupId>
+            <artifactId>imgscalr-lib</artifactId>
+        </dependency>
+
         <!-- SPRING -->
         <dependency>
             <groupId>org.springframework</groupId>
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java Sat Feb 8 09:19:06 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java Wed Feb 12 10:07:08 2014 UTC
@@ -247,7 +247,7 @@
     }

     @Override
- public RemoveIconResult removeIcon(RemoveIconRequest request) throws ObjectNotFoundException { + public RemovePkgIconResult removePkgIcon(RemovePkgIconRequest request) throws ObjectNotFoundException {

         Preconditions.checkNotNull(request);
         Preconditions.checkState(!Strings.isNullOrEmpty(request.name));
@@ -278,7 +278,96 @@

logger.info("did remove icons for pkg {}",pkgOptional.get().getName());

-        return new RemoveIconResult();
+        return new RemovePkgIconResult();
+    }
+
+    @Override
+ public GetPkgScreenshotsResult getPkgScreenshots(GetPkgScreenshotsRequest getPkgScreenshotsRequest) throws ObjectNotFoundException {
+        Preconditions.checkNotNull(getPkgScreenshotsRequest);
+        Preconditions.checkNotNull(getPkgScreenshotsRequest.pkgName);
+
+        final ObjectContext context = serverRuntime.getContext();
+ Optional<Pkg> pkgOptional = Pkg.getByName(context, getPkgScreenshotsRequest.pkgName);
+
+        if(!pkgOptional.isPresent()) {
+ throw new ObjectNotFoundException(Pkg.class.getSimpleName(), getPkgScreenshotsRequest.pkgName);
+        }
+
+        GetPkgScreenshotsResult result = new GetPkgScreenshotsResult();
+        result.items = Lists.transform(
+                pkgOptional.get().getSortedPkgScreenshots(),
+ new Function<PkgScreenshot, GetPkgScreenshotsResult.PkgScreenshot>() {
+                    @Override
+ public GetPkgScreenshotsResult.PkgScreenshot apply(PkgScreenshot pkgScreenshot) { + GetPkgScreenshotsResult.PkgScreenshot rs = new GetPkgScreenshotsResult.PkgScreenshot();
+                        rs.code = pkgScreenshot.getCode();
+                        return rs;
+                    }
+                }
+        );
+
+        return result;
+    }
+
+    @Override
+ public RemovePkgScreenshotResult removePkgScreenshot(RemovePkgScreenshotRequest removePkgScreenshotRequest) throws ObjectNotFoundException {
+        Preconditions.checkNotNull(removePkgScreenshotRequest);
+        Preconditions.checkNotNull(removePkgScreenshotRequest.code);
+
+        final ObjectContext context = serverRuntime.getContext();
+ Optional<PkgScreenshot> screenshotOptional = PkgScreenshot.getByCode(context, removePkgScreenshotRequest.code);
+
+        if(!screenshotOptional.isPresent()) {
+ throw new ObjectNotFoundException(PkgScreenshot.class.getSimpleName(), removePkgScreenshotRequest.code);
+        }
+
+        User authUser = obtainAuthenticatedUser(context);
+        Pkg pkg = screenshotOptional.get().getPkg();
+
+ if(!authorizationService.check(context, authUser, pkg, Permission.PKG_EDITSCREENSHOT)) {
+            throw new AuthorizationFailureException();
+        }
+
+ pkg.removeToManyTarget(Pkg.PKG_SCREENSHOTS_PROPERTY, screenshotOptional.get(), true);
+
+ Optional<PkgScreenshotImage> image = screenshotOptional.get().getPkgScreenshotImage();
+
+        if(image.isPresent()) {
+            context.deleteObjects(image.get());
+        }
+
+        context.deleteObjects(screenshotOptional.get());
+        context.commitChanges();
+
+ logger.info("did remove the screenshot {} on package {}", removePkgScreenshotRequest.code, pkg.getName());
+
+        return new RemovePkgScreenshotResult();
     }

+    @Override
+ public ReorderPkgScreenshotsResult reorderPkgScreenshots(ReorderPkgScreenshotsRequest reorderPkgScreenshotsRequest) throws ObjectNotFoundException {
+        Preconditions.checkNotNull(reorderPkgScreenshotsRequest);
+        Preconditions.checkNotNull(reorderPkgScreenshotsRequest.pkgName);
+        Preconditions.checkNotNull(reorderPkgScreenshotsRequest.codes);
+
+        final ObjectContext context = serverRuntime.getContext();
+ Optional<Pkg> pkgOptional = Pkg.getByName(context, reorderPkgScreenshotsRequest.pkgName);
+
+        if(!pkgOptional.isPresent()) {
+ throw new ObjectNotFoundException(Pkg.class.getSimpleName(), reorderPkgScreenshotsRequest.pkgName);
+        }
+
+        User authUser = obtainAuthenticatedUser(context);
+
+ if(!authorizationService.check(context, authUser, pkgOptional.get(), Permission.PKG_EDITSCREENSHOT)) {
+            throw new AuthorizationFailureException();
+        }
+
+ pkgOptional.get().reorderPkgScreenshots(reorderPkgScreenshotsRequest.codes);
+        context.commitChanges();
+
+ logger.info("did reorder the screenshots on package {}", pkgOptional.get().getName());
+
+        return null;
+    }
 }
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/Pkg.java Sun Feb 9 10:00:28 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/Pkg.java Wed Feb 12 10:07:08 2014 UTC
@@ -7,7 +7,9 @@

 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.query.SelectQuery;
@@ -16,6 +18,8 @@
 import org.haikuos.haikudepotserver.dataobjects.auto._Pkg;
import org.haikuos.haikudepotserver.dataobjects.support.CreateAndModifyTimestamped;

+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Date;
 import java.util.List;
 import java.util.regex.Pattern;
@@ -90,5 +94,68 @@
     public Date getModifyTimestampSecondAccuracy() {
return new java.util.Date((getModifyTimestamp().getTime() / 1000) * 1000);
     }
+
+    public List<PkgScreenshot> getSortedPkgScreenshots() {
+ List<PkgScreenshot> screenshots = Lists.newArrayList(getPkgScreenshots());
+        Collections.sort(screenshots);
+        return screenshots;
+    }
+
+    public Optional<Integer> getHighestPkgScreenshotOrdering() {
+        List<PkgScreenshot> screenshots = getSortedPkgScreenshots();
+
+        if(screenshots.isEmpty()) {
+            return Optional.absent();
+        }
+
+ return Optional.of(screenshots.get(screenshots.size()-1).getOrdering());
+    }
+
+    /**
+ * <p>This method will re-order the screenshots according to the set of codes present in the supplied list. + * If the same code appears twice in the list, an {@link java.lang.IllegalArgumentException} will be + * thrown. Any screenshots that are not mentioned in the list will be indeterminately ordered at the end
+     * of the list.</p>
+     */
+
+    public void reorderPkgScreenshots(final List<String> codes) {
+        Preconditions.checkNotNull(codes);
+
+        // first check that there are no duplicates.
+        if(ImmutableSet.copyOf(codes).size() != codes.size()) {
+ throw new IllegalArgumentException("the codes supplied contain duplicates which would interfere with the ordering");
+        }
+
+ List<PkgScreenshot> screenshots = Lists.newArrayList(getPkgScreenshots());
+        Collections.sort(
+                screenshots,
+                new Comparator<PkgScreenshot>() {
+                    @Override
+ public int compare(PkgScreenshot o1, PkgScreenshot o2) {
+                        int o1i = codes.indexOf(o1.getCode());
+                        int o2i = codes.indexOf(o2.getCode());
+
+                        if(-1==o1i && -1==o2i) {
+                            return o1.getCode().compareTo(o2.getCode());
+                        }
+
+                        if(-1==o1i) {
+                            o1i = Integer.MAX_VALUE;
+                        }
+
+                        if(-1==o2i) {
+                            o2i = Integer.MAX_VALUE;
+                        }
+
+                        return Integer.compare(o1i,o2i);
+                    }
+                }
+        );
+
+        for(int i=0;i<screenshots.size();i++) {
+            PkgScreenshot pkgScreenshot = screenshots.get(i);
+            pkgScreenshot.setOrdering(i+1);
+        }
+    }

 }
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/PkgScreenshot.java Wed Dec 11 08:25:33 2013 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/PkgScreenshot.java Wed Feb 12 10:07:08 2014 UTC
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013, Andrew Lindesay
+ * Copyright 2013-2014, Andrew Lindesay
  * Distributed under the terms of the MIT License.
  */

@@ -16,7 +16,7 @@

 import java.util.List;

-public class PkgScreenshot extends _PkgScreenshot {
+public class PkgScreenshot extends _PkgScreenshot implements Comparable<PkgScreenshot> {

public static Optional<PkgScreenshot> getByCode(ObjectContext context, String code) {
         Preconditions.checkNotNull(context);
@@ -28,4 +28,24 @@
                 null));
     }

+    /**
+ * <p>As there should be only one of these, if there are two then this method will throw an
+     * {@link IllegalStateException}.</p>
+     */
+
+    public Optional<PkgScreenshotImage> getPkgScreenshotImage() {
+        List<PkgScreenshotImage> images = getPkgScreenshotImages();
+
+        switch(images.size()) {
+            case 0: return Optional.absent();
+            case 1: return Optional.of(images.get(0));
+            default:
+ throw new IllegalStateException("more than one pkg icon image found on an icon image");
+        }
+    }
+
+    @Override
+    public int compareTo(PkgScreenshot o) {
+        return getOrdering().compareTo(o.getOrdering());
+    }
 }
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgService.java Sun Feb 2 09:15:35 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgService.java Wed Feb 12 10:07:08 2014 UTC
@@ -20,23 +20,24 @@
 import org.haikuos.haikudepotserver.dataobjects.*;
 import org.haikuos.haikudepotserver.dataobjects.Pkg;
 import org.haikuos.haikudepotserver.dataobjects.PkgUrlType;
-import org.haikuos.haikudepotserver.dataobjects.PkgVersion;
 import org.haikuos.haikudepotserver.pkg.model.BadPkgIconException;
+import org.haikuos.haikudepotserver.pkg.model.BadPkgScreenshotException;
 import org.haikuos.haikudepotserver.pkg.model.PkgSearchSpecification;
 import org.haikuos.haikudepotserver.support.Closeables;
 import org.haikuos.haikudepotserver.support.ImageHelper;
 import org.haikuos.haikudepotserver.support.cayenne.LikeHelper;
-import org.haikuos.pkg.model.*;
+import org.imgscalr.Scalr;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;

-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.UUID;

 /**
  * <p>This service undertakes non-trivial operations on packages.</p>
@@ -47,6 +48,8 @@

protected static Logger logger = LoggerFactory.getLogger(PkgService.class);

+    protected static int SCREENSHOT_SIDE_LIMIT = 1500;
+
     private ImageHelper imageHelper = new ImageHelper();

     // ------------------------------
@@ -278,6 +281,106 @@

logger.info("the icon {}px for package {} has been updated", size.width, pkg.getName());
     }
+
+    // ------------------------------
+    // SCREENSHOT
+
+    /**
+ * <p>This method will write the package's screenshot to the output stream. It will constrain the output to the
+     * size given by scaling the image.  The output is a PNG image.</p>
+     */
+
+    public void writePkgScreenshotImage(
+            OutputStream output,
+            ObjectContext context,
+            PkgScreenshot screenshot,
+            int targetWidth,
+            int targetHeight) throws IOException {
+
+        Preconditions.checkNotNull(output);
+        Preconditions.checkNotNull(context);
+        Preconditions.checkNotNull(screenshot);
+        Preconditions.checkState(targetHeight > 0);
+        Preconditions.checkState(targetWidth > 0);
+
+ Optional<PkgScreenshotImage> pkgScreenshotImageOptional = screenshot.getPkgScreenshotImage();
+
+        if(!pkgScreenshotImageOptional.isPresent()) {
+ throw new IllegalStateException("the screenshot "+screenshot.getCode()+" is missing a screenshot image");
+        }
+
+ if(!pkgScreenshotImageOptional.get().getMediaType().getCode().equals(com.google.common.net.MediaType.PNG.toString())) { + throw new IllegalStateException("the screenshot system only supports png images at the present time");
+        }
+
+        byte[] data = pkgScreenshotImageOptional.get().getData();
+        ImageHelper.Size size = imageHelper.derivePngSize(data);
+
+        // check to see if the screenshot needs to be resized to fit.
+        if(size.width > targetWidth || size.height > targetHeight) {
+ ByteArrayInputStream imageInputStream = new ByteArrayInputStream(data);
+            BufferedImage bufferedImage = ImageIO.read(imageInputStream);
+ BufferedImage scaledBufferedImage = Scalr.resize(bufferedImage, targetWidth, targetHeight);
+            ImageIO.write(scaledBufferedImage, "PNG", output);
+        }
+        else {
+            output.write(data);
+        }
+    }
+
+    /**
+ * <p>This method will write the PNG data supplied in the input to the package as a screenshot. Note that the icon + * must comply with necessary characteristics. If it is not compliant then an images of + * {@link org.haikuos.haikudepotserver.pkg.model.BadPkgScreenshotException} will be thrown.</p>
+     */
+
+    public PkgScreenshot storePkgScreenshotImage(
+            InputStream input,
+            ObjectContext context,
+            Pkg pkg) throws IOException, BadPkgScreenshotException {
+
+        Preconditions.checkNotNull(input);
+        Preconditions.checkNotNull(context);
+        Preconditions.checkNotNull(pkg);
+
+        byte[] pngData = ByteStreams.toByteArray(input);
+        ImageHelper.Size size =  imageHelper.derivePngSize(pngData);
+
+ // check that the file roughly looks like PNG and the size is something
+        // reasonable.
+
+ if(size.height > SCREENSHOT_SIDE_LIMIT || size.width > SCREENSHOT_SIDE_LIMIT) { + logger.warn("attempt to store a screenshot image that is too large; "+size.toString());
+        }
+
+ MediaType png = MediaType.getByCode(context, com.google.common.net.MediaType.PNG.toString()).get();
+
+ // now we need to know the largest ordering so we can add this one at the end of the orderings
+        // such that it is the next one in the list.
+
+        int ordering = 1;
+ Optional<Integer> highestExistingScreenshotOrdering = pkg.getHighestPkgScreenshotOrdering();
+
+        if(highestExistingScreenshotOrdering.isPresent()) {
+ ordering = highestExistingScreenshotOrdering.get().intValue() + 1;
+        }
+
+        PkgScreenshot screenshot = context.newObject(PkgScreenshot.class);
+        screenshot.setCode(UUID.randomUUID().toString());
+        screenshot.setOrdering(new Integer(ordering));
+ pkg.addToManyTarget(Pkg.PKG_SCREENSHOTS_PROPERTY, screenshot, true);
+
+ PkgScreenshotImage screenshotImage = context.newObject(PkgScreenshotImage.class);
+        screenshotImage.setMediaType(png);
+        screenshotImage.setData(pngData);
+ screenshot.addToManyTarget(PkgScreenshot.PKG_SCREENSHOT_IMAGES_PROPERTY, screenshotImage, true);
+
+        pkg.setModifyTimestamp(new java.util.Date());
+
+ logger.info("a screenshot #{} has been added to package {} ({})", ordering, pkg.getName(), screenshot.getCode());
+
+        return screenshot;
+    }

     // ------------------------------
     // IMPORT
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgIconController.java Sat Feb 8 09:19:06 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgIconController.java Wed Feb 12 10:07:08 2014 UTC
@@ -149,7 +149,7 @@
     }

     /**
- * <p>This handler will take-up an HTTP PUT that provides an con image for the package.</p> + * <p>This handler will take-up an HTTP PUT that provides an icon image for the package.</p>
      */

@RequestMapping(value = "/{"+KEY_PKGNAME+"}.{"+KEY_FORMAT+"}", method = RequestMethod.PUT)
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationService.java Sun Feb 9 10:00:28 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationService.java Wed Feb 12 10:07:08 2014 UTC
@@ -149,6 +149,7 @@
return null!=authenticatedUser && authenticatedUser.getIsRoot();

             case PKG_EDITICON:
+            case PKG_EDITSCREENSHOT:
return null!=authenticatedUser && authenticatedUser.getIsRoot();

             default:
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/model/Permission.java Sun Feb 9 10:00:28 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/model/Permission.java Wed Feb 12 10:07:08 2014 UTC
@@ -19,7 +19,8 @@
     USER_CHANGEPASSWORD(TargetType.USER),
     USER_LIST(null),

-    PKG_EDITICON(TargetType.PKG);
+    PKG_EDITICON(TargetType.PKG),
+    PKG_EDITSCREENSHOT(TargetType.PKG);

     private TargetType requiredTargetType;

=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/ImageHelper.java Wed Nov 27 09:58:54 2013 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/ImageHelper.java Wed Feb 12 10:07:08 2014 UTC
@@ -79,6 +79,10 @@
         public boolean areSides(int s) {
             return s==width && s==height;
         }
+
+        public String toString() {
+            return String.format("{%d,%d}",width,height);
+        }
     }

 }
=======================================
--- /haikudepotserver-webapp/src/main/resources/HaikuDepot.map.xml Wed Dec 11 08:25:33 2013 UTC +++ /haikudepotserver-webapp/src/main/resources/HaikuDepot.map.xml Wed Feb 12 10:07:08 2014 UTC
@@ -71,7 +71,7 @@
                </db-key-generator>
        </db-entity>
        <db-entity name="pkg_screenshot_image" schema="haikudepot">
-               <db-attribute name="data" type="BLOB" isMandatory="true"/>
+               <db-attribute name="data" type="VARBINARY" isMandatory="true"/>
<db-attribute name="id" type="BIGINT" isPrimaryKey="true" isMandatory="true"/>
                <db-attribute name="media_type_id" type="BIGINT" 
isMandatory="true"/>
                <db-attribute name="pkg_screenshot_id" type="BIGINT" 
isMandatory="true"/>
=======================================
--- /haikudepotserver-webapp/src/main/resources/spring/servlet-context.xml Sat Feb 1 07:54:02 2014 UTC +++ /haikudepotserver-webapp/src/main/resources/spring/servlet-context.xml Wed Feb 12 10:07:08 2014 UTC
@@ -20,6 +20,7 @@
     <mvc:resources mapping="/js/**" location="/js/" />
     <mvc:resources mapping="/css/**" location="/css/" />
     <mvc:resources mapping="/img/**" location="/img/" />
+    <mvc:resources mapping="favicon.ico" location="/img/favicon.ico" />

     <bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
=======================================
--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/more.html Sat Feb 8 09:19:06 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/more.html Wed Feb 12 10:07:08 2014 UTC
@@ -14,6 +14,9 @@
         <li>
             <a href="" ng-click="goHome()">Home</a>
         </li>
+        <li ng-show="canViewUser()">
+ <a href="" ng-click="goViewUser()">View currently authenticated user</a>
+        </li>
         <li show-if-permission="'REPOSITORY_LIST'">
             <a href="" ng-click="goListRepositories()">Repositories</a>
         </li>
=======================================
--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/morecontroller.js Sun Feb 2 09:15:35 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/morecontroller.js Wed Feb 12 10:07:08 2014 UTC
@@ -25,6 +25,14 @@
             // -------------------
             // USER

+            $scope.canViewUser = function() {
+                return !!userState.user();
+            }
+
+            $scope.goViewUser = function() {
+ $location.path('/viewuser/'+userState.user().nickname).search({});
+            }
+
             function refreshAuthorization() {

                 function disallowAll() {
=======================================
--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/runtimeinformation.html Fri Jan 31 10:26:48 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/runtimeinformation.html Wed Feb 12 10:07:08 2014 UTC
@@ -17,8 +17,6 @@

     <h1>Versions</h1>

-    <p>The application has been running for some time.</p>
-
     <table class="table-general">
         <thead>
         <th>Component</th>
=======================================
--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/viewpkgcontroller.js Sat Feb 8 09:19:06 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/viewpkgcontroller.js Wed Feb 12 10:07:08 2014 UTC
@@ -81,7 +81,7 @@
             $scope.goRemoveIcon = function() {
                 jsonRpc.call(
                         constants.ENDPOINT_API_V1_PKG,
-                        "removeIcon",
+                        "removePkgIcon",
                         [{ name: $routeParams.name }]
                     ).then(
                     function(result) {
=======================================
--- /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/PkgApiIT.java Sat Feb 8 09:19:06 2014 UTC +++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/PkgApiIT.java Wed Feb 12 10:07:08 2014 UTC
@@ -6,6 +6,9 @@
 package org.haikuos.haikudepotsever.api1;

 import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import junit.framework.Assert;
 import org.apache.cayenne.ObjectContext;
 import org.fest.assertions.Assertions;
@@ -13,6 +16,7 @@
 import org.haikuos.haikudepotserver.api1.model.pkg.*;
 import org.haikuos.haikudepotserver.api1.support.ObjectNotFoundException;
 import org.haikuos.haikudepotserver.dataobjects.Pkg;
+import org.haikuos.haikudepotserver.dataobjects.PkgScreenshot;
 import org.haikuos.haikudepotserver.pkg.PkgService;
 import org.haikuos.haikudepotserver.support.Closeables;
 import org.haikuos.haikudepotsever.api1.support.AbstractIntegrationTest;
@@ -21,6 +25,7 @@

 import javax.annotation.Resource;
 import java.io.InputStream;
+import java.util.List;

 public class PkgApiIT extends AbstractIntegrationTest {

@@ -141,7 +146,7 @@
         }

         // ------------------------------------
-        pkgApi.removeIcon(new RemoveIconRequest("pkg1"));
+        pkgApi.removePkgIcon(new RemovePkgIconRequest("pkg1"));
         // ------------------------------------

         {
@@ -151,5 +156,96 @@
         }
     }

+    /**
+ * <p>This test depends on the sample package pkg1 having some screenshots associated with it.</p>
+     */
+
+    @Test
+    public void testGetPkgScreenshots() throws ObjectNotFoundException {
+ IntegrationTestSupportService.StandardTestData data = integrationTestSupportService.createStandardTestData();
+
+        // ------------------------------------
+ GetPkgScreenshotsResult result = pkgApi.getPkgScreenshots(new GetPkgScreenshotsRequest(data.pkg1.getName()));
+        // ------------------------------------
+
+ Assertions.assertThat(result.items.size()).isEqualTo(data.pkg1.getPkgScreenshots().size()); + List<PkgScreenshot> sortedScreenshots = data.pkg1.getSortedPkgScreenshots();
+
+        for(int i=0;i<sortedScreenshots.size();i++) {
+            PkgScreenshot pkgScreenshot = sortedScreenshots.get(i);
+ GetPkgScreenshotsResult.PkgScreenshot apiPkgScreenshot = result.items.get(i); + Assertions.assertThat(pkgScreenshot.getCode()).isEqualTo(apiPkgScreenshot.code);
+        }
+    }
+
+    /**
+ * <p>This test depends on the sample package pkg1 having some screenshots associated with it.</p>
+     */
+
+    @Test
+    public void testRemovePkgScreenshot() throws Exception {
+        setAuthenticatedUserToRoot();
+
+ IntegrationTestSupportService.StandardTestData data = integrationTestSupportService.createStandardTestData(); + List<PkgScreenshot> sortedScreenshotsBefore = data.pkg1.getSortedPkgScreenshots();
+
+        if(sortedScreenshotsBefore.size() < 2) {
+ throw new IllegalStateException("the test cannot run without more than two screenshots");
+        }
+
+        final String code1 = sortedScreenshotsBefore.get(1).getCode();
+
+        // ------------------------------------
+        pkgApi.removePkgScreenshot(new RemovePkgScreenshotRequest(code1));
+        // ------------------------------------
+
+        ObjectContext context = serverRuntime.getContext();
+ Optional<Pkg> pkgOptional = Pkg.getByName(context, data.pkg1.getName()); + List<PkgScreenshot> sortedScreenshotsAfter = data.pkg1.getSortedPkgScreenshots();
+
+ Assertions.assertThat(sortedScreenshotsAfter.size()).isEqualTo(sortedScreenshotsBefore.size()-1);
+
+ Assertions.assertThat(Iterables.tryFind(sortedScreenshotsAfter, new Predicate<PkgScreenshot>() {
+            @Override
+            public boolean apply(PkgScreenshot pkgScreenshot) {
+                return pkgScreenshot.getCode().equals(code1);
+            }
+        }).isPresent()).isFalse();
+    }
+
+    /**
+ * <p>This test assumes that the test data has a pkg1 with three screenshots associated with it.</p>
+     */
+
+    @Test
+    public void testReorderPkgScreenshots() throws Exception {
+        setAuthenticatedUserToRoot();
+
+ IntegrationTestSupportService.StandardTestData data = integrationTestSupportService.createStandardTestData(); + List<PkgScreenshot> sortedScreenshotsBefore = data.pkg1.getSortedPkgScreenshots();
+
+        if(3 != sortedScreenshotsBefore.size()) {
+ throw new IllegalStateException("the test requires that pkg1 has three screenshots associated with it");
+        }
+
+        // ------------------------------------
+        pkgApi.reorderPkgScreenshots(new ReorderPkgScreenshotsRequest(
+                data.pkg1.getName(),
+                ImmutableList.of(
+                        sortedScreenshotsBefore.get(2).getCode(),
+                        sortedScreenshotsBefore.get(0).getCode()
+                )
+        ));
+        // ------------------------------------
+
+        ObjectContext context = serverRuntime.getContext();
+ Optional<Pkg> pkgOptional = Pkg.getByName(context, data.pkg1.getName()); + List<PkgScreenshot> sortedScreenshotsAfter = data.pkg1.getSortedPkgScreenshots();
+
+        Assertions.assertThat(sortedScreenshotsAfter.size()).isEqualTo(3);
+ Assertions.assertThat(sortedScreenshotsAfter.get(0).getCode()).isEqualTo(sortedScreenshotsBefore.get(2).getCode()); + Assertions.assertThat(sortedScreenshotsAfter.get(1).getCode()).isEqualTo(sortedScreenshotsBefore.get(0).getCode()); + Assertions.assertThat(sortedScreenshotsAfter.get(2).getCode()).isEqualTo(sortedScreenshotsBefore.get(1).getCode());
+    }

 }
=======================================
--- /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/support/IntegrationTestSupportService.java Sun Feb 2 09:38:27 2014 UTC +++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/support/IntegrationTestSupportService.java Wed Feb 12 10:07:08 2014 UTC
@@ -8,9 +8,12 @@
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.haikuos.haikudepotserver.dataobjects.*;
+import org.haikuos.haikudepotserver.pkg.PkgService;
+import org.haikuos.haikudepotserver.support.Closeables;
 import org.springframework.stereotype.Service;

 import javax.annotation.Resource;
+import java.io.InputStream;

 /**
* <p>This class is designed to help out with creating some common test data that can be re-used between tests.</p>
@@ -22,6 +25,9 @@
     @Resource
     ServerRuntime serverRuntime;

+    @Resource
+    PkgService pkgService;
+
     private ObjectContext objectContext = null;

     public ObjectContext getObjectContext() {
@@ -31,6 +37,21 @@

         return objectContext;
     }
+
+ private PkgScreenshot addPkgScreenshot(ObjectContext objectContext, Pkg pkg) {
+        InputStream inputStream = null;
+
+        try {
+ inputStream = IntegrationTestSupportService.class.getResourceAsStream("/sample-320x240.png"); + return pkgService.storePkgScreenshotImage(inputStream, objectContext, pkg);
+        }
+        catch(Exception e) {
+ throw new IllegalStateException("an issue has arisen loading a sample screenshot into a test package",e);
+        }
+        finally {
+            Closeables.closeQuietly(inputStream);
+        }
+    }

     public StandardTestData createStandardTestData() {

@@ -49,6 +70,10 @@
         result.pkg1.setActive(true);
         result.pkg1.setName("pkg1");

+        addPkgScreenshot(context,result.pkg1);
+        addPkgScreenshot(context,result.pkg1);
+        addPkgScreenshot(context,result.pkg1);
+
         result.pkg1Version1 = context.newObject(PkgVersion.class);
         result.pkg1Version1.setActive(Boolean.FALSE);
         result.pkg1Version1.setArchitecture(x86);

==============================================================================
Revision: b52dfe053b09
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Wed Feb 12 10:37:01 2014 UTC
Log:      + integration test for the pkg screenshot controller

http://code.google.com/p/haiku-depot-web-app/source/detail?r=b52dfe053b09

Added:
/haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/pkg/controller/PkgScreenshotControllerIT.java

=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/pkg/controller/PkgScreenshotControllerIT.java Wed Feb 12 10:37:01 2014 UTC
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotsever.pkg.controller;
+
+import com.google.common.base.Optional;
+import com.google.common.io.ByteStreams;
+import com.google.common.net.MediaType;
+import org.apache.cayenne.ObjectContext;
+import org.fest.assertions.Assertions;
+import org.haikuos.haikudepotserver.dataobjects.PkgScreenshot;
+import org.haikuos.haikudepotserver.pkg.controller.PkgScreenshotController;
+import org.haikuos.haikudepotserver.support.Closeables;
+import org.haikuos.haikudepotserver.support.ImageHelper;
+import org.haikuos.haikudepotsever.api1.support.AbstractIntegrationTest;
+import org.haikuos.haikudepotsever.api1.support.IntegrationTestSupportService;
+import org.junit.Test;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class PkgScreenshotControllerIT extends AbstractIntegrationTest {
+
+    @Resource
+    PkgScreenshotController pkgScreenshotController;
+
+    @Resource
+    IntegrationTestSupportService integrationTestSupportService;
+
+    /**
+ * <p>This will return an image that can be used as a sample screenshot.</p>
+     */
+
+    private byte[] getScreenshotData() throws IOException {
+        InputStream inputStream = null;
+
+        try {
+ inputStream = this.getClass().getResourceAsStream("/sample-320x240.png");
+            return ByteStreams.toByteArray(inputStream);
+        }
+        finally {
+            Closeables.closeQuietly(inputStream);
+        }
+    }
+
+    @Test
+    public void testPut() throws Exception {
+
+        setAuthenticatedUserToRoot();
+
+ IntegrationTestSupportService.StandardTestData data = integrationTestSupportService.createStandardTestData();
+        byte[] imageData = getScreenshotData();
+
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        MockHttpServletResponse response = new MockHttpServletResponse();
+        request.setContent(imageData);
+
+        // ------------------------------------
+        pkgScreenshotController.put(request, response, "png", "pkg1");
+        // -----------------------------------
+
+        // the header should contain the image code
+ String code = response.getHeader(PkgScreenshotController.HEADER_SCREENSHOTCODE);
+        Assertions.assertThat(code).isNotEmpty();
+
+        ObjectContext context = serverRuntime.getContext();
+ Optional<PkgScreenshot> screenshotOptional = PkgScreenshot.getByCode(context, code);
+        Assertions.assertThat(screenshotOptional.isPresent()).isTrue();
+ Assertions.assertThat(screenshotOptional.get().getPkg().getName()).isEqualTo("pkg1"); + Assertions.assertThat(screenshotOptional.get().getPkgScreenshotImage().get().getData()).isEqualTo(imageData);
+
+    }
+
+    @Test
+    public void testGet_noScaling() throws Exception {
+
+ IntegrationTestSupportService.StandardTestData data = integrationTestSupportService.createStandardTestData();
+        byte[] imageData = getScreenshotData();
+
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        MockHttpServletResponse response = new MockHttpServletResponse();
+
+        // ------------------------------------
+        pkgScreenshotController.fetchGet(
+                request, response,
+                640, 480,
+                "png",
+                data.pkg1.getSortedPkgScreenshots().get(0).getCode());
+        // -----------------------------------
+
+ Assertions.assertThat(response.getContentType()).isEqualTo(MediaType.PNG.toString()); + Assertions.assertThat(response.getContentAsByteArray()).isEqualTo(imageData);
+
+    }
+
+    @Test
+    public void testGet_scaling() throws Exception {
+
+ IntegrationTestSupportService.StandardTestData data = integrationTestSupportService.createStandardTestData();
+        byte[] imageData = getScreenshotData();
+
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        MockHttpServletResponse response = new MockHttpServletResponse();
+
+        // ------------------------------------
+        pkgScreenshotController.fetchGet(
+                request, response,
+                160, 120,
+                "png",
+                data.pkg1.getSortedPkgScreenshots().get(0).getCode());
+        // -----------------------------------
+
+ Assertions.assertThat(response.getContentType()).isEqualTo(MediaType.PNG.toString());
+
+        ImageHelper imageHelper = new ImageHelper();
+ ImageHelper.Size size = imageHelper.derivePngSize(response.getContentAsByteArray());
+        Assertions.assertThat(size.width).isEqualTo(160);
+        Assertions.assertThat(size.height).isEqualTo(120);
+
+    }
+
+}

==============================================================================
Revision: 79eb8a4e32f8
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Fri Feb 14 08:42:33 2014 UTC
Log:      + integration test for the pkg icon controller

http://code.google.com/p/haiku-depot-web-app/source/detail?r=79eb8a4e32f8

Added:
/haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/pkg/controller/PkgIconControllerIT.java
Modified:
/haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgService.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/PkgApiIT.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/support/AbstractIntegrationTest.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/support/IntegrationTestSupportService.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/pkg/controller/PkgScreenshotControllerIT.java

=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/pkg/controller/PkgIconControllerIT.java Fri Feb 14 08:42:33 2014 UTC
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotsever.pkg.controller;
+
+import com.google.common.base.Optional;
+import com.google.common.net.MediaType;
+import org.apache.cayenne.ObjectContext;
+import org.fest.assertions.Assertions;
+import org.haikuos.haikudepotserver.dataobjects.Pkg;
+import org.haikuos.haikudepotserver.pkg.controller.PkgIconController;
+import org.haikuos.haikudepotsever.api1.support.AbstractIntegrationTest;
+import org.haikuos.haikudepotsever.api1.support.IntegrationTestSupportService;
+import org.junit.Test;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+
+public class PkgIconControllerIT extends AbstractIntegrationTest {
+
+    @Resource
+    PkgIconController pkgIconController;
+
+    @Resource
+    IntegrationTestSupportService integrationTestSupportService;
+
+    private byte[] getIconData() throws IOException {
+        return getResourceData("/sample-32x32.png");
+    }
+
+    /**
+ * <p>This test works knowing that the test package pkg1 will have a PNG image pre-loaded for it.</p>
+     */
+
+    @Test
+    public void testGet() throws Exception {
+
+ IntegrationTestSupportService.StandardTestData data = integrationTestSupportService.createStandardTestData();
+        byte[] imageData = getIconData();
+
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        MockHttpServletResponse response = new MockHttpServletResponse();
+
+        // ------------------------------------
+        pkgIconController.fetchGet(
+                request, response,
+                32,
+                "png",
+                "pkg1");
+        // -----------------------------------
+
+ Assertions.assertThat(response.getContentType()).isEqualTo(MediaType.PNG.toString()); + Assertions.assertThat(response.getContentAsByteArray()).isEqualTo(imageData);
+
+    }
+
+    @Test
+    public void testPut() throws Exception {
+
+        setAuthenticatedUserToRoot();
+
+ IntegrationTestSupportService.StandardTestData data = integrationTestSupportService.createStandardTestData();
+        byte[] imageData = getIconData();
+
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        request.setContent(imageData);
+        MockHttpServletResponse response = new MockHttpServletResponse();
+
+        // ------------------------------------
+         pkgIconController.put(
+                 request,response,
+                 32,
+                 "png",
+                 "pkg2");
+        // ------------------------------------
+
+        {
+            ObjectContext context = serverRuntime.getContext();
+            Optional<Pkg> pkgOptional = Pkg.getByName(context,"pkg2");
+ Optional<org.haikuos.haikudepotserver.dataobjects.MediaType> mediaTypeOptional = org.haikuos.haikudepotserver.dataobjects.MediaType.getByCode(context,MediaType.PNG.toString()); + Assertions.assertThat(pkgOptional.get().getPkgIcon(mediaTypeOptional.get(),32).get().getPkgIconImage().get().getData()).isEqualTo(imageData);
+        }
+
+    }
+
+}
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgService.java Wed Feb 12 10:07:08 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgService.java Fri Feb 14 08:42:33 2014 UTC
@@ -223,8 +223,9 @@
         if(pkgIconImageOptional.isPresent()) {
             output.write(pkgIconImageOptional.get().getData());
         }
-
-        writeGenericIconImage(output, size);
+        else {
+            writeGenericIconImage(output, size);
+        }
     }

     /**
=======================================
--- /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/PkgApiIT.java Wed Feb 12 10:07:08 2014 UTC +++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/PkgApiIT.java Fri Feb 14 08:42:33 2014 UTC
@@ -72,7 +72,7 @@
         GetPkgResult result = pkgApi.getPkg(request);
         // ------------------------------------

-        Assertions.assertThat(result.hasIcon).isFalse();
+ Assertions.assertThat(result.hasIcon).isTrue(); // icons are preloaded in the test data
         Assertions.assertThat(result.name).isEqualTo("pkg1");
         Assertions.assertThat(result.versions.size()).isEqualTo(1);
Assertions.assertThat(result.versions.get(0).architectureCode).isEqualTo("x86");
@@ -108,8 +108,7 @@
     }

     /**
- * <p>This test will first of all load an icon in for a package and will then use the API to remove it; checking
-     * that the icon is there before and is not there afterwards.</p>
+ * <p>This test knows that an icon exists for pkg1 and then removes it.</p>
      */

     @Test
@@ -118,31 +117,11 @@
         setAuthenticatedUserToRoot();

IntegrationTestSupportService.StandardTestData data = integrationTestSupportService.createStandardTestData();
-        InputStream sample32InputStream = null;
-
-        try {
- sample32InputStream = getClass().getResourceAsStream("/sample-32x32.png");
-
-            if(null==sample32InputStream) {
- throw new IllegalStateException("unable to find the test input stream for the icon image");
-            }
-
-            pkgService.storePkgIconImage(
-                    sample32InputStream,
-                    32,
-                    integrationTestSupportService.getObjectContext(),
-                    data.pkg1);
-
- integrationTestSupportService.getObjectContext().commitChanges();
-        }
-        finally {
-            Closeables.closeQuietly(sample32InputStream);
-        }

         {
             ObjectContext objectContext = serverRuntime.getContext();
Optional<Pkg> pkgOptionalBefore = Pkg.getByName(objectContext, "pkg1"); - Assertions.assertThat(pkgOptionalBefore.get().getPkgIcons().size()).isEqualTo(1); + Assertions.assertThat(pkgOptionalBefore.get().getPkgIcons().size()).isEqualTo(2); // 16 and 32 px sizes
         }

         // ------------------------------------
=======================================
--- /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/support/AbstractIntegrationTest.java Sat Jan 18 09:59:17 2014 UTC +++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/support/AbstractIntegrationTest.java Fri Feb 14 08:42:33 2014 UTC
@@ -6,6 +6,7 @@
 package org.haikuos.haikudepotsever.api1.support;

 import com.google.common.base.Optional;
+import com.google.common.io.ByteStreams;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.haikuos.haikudepotserver.dataobjects.User;
@@ -22,6 +23,8 @@
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

 import javax.annotation.Resource;
+import java.io.IOException;
+import java.io.InputStream;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
@@ -57,6 +60,23 @@
     @Resource
     AuthenticationService authenticationService;

+    protected byte[] getResourceData(String path) throws IOException {
+        InputStream inputStream = null;
+
+        try {
+            inputStream = this.getClass().getResourceAsStream(path);
+
+            if(null==inputStream) {
+ throw new IllegalStateException("unable to find the test resource; "+path);
+            }
+
+            return ByteStreams.toByteArray(inputStream);
+        }
+        finally {
+            Closeables.closeQuietly(inputStream);
+        }
+    }
+
     /**
* <p>Before each test is run, we want to remove all of the database objects and then re-populate
      * them back again.</p>
=======================================
--- /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/support/IntegrationTestSupportService.java Wed Feb 12 10:07:08 2014 UTC +++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/api1/support/IntegrationTestSupportService.java Fri Feb 14 08:42:33 2014 UTC
@@ -52,6 +52,26 @@
             Closeables.closeQuietly(inputStream);
         }
     }
+
+ private void addPkgIcon(ObjectContext objectContext, Pkg pkg, int size) {
+        InputStream inputStream = null;
+
+        try {
+ inputStream = this.getClass().getResourceAsStream(String.format("/sample-%dx%d.png",size,size)); + pkgService.storePkgIconImage(inputStream, size, objectContext, pkg);
+        }
+        catch(Exception e) {
+ throw new IllegalStateException("an issue has arisen loading an icon",e);
+        }
+        finally {
+            Closeables.closeQuietly(inputStream);
+        }
+    }
+
+    private void addPkgIcons(ObjectContext objectContext, Pkg pkg) {
+        addPkgIcon(objectContext, pkg, 16);
+        addPkgIcon(objectContext, pkg, 32);
+    }

     public StandardTestData createStandardTestData() {

@@ -73,6 +93,7 @@
         addPkgScreenshot(context,result.pkg1);
         addPkgScreenshot(context,result.pkg1);
         addPkgScreenshot(context,result.pkg1);
+        addPkgIcons(context, result.pkg1);

         result.pkg1Version1 = context.newObject(PkgVersion.class);
         result.pkg1Version1.setActive(Boolean.FALSE);
=======================================
--- /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/pkg/controller/PkgScreenshotControllerIT.java Wed Feb 12 10:37:01 2014 UTC +++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotsever/pkg/controller/PkgScreenshotControllerIT.java Fri Feb 14 08:42:33 2014 UTC
@@ -37,15 +37,7 @@
      */

     private byte[] getScreenshotData() throws IOException {
-        InputStream inputStream = null;
-
-        try {
- inputStream = this.getClass().getResourceAsStream("/sample-320x240.png");
-            return ByteStreams.toByteArray(inputStream);
-        }
-        finally {
-            Closeables.closeQuietly(inputStream);
-        }
+        return getResourceData("/sample-320x240.png");
     }

     @Test

Other related posts:

  • » [haiku-depot-web] [haiku-depot-web-app] 3 new revisions pushed by haiku.li...@xxxxxxxxx on 2014-02-14 08:43 GMT - haiku-depot-web-app