[haiku-depot-web] [haiku-depot-web-app] 3 new revisions pushed by haiku.li...@xxxxxxxxx on 2014-08-04 00:20 GMT

  • From: haiku-depot-web-app@xxxxxxxxxxxxxx
  • To: haiku-depot-web@xxxxxxxxxxxxx
  • Date: Mon, 04 Aug 2014 00:20:50 +0000

master moved from d0f77bc7ea14 to 98cfe0d1d372

3 new revisions:

Revision: 0f94d3459358
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Sun Aug  3 11:11:48 2014 UTC
Log: + update docs; localization, api for scheduled task, deployment update...
http://code.google.com/p/haiku-depot-web-app/source/detail?r=0f94d3459358

Revision: 91a16c955e95
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Sun Aug  3 21:19:01 2014 UTC
Log: + small fix to the breadcrumb service; search set to {} if there's no ...
http://code.google.com/p/haiku-depot-web-app/source/detail?r=91a16c955e95

Revision: 98cfe0d1d372
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Mon Aug  4 00:20:12 2014 UTC
Log:      + small documentation change
http://code.google.com/p/haiku-depot-web-app/source/detail?r=98cfe0d1d372

==============================================================================
Revision: 0f94d3459358
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Sun Aug  3 11:11:48 2014 UTC
Log: + update docs; localization, api for scheduled task, deployment update
+ logging constant change (upper case)
+ maintenance shifted from internal scheduler to external schedule (eg; cron)
+ removed old Cayenne expression-based logic (was commented out)
+ improved performance for pkg icons in lists
+ improved about page
+ handling (warning message) for unsupported browsers

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

Added:
 /haikudepotserver-docs/src/main/latex/docs/part-localization.tex
/haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/operations/controller/MaintenanceController.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/passwordreset/PasswordResetMaintenanceService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/web/SpringProvidedConfigPropertiesSource.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/userrating/LocalUserRatingDerivationService.java
 /haikudepotserver-webapp/src/main/webapp/WEB-INF/includes/unsupported.jsp
 /haikudepotserver-webapp/src/main/webapp/css/unsupported.css
 /haikudepotserver-webapp/src/main/webapp/img/generic16.png
 /haikudepotserver-webapp/src/main/webapp/img/generic32.png
 /haikudepotserver-webapp/src/main/webapp/img/haikudepot-error.png
/haikudepotserver-webapp/src/main/webapp/js/app/directive/passivecontentdirective.js /haikudepotserver-webapp/src/main/webapp/js/app/directive/supporteddirective.js
 /haikudepotserver-webapp/src/main/webapp/js/app/passivecontent/README.TXT
/haikudepotserver-webapp/src/main/webapp/js/app/passivecontent/aboutcontent.html /haikudepotserver-webapp/src/main/webapp/js/app/passivecontent/aboutcontent_de.html
Deleted:
/haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/userrating/LocalUserRatingDerviationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/web/SpringProvidedConfigPropertiesSource.java
 /haikudepotserver-webapp/src/main/resources/img/generic/README.TXT
 /haikudepotserver-webapp/src/main/resources/img/generic/generic16.png
 /haikudepotserver-webapp/src/main/resources/img/generic/generic32.png
Modified:
/haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/SearchPkgsResult.java
 /haikudepotserver-docs/src/main/latex/docs/docs.tex
 /haikudepotserver-docs/src/main/latex/docs/part-api.tex
 /haikudepotserver-docs/src/main/latex/docs/part-deployment.tex
/haikudepotserver-packagefile/src/main/java/org/haikuos/pkg/tool/AttributeDumpTool.java /haikudepotserver-packagefile/src/main/java/org/haikuos/pkg/tool/PkgDumpTool.java
 /haikudepotserver-parent/pom.xml
 /haikudepotserver-webapp/pom.xml
/haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/AuthorizationApiImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/MiscellaneousApiImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/RepositoryApiImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/UserApiImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/UserRatingApiImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/captcha/DatabaseCaptchaRepository.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/mail/MailTemplateLoader.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/passwordreset/PasswordResetOrchestrationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgOrchestrationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgIconController.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgScreenshotController.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/repository/RepositoryImportService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/repository/RepositoryOrchestrationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/repository/controller/RepositoryImportController.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthenticationFilter.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthenticationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationPkgRuleOrchestrationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/controller/AuthorizationPkgRuleController.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/ImageHelper.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/VersionCoordinates.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/db/migration/ManagedDatabase.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/user/UserOrchestrationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/userrating/UserRatingOrchestrationService.java
 /haikudepotserver-webapp/src/main/resources/messages.properties
 /haikudepotserver-webapp/src/main/resources/messages_de.properties
 /haikudepotserver-webapp/src/main/resources/spring/application-context.xml
 /haikudepotserver-webapp/src/main/resources/spring/general.xml
 /haikudepotserver-webapp/src/main/webapp/WEB-INF/views/entryPoint.jsp
 /haikudepotserver-webapp/src/main/webapp/WEB-INF/web.xml
 /haikudepotserver-webapp/src/main/webapp/css/haikudepotserver.css
 /haikudepotserver-webapp/src/main/webapp/css/viewpkg.css
 /haikudepotserver-webapp/src/main/webapp/img/README.TXT
 /haikudepotserver-webapp/src/main/webapp/js/app/controller/about.html
 /haikudepotserver-webapp/src/main/webapp/js/app/controller/home.html
/haikudepotserver-webapp/src/main/webapp/js/app/directive/pkgicondirective.js /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/AbstractIntegrationTest.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/CapturingMailSender.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/IntegrationTestSupportService.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/api1/AuthorizationApiIT.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/userrating/NoopUserRatingDerviationService.java

=======================================
--- /dev/null
+++ /haikudepotserver-docs/src/main/latex/docs/part-localization.tex Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,46 @@
+% -----------
+% Copyright 2014, Andrew Lindesay
+% Distributed under the terms of the MIT License.
+% -----------
+
+\section{Localization}
+
+Localization refers to the process of adapting the interface of the application to support different languages. Different languages such as English, German or Chinese are referred to as ``natural languages'' in the application in order to differentiate from computer languages such as C++, Java or Ruby. An instance of the application running in a browser has a chosen natural language that has either come about through the user explicitly choosing a language or through the user having authenticated and the authenticated user's natural language being employed.
+
+\subsection{Dates, Times and Numerics}
+
+In general, presentation of dates, times and numerics is made in a locale-agnostic manner.
+
+\subsection{General Messages and Text}
+
+The user interface of the application is implemented in the browser using \href{http://www.angularjs.org/}{AngularJS}. This is a ``single page'' architecture. A service ``messageSource'' is provided that provides a key-to-text mapping system. Example keys are;
+
+\begin{itemize}
+\item {\tt gen.home.title}
+\item {\tt changePassword.action.title}
+\item {\tt addAuthorizationPkgRule.userNickname.required}
+\end{itemize}
+
+The rest of the application uses the messageSource service, together with these known keys, to localize the text that is used to build the user interface. A directive, ``message'' is useful in that it is able to render language-specific text based on the current natural language and a key.
+
+The mapping from the keys to text is done using java properties files. These property files are located in the source at;
+
+\framebox{\tt haikudepotserver-webapp/src/resources/messages*.properties}
+
+Variants of the properties file for various natural languages can be found at this location and each file is suffixed by the code for the natural language. The default, with no suffix, is the English natural language.
+
+If a key does not have a value specified for a specific natural language then it will fall back to the default of English.
+
+\subsection{Emails}
+
+Emails are rendered from data models using the \href{http://freemarker.org/}{Freemarker} library. For each email there is a default which is the English natural language and then there may be variants for various natural languages. The Freemarker templates for email generation are located at;
+
+\framebox{\tt haikudepotserver-webapp/src/resources/email/*.ftl}
+
+\subsection{Error Pages}
+
+The ``error page'' is a page that renders a message to indicate that, for some reason, the user's usage of the application cannot continue. The localization of this page is in-code logic because this approach yields a low probability that the rendering of the error page will result in further error. The text for this page can be found in the file {\it ErrorFilter.java}.
+
+\subsection{Unsupported}
+
+An ``unsupported page'' is designed to appear when a browser does not support the technology required to drive the user interface of the application. This unsupported page has localization messages directly in the JSP template because any detection of natural language or mechanisms to select a natural language may not function. The text for this page can be fund in the file {\it unsupported.jsp}.
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/operations/controller/MaintenanceController.java Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.operations.controller;
+
+import com.google.common.net.HttpHeaders;
+import com.google.common.net.MediaType;
+import org.haikuos.haikudepotserver.passwordreset.PasswordResetMaintenanceService;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * <p>This controller takes care of scheduling maintenance tasks.</p>
+ */
+
+@Controller
+@RequestMapping("/maintenance")
+public class MaintenanceController {
+
+    @Resource
+    PasswordResetMaintenanceService passwordResetMaintenanceService;
+
+    /**
+ * <p>This triggers medium-term maintenance tasks. It is suggested that this might be triggered
+     * hourly.</p>
+     */
+
+    @RequestMapping(value = "/mediumterm", method = RequestMethod.GET)
+    public void fetch(
+            HttpServletResponse response) throws IOException {
+
+        passwordResetMaintenanceService.submit();
+
+        response.setStatus(HttpServletResponse.SC_OK);
+ response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8.toString()); + response.getWriter().print(String.format("accepted request for medium term maintenance"));
+
+    }
+
+}
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/passwordreset/PasswordResetMaintenanceService.java Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.passwordreset;
+
+import com.google.common.base.Preconditions;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.haikuos.haikudepotserver.support.AbstractLocalBackgroundProcessingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Resource;
+
+public class PasswordResetMaintenanceService extends AbstractLocalBackgroundProcessingService {
+
+ protected static Logger LOGGER = LoggerFactory.getLogger(PasswordResetMaintenanceService.class);
+
+    @Resource
+    ServerRuntime serverRuntime;
+
+    @Resource
+    PasswordResetOrchestrationService passwordResetOrchestrationService;
+
+    /**
+ * <p>This method has been overridden in order to ensure that during start-up at least one
+     * maintenance of the password reset is done.</p>
+     */
+
+    @Override
+    public void doStart() {
+        super.doStart();
+        submit();
+    }
+
+    public void submit() {
+ Preconditions.checkState(null != executor, "the service is not running, but a job is being submitted");
+
+        if(runnables.isEmpty()) {
+            executor.submit(new Runnable() {
+                @Override
+                public void run() {
+ passwordResetOrchestrationService.deleteExpiredPasswordResetTokens();
+                }
+            });
+
+ LOGGER.info("did submit job to perform password reset maintenance");
+        }
+        else {
+ LOGGER.info("did not submit job to perform password reset maintenance; there was one already queued");
+        }
+
+    }
+
+}
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/web/SpringProvidedConfigPropertiesSource.java Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+package org.haikuos.haikudepotserver.support.web;
+
+import net.jawr.web.resource.bundle.factory.util.ConfigPropertiesSource;
+import org.springframework.web.context.ContextLoader;
+import org.springframework.web.context.WebApplicationContext;
+
+import java.util.Properties;
+
+/**
+ * <p>Subclass of the JAWR properties file loader that can hook in and get a spring-sourced config properties
+ * from the spring context.</p>
+ */
+
+public class SpringProvidedConfigPropertiesSource implements ConfigPropertiesSource {
+
+ private final static String KEY_PROPERTIESBEAN = "jawrConfigProperties";
+
+    public Properties getConfigProperties() {
+ WebApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); + Properties properties = (Properties) ctx.getBean(KEY_PROPERTIESBEAN);
+        return properties;
+    }
+
+    public boolean configChanged() {
+        return false;
+    }
+
+}
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/userrating/LocalUserRatingDerivationService.java Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,67 @@
+package org.haikuos.haikudepotserver.userrating;
+
+import com.google.common.base.Preconditions;
+import org.haikuos.haikudepotserver.support.AbstractLocalBackgroundProcessingService; +import org.haikuos.haikudepotserver.userrating.model.UserRatingDerivationJob;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Resource;
+
+/**
+ * <p>This implementation of the {@link org.haikuos.haikudepotserver.userrating.UserRatingDerivationService} + * operates in the same runtime as the application and has no persistence or distributed behaviour.</p>
+ */
+
+public class LocalUserRatingDerivationService
+        extends AbstractLocalBackgroundProcessingService
+        implements UserRatingDerivationService {
+
+ protected static Logger LOGGER = LoggerFactory.getLogger(UserRatingDerivationService.class);
+
+    @Resource
+    UserRatingOrchestrationService userRatingOrchestrationService;
+
+    public void submit(final UserRatingDerivationJob job) {
+        Preconditions.checkNotNull(job);
+ Preconditions.checkState(null!=executor, "the service is not running, but a job is being submitted");
+        executor.submit(new UserRatingDerivationJobRunnable(this, job));
+ LOGGER.info("have submitted job to derive user rating; {}", job.toString());
+    }
+
+    protected void run(UserRatingDerivationJob job) {
+        Preconditions.checkNotNull(job);
+ userRatingOrchestrationService.updateUserRatingDerivation(job.getPkgName());
+    }
+
+    /**
+ * <p>This is the object that gets enqueued to actually do the work.</p>
+     */
+
+ public static class UserRatingDerivationJobRunnable implements Runnable {
+
+        private UserRatingDerivationJob job;
+
+        private LocalUserRatingDerivationService service;
+
+        public UserRatingDerivationJobRunnable(
+                LocalUserRatingDerivationService service,
+                UserRatingDerivationJob job) {
+            Preconditions.checkNotNull(service);
+            Preconditions.checkNotNull(job);
+            this.service = service;
+            this.job = job;
+        }
+
+        public UserRatingDerivationJob getJob() {
+            return job;
+        }
+
+        @Override
+        public void run() {
+            service.run(job);
+        }
+
+    }
+
+}
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/webapp/WEB-INF/includes/unsupported.jsp Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,37 @@
+<%--
+This section of HTML is used to display to the user that their browser is not supported. It is rendered by default +and then, when the AngularJS environment runs, a special directive will hide this div; proving that the AngularJS
+environment is working.
+--%>
+
+<div id="unsupported">
+    <div id="unsupported-container">
+ <div class="unsupported-image"><img src="/img/haikudepot-error.png"></div>
+        <h1>Haiku Depot Server</h1>
+
+        <div class="unsupported-message-container">
+            This application doesn't properly work in your current browser.
+ It could be that your browser has JavaScript disabled or it may be because this browser is not supported.
+            Latest versions of the browsers
+ <a href="https://www.haiku-os.org/docs/userguide/en/applications/webpositive.html";>WebPositive</a>,
+            <a href="https://www.mozilla.org/firefox";>Firefox</a>
+            and
+ <a href="https://www.google.com/chrome/browser/";>Google Chrome</a>
+            are known to function.
+        </div>
+
+        <div class="unsupported-message-container">
+            Die Anwendung funktioniert in diesem Browser nicht richtig.
+ Es k&#xF6;nnte sein, dass JavaScript deaktiviert ist oder der Browser
+            generell nicht unterst&#xFC;tzt wird.
+            Die neuesten Versionen von
+ <a href="https://www.haiku-os.org/docs/userguide/en/applications/webpositive.html";>WebPositive</a>,
+            <a href="https://www.mozilla.org/firefox";>Firefox</a>
+ und <a href="https://www.google.com/chrome/browser/";>Google Chrome</a>
+            funktionieren auf alle F&#xE4;lle.
+        </div>
+
+    </div>
+</div>
+
+<supported></supported>
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/webapp/css/unsupported.css Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,42 @@
+/*
+This material refers to a panel that may appear if the browser is not supported or the javascript environment is
+not configured.
+*/
+
+#unsupported {
+    background-color: #505050;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    font-family: sans-serif;
+}
+
+#unsupported.unsupported-hide {
+    display: none;
+}
+
+#unsupported h1 {
+    text-align: center;
+}
+
+#unsupported .unsupported-image {
+    text-align: center;
+}
+
+#unsupported #unsupported-container {
+    color: white;
+    width: 420px;
+    height: 320px;
+    margin:0 auto;
+    margin-top: 72px;
+}
+
+#unsupported #unsupported-container .unsupported-message-container {
+    margin-bottom: 20px;
+}
+
+#unsupported #unsupported-container .unsupported-message-container > a {
+    color: white;
+}
=======================================
--- /dev/null   
+++ /haikudepotserver-webapp/src/main/webapp/img/generic16.png Sun Aug 3 11:11:48 2014 UTC
Binary file, no diff available.
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/webapp/img/generic32.png Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,49 @@
+ PNG
+ + +IHDR szzô IDATX
+Õ mlTU   sî 1/2 3íLg  ÔÒ
+ȸk C
+iBÂ~%>>d5 t7  X6îJLÔ #á   ݸº* 7d 4 Ù¨Í* ÅZ? ,]  ºBQk§¥B[Ñ"¥¥RJ)ÓÎÜ w Ü¡´ Ê 
Èfϯ9÷ ÷<Ïyï{Î
+ø?n¡ÿ Ø þ d *àW q 1/2 à7 õ ]'}=ur°~ ¬[³L cÀ: äû /M$ÊÎ× 3/4 ¿K 1/4 Ìa ô á ÔëÒÕQ!;+ +?/ à5(R)"+* 1a`óC Þwÿúõ PR
+   o ä\öw
+H I§ø4ÙÉ o7ñÔ³{¿ f]
+ à /n ýÛew °\ðÎgÁ à I + ¤ < §µ kAeNóë
+ f/ÿÑ   Á6p  4ÈðE Ø  ¸àÚ8 4  1/2 ô~3s  y ÷ø ¸ª
+5e!æä P + ñáâ"v §¡ º \Õ ÈI@ Ä> ÛÕ s< 1ù' Sg¡ó,$= S¿ ú ~NuðÚ
+` (|   -à1 {úM   tt úË p(R)
+¥§  ¢ À5   ) ej |      ñ é  x  ¢ 3/4 ÊÂñÓ¯-  .U  ð$p  O£
+
+ej? V e h+ +X~ÿ \ Q:<ú \± Æ
+Ü
+1/4 ¿ríÆõÕµÇ  }aïb_@  0.JX ¿Ù.¤Þ0A $¶ +  £÷éÒx<ñÂê'6 n+ÿ1"0l{ür^ ïä
+ ç ë!(R) 8
+8 Ävñl ÝÚ +ç aðï|4/í ÷ôðêÑ£4ôöV Û = ;:Ea bñòû yô(c) ++þ 9(¥PJ¡µ¢·· ÎÏ L/Í# ³Ph@@i ò+CõÚ(à â& fû. óæ + óÈ Ü 1/2`Áì¢hô ºÖÖ? à ܰmöí `Zß¬Þ íÐÚ äõ Ïó D=Ë~s 3§ ÇF\? 4 + RÓ<Èö]ù¬*/'h ^^ a Í Ü¶ñ 1 W <ýr'e3 O ¢Ô7OOÇ l xëµçY4¯ e¿ Æ µ/ÑØOMr +Õ ¬,/'ß² R2g Jk<ÏãÐ 3/4 +-8Àï(c) #` 8csâL?±< 93ó ~c ˺X |¡ ¶ ºî R·ã + =]Å3 ÆYzç fá<<æÏ'ß4 + S R8¶Ã >>ké¬L^² Ç g ]þsd Cí ¸¥4DAÈdxÈ|ò¥FþÑÐ ÿK fÖ ²ö o- Þ^"ñ8
+Ó| R¤ Óì<<ÚÃ(c)ª KÂG ´Rx"# m  ;S
+îL1³(Èþ=-T vÞ iŸp + ÅX  áx
+
+ ¢Q T þýû Sûá úÿÕuYø @ÀRdlÁ ±/=àØ(c)ôE8 +B3Fz Q\LÐ4G Àîî 3/4"üB<¡ ejt.· @ñ îhx(R)3 Mò :w +3/4 Zàøv ì'( x âà à92a4} ß ¤ ¸ Úß<<(R)@ º +ò |1A ú ¡åñ¯ á ÛÚ8 Jå +ßDK °5ûè,Pk [ íë¨(c)~nn¬ T8é ¬ 1/4 0R +-§Æ÷ { >}zû±cÅyZ J
+
+  Ç^DÚ?úúRðÁ,|'pÖÀ/öO -- µ
+ üóïsÃá 1/4 ÂÈd_D$+0 ú +À }]] +[ :^¤ý£¯' _.[ p/Ðö³%kåÞ'ë Äã + Ö << Øeâzÿ4 3/4|²|¹¬!!@7ðçËÅMTó ð>>,4oÔʯ´ +¸ Ø ÿ· óÊ' tµAß!îú¶ÿ ÒB 3/4{nv IEND(R)B` =======================================
--- /dev/null   
+++ /haikudepotserver-webapp/src/main/webapp/img/haikudepot-error.png Sun Aug 3 11:11:48 2014 UTC
Binary file, no diff available.
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/webapp/js/app/directive/passivecontentdirective.js Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+/**
+ * <p>This directive renders a small piece of text and maybe a hyperlink to show a user.</p>
+ */
+
+angular.module('haikudepotserver')
+    .factory('passiveContentCache',[
+        '$cacheFactory',
+        function($cacheFactory) {
+            return $cacheFactory('passiveContent',{ capacity:10 });
+        }
+    ])
+    .directive('passiveContent',[
+        'passiveContentCache','$http','$log','$q',
+        'userState','errorHandling',
+        function(
+            passiveContentCache,$http,$log,$q,
+            userState,errorHandling) {
+            return {
+                restrict: 'A',
+                link : function($scope,element,attributes) {
+
+                    var path = attributes['passiveContent'];
+
+                    function getTemplate(p,naturalLanguageCode) {
+
+ if(!p || !p.length || !p.substring(p.length-5, p.length) == '.html') { + throw Error('the path must be supplied to obtain the passive content and must end with ".html"');
+                        }
+
+                        var deferred = $q.defer();
+ var isFallback = !naturalLanguageCode | | !naturalLanguageCode.length || 'en' == naturalLanguageCode;
+                        var pDash = p;
+
+                        if(!isFallback) {
+ pDash = p.substring(0, p.length-5) + '_' + naturalLanguageCode + '.html';
+                        }
+
+                        var cachedResult = passiveContentCache.get(pDash);
+
+                        if(cachedResult) {
+                            deferred.resolve(cachedResult);
+                        }
+                        else {
+                            $http.get('/js/app/passivecontent/' + pDash)
+                                .success(function (data, status) {
+
+                                    if(200==status) {
+ passiveContentCache.put(pDash,data);
+                                        deferred.resolve(data);
+                                    }
+                                    else {
+ $log.error('http status ' + status + ' error has arisen obtaining the passive content; ' + p);
+                                        deferred.reject();
+                                    }
+
+                                })
+                                .error(function(data,status) {
+
+                                    if (404 == status) {
+                                        if (!isFallback) {
+                                            getTemplate(p).then(
+                                                function (fallbackData) {
+ deferred.resolve(fallbackData);
+                                                },
+                                                function () {
+                                                    deferred.reject();
+                                                }
+                                            );
+                                        }
+                                        else {
+ $log.error('unable to obtain the passive content; ' + p + ' - not found');
+                                            deferred.reject();
+                                        }
+                                    }
+                                    else {
+ $log.error('unable to obtain the passive content; ' + p + '(status:' + status + ')');
+                                        deferred.reject();
+                                    }
+
+                                });
+                        }
+
+                        return deferred.promise;
+                    }
+
+                    function update() {
+
+                        var p = attributes['passiveContent'];
+
+                        if (p && p.length) {
+
+ getTemplate(p, userState.naturalLanguageCode()).then(
+                                function (templateData) {
+
+ // now take this to be some html and insert it. + // TODO; render as underscore template? maybe not necessary. + var templateDataEl = angular.element(templateData);
+                                    element.children().remove();
+                                    element.append(templateDataEl);
+
+                                },
+                                function () {
+ errorHandling.navigateToError(); // already logged.
+                                }
+                            )
+
+                        }
+                    }
+
+                    // EVENT AND CHANGE HANDLING
+
+ attributes.$observe('passiveContent', function() { update(); } ); + $scope.$on( "naturalLanguageChange", function() { update(); } );
+
+                }
+            }
+
+        }
+    ]);
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/webapp/js/app/directive/supporteddirective.js Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014, Andrew Lindesay
+ * Distributed under the terms of the MIT License.
+ */
+
+/**
+ * <p>The single-page JSP page has an 'unsupported' include. This will show a warning if the browser is not + * able to support this application because, for example, it is too old or has javascript disabled. This
+ * directive will remove this so the application displays properly.</p>
+ */
+
+angular.module('haikudepotserver').directive('supported',[
+    '$log',
+    function($log) {
+        return {
+            restrict: 'E',
+            link : function($scope,element,attributes) {
+
+                var d = element[0].ownerDocument;
+                var unsupportedEl = d.getElementById('unsupported');
+
+                if(!unsupportedEl) {
+ throw new Error('unable to find the "unsupported" element');
+                }
+
+ var unsupportedElClass = unsupportedEl.getAttribute('class');
+                var unsupportedElClasses = [];
+
+                if(unsupportedElClass && unsupportedElClass.length) {
+                    unsupportedElClasses = unsupportedElClass.split(' ');
+                }
+
+                unsupportedElClasses.push('unsupported-hide');
+ unsupportedEl.setAttribute('class',unsupportedElClasses.join(' '));
+
+            }
+        }
+
+    }
+]);
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/webapp/js/app/passivecontent/README.TXT Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,2 @@
+This directory contains content that can be rendered directly onto the screen. This by-passes the AngularJS templating
+system and so is able to render localized text that is formatted as HTML.
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/webapp/js/app/passivecontent/aboutcontent.html Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,60 @@
+<div>
+
+    <h1>Purpose</h1>
+
+    <p>
+ This web application is an online tool for working with the software packages of the + <a href="http://www.haiku-os.org/";>Haiku Operating System</a> (Haiku). The web application aims to
+        provide the following functionality;
+    </p>
+
+    <ul>
+        <li>An internet-accessible catalog of the packages.</li>
+        <li>
+ A repository of <em>additional data</em> related to packages that is not included in the standard
+            package format &mdash; such as;
+            <ul>
+                <li>Screenshots</li>
+                <li>Iconography</li>
+                <li>Localizations</li>
+                <li>User-feedback</li>
+            </ul>
+        </li>
+ <li>A user interface to manipulate the <em>additional data</em>.</li>
+        <li>
+ A mechanism to vend this <em>additional data</em> to <em>HaikuDepot</em>, a desktop application
+            for managing packages.
+        </li>
+    </ul>
+
+    <h1>License</h1>
+
+    <p>
+ This software is licensed under the <a href="http://opensource.org/licenses/MIT";>MIT License</a>.
+    </p>
+
+    <h1>Contributors</h1>
+
+ <p>The following people have specifically contributed to this web application;</p>
+
+    <h2>Design and Engineering</h2>
+
+    <ul>
+        <li>Andrew Lindesay</li>
+    </ul>
+
+    <h2>Localizations</h2>
+
+    <ul>
+        <li>Humdinger &mdash; German</li>
+    </ul>
+
+    <h1>Source Code / Mailing List</h1>
+
+    <p>
+ This application's source is <a href="https://code.google.com/p/haiku-depot-web-app/";>hosted</a> at + Google code. The source code includes a LaTeX document covering many aspects of the application. A + <a href="//www.freelists.org/list/haiku-depot-web";>mailing list</a> also exists for the project.
+    </p>
+
+</div>
=======================================
--- /dev/null
+++ /haikudepotserver-webapp/src/main/webapp/js/app/passivecontent/aboutcontent_de.html Sun Aug 3 11:11:48 2014 UTC
@@ -0,0 +1,60 @@
+<div>
+    <h1>Zielsetzung</h1>
+
+    <p>
+ Diese Anwendung ist ein Online-Tool zur Bearbeitung der Softwarepakete des Betriebssystems + <a href="http://www.haiku-os.org/"; target="_blank">Haiku</a>. Die Web-Anwendung bietet
+        dabei die folgenden Funktionen:
+    </p>
+
+    <ul>
+        <li>Einen Online-Katalog aller Pakete.</li>
+        <li>
+ Eine Quelle für <em>zusätzliche Daten</em> für Pakete, die nicht im Standard-Paketformat enthalten
+            sind, beispielsweise:
+            <ul>
+                <li>Bildschirmfotos</li>
+                <li>Icons</li>
+                <li>Übersetzungen</li>
+                <li>Bewertungen</li>
+            </ul>
+        </li>
+ <li>Eine Benutzeroberfläche zur Bearbeitung der <em>zusätzlichen Daten</em>.</li>
+        <li>
+ Einen Mechanismus um diese <em>zusätzlichen Daten</em> <em>HaikuDepot</em> zur Verfügung zustellen,
+            der Desktop-Anwendung zum Managen von Software-Paketen.
+        </li>
+    </ul>
+
+    <h1>Lizenz</h1>
+
+    <p>
+ Die Software wird unter der <a href="http://opensource.org/licenses/MIT"; target="_blank">MIT Lizenz</a> lizensiert.
+    </p>
+
+    <h1>Mitstreiter</h1>
+
+ <p>Folgende Personen haben bei der Realisierung dieser Web-Anwendung mitgeholfen:</p>
+
+    <h2>Design und Programmierung</h2>
+
+    <ul>
+        <li>Andrew Lindesay</li>
+    </ul>
+
+    <h2>Übersetzungen</h2>
+
+    <ul>
+        <li>Humdinger -- Deutsche</li>
+    </ul>
+
+    <h1>Sourcecode / Mailinglist</h1>
+
+    <p>
+ Der Sourcecode der Anwendung liegt bei <a href="https://code.google.com/p/haiku-depot-web-app/"; target="_blank"> + Google Code</a>. Der Sourcecode beinhaltet ein LaTeX Dokument, das viele Details der Anwendung beschreibt. + Außerdem existiert für das Projekt eine <a href="//www.freelists.org/list/haiku-depot-web"; target="_blank">
+        Mailingliste</a>.
+    </p>
+
+</div>
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/userrating/LocalUserRatingDerviationService.java Mon Jun 23 10:01:05 2014 UTC
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.haikuos.haikudepotserver.userrating;
-
-import com.google.common.base.Preconditions;
-import org.haikuos.haikudepotserver.support.AbstractLocalBackgroundProcessingService; -import org.haikuos.haikudepotserver.userrating.model.UserRatingDerivationJob;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.annotation.Resource;
-
-/**
- * <p>This implementation of the {@link org.haikuos.haikudepotserver.userrating.UserRatingDerivationService} - * operates in the same runtime as the application and has no persistence or distributed behaviour.</p>
- */
-
-public class LocalUserRatingDerviationService
-        extends AbstractLocalBackgroundProcessingService
-        implements UserRatingDerivationService {
-
- protected static Logger logger = LoggerFactory.getLogger(UserRatingDerivationService.class);
-
-    @Resource
-    UserRatingOrchestrationService userRatingOrchestrationService;
-
-    public void submit(final UserRatingDerivationJob job) {
-        Preconditions.checkNotNull(job);
- Preconditions.checkState(null!=executor, "the service is not running, but a job is being submitted");
-        executor.submit(new UserRatingDerivationJobRunnable(this, job));
- logger.info("have submitted job to derive user rating; {}", job.toString());
-    }
-
-    protected void run(UserRatingDerivationJob job) {
-        Preconditions.checkNotNull(job);
- userRatingOrchestrationService.updateUserRatingDerivation(job.getPkgName());
-    }
-
-    /**
- * <p>This is the object that gets enqueued to actually do the work.</p>
-     */
-
- public static class UserRatingDerivationJobRunnable implements Runnable {
-
-        private UserRatingDerivationJob job;
-
-        private LocalUserRatingDerviationService service;
-
-        public UserRatingDerivationJobRunnable(
-                LocalUserRatingDerviationService service,
-                UserRatingDerivationJob job) {
-            Preconditions.checkNotNull(service);
-            Preconditions.checkNotNull(job);
-            this.service = service;
-            this.job = job;
-        }
-
-        public UserRatingDerivationJob getJob() {
-            return job;
-        }
-
-        @Override
-        public void run() {
-            service.run(job);
-        }
-
-    }
-
-}
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/web/SpringProvidedConfigPropertiesSource.java Sat Jul 12 08:36:41 2014 UTC
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2014, Andrew Lindesay
- * Distributed under the terms of the MIT License.
- */
-
-package org.haikuos.haikudepotserver.web;
-
-import net.jawr.web.resource.bundle.factory.util.ConfigPropertiesSource;
-import org.springframework.web.context.ContextLoader;
-import org.springframework.web.context.WebApplicationContext;
-
-import java.util.Properties;
-
-/**
- * <p>Subclass of the JAWR properties file loader that can hook in and get a spring-sourced config properties
- * from the spring context.</p>
- */
-
-public class SpringProvidedConfigPropertiesSource implements ConfigPropertiesSource {
-
- private final static String KEY_PROPERTIESBEAN = "jawrConfigProperties";
-
-    public Properties getConfigProperties() {
- WebApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); - Properties properties = (Properties) ctx.getBean(KEY_PROPERTIESBEAN);
-        return properties;
-    }
-
-    public boolean configChanged() {
-        return false;
-    }
-
-}
=======================================
--- /haikudepotserver-webapp/src/main/resources/img/generic/README.TXT Thu Dec 5 09:32:05 2013 UTC
+++ /dev/null
@@ -1,5 +0,0 @@
-The 'generic' icons are used when there is no other icon for a given package. This icon was obtained from the Haiku source repository 2013-11-23 and was obtained from;
-
-.../data/artwork/icons/App_Generic
-
-The icons were loaded into the 'Icon-o-Matic' application in Haiku and then exported to PNG.
=======================================
--- /haikudepotserver-webapp/src/main/resources/img/generic/generic16.png Wed Nov 27 09:58:54 2013 UTC
+++ /dev/null   
Binary file, no diff available.
=======================================
--- /haikudepotserver-webapp/src/main/resources/img/generic/generic32.png Wed Nov 27 09:58:54 2013 UTC
+++ /dev/null
@@ -1,49 +0,0 @@
- PNG
- - -IHDR szzô IDATX
-Õ mlTU   sî 1/2 3íLg  ÔÒ
-ȸk C
-iBÂ~%>>d5 t7  X6îJLÔ #á   ݸº* 7d 4 Ù¨Í* ÅZ? ,]  ºBQk§¥B[Ñ"¥¥RJ)ÓÎÜ w Ü¡´ Ê 
Èfϯ9÷ ÷<Ïyï{Î
-ø?n¡ÿ Ø þ d *àW q 1/2 à7 õ ]'}=ur°~ ¬[³L cÀ: äû /M$ÊÎ× 3/4 ¿K 1/4 Ìa ô á ÔëÒÕQ!;+ -?/ à5(R)"+* 1a`óC Þwÿúõ PR
-   o ä\öw
-H I§ø4ÙÉ o7ñÔ³{¿ f]
- à /n ýÛew °\ðÎgÁ à I - ¤ < §µ kAeNóë
- f/ÿÑ   Á6p  4ÈðE Ø  ¸àÚ8 4  1/2 ô~3s  y ÷ø ¸ª
-5e!æä P - ñáâ"v §¡ º \Õ ÈI@ Ä> ÛÕ s< 1ù' Sg¡ó,$= S¿ ú ~NuðÚ
-` (|   -à1 {úM   tt úË p(R)
-¥§  ¢ À5   ) ej |      ñ é  x  ¢ 3/4 ÊÂñÓ¯-  .U  ð$p  O£
-
-ej? V e h+ -X~ÿ \ Q:<ú \± Æ
-Ü
-1/4 ¿ríÆõÕµÇ  }aïb_@  0.JX ¿Ù.¤Þ0A $¶ +  £÷éÒx<ñÂê'6 n+ÿ1"0l{ür^ ïä
- ç ë!(R) 8
-8 Ävñl ÝÚ -ç aðï|4/í ÷ôðêÑ£4ôöV Û = ;:Ea bñòû yô(c) -+þ 9(¥PJ¡µ¢·· ÎÏ L/Í# ³Ph@@i ò+CõÚ(à â& fû. óæ - óÈ Ü 1/2`Áì¢hô ºÖÖ? à ܰmöí `Zß¬Þ íÐÚ äõ Ïó D=Ë~s 3§ ÇF\? 4 - RÓ<Èö]ù¬*/'h ^^ a Í Ü¶ñ 1 W <ýr'e3 O ¢Ô7OOÇ l xëµçY4¯ e¿ Æ µ/ÑØOMr -Õ ¬,/'ß² R2g Jk<ÏãÐ 3/4 --8Àï(c) #` 8csâL?±< 93ó ~c ˺X |¡ ¶ ºî R·ã - =]Å3 ÆYzç fá<<æÏ'ß4 - S R8¶Ã >>ké¬L^² Ç g ]þsd Cí ¸¥4DAÈdxÈ|ò¥FþÑÐ ÿK fÖ ²ö o- Þ^"ñ8
-Ó| R¤ Óì<<ÚÃ(c)ª KÂG ´Rx"# m  ;S
-îL1³(Èþ=-T vÞ iŸp + ÅX  áx
-
- ¢Q T þýû Sûá úÿÕuYø @ÀRdlÁ ±/=àØ(c)ôE8 -B3Fz Q\LÐ4G Àîî 3/4"üB<¡ ejt.· @ñ îhx(R)3 Mò :w -3/4 Zàøv ì'( x âà à92a4} ß ¤ ¸ Úß<<(R)@ º -ò |1A ú ¡åñ¯ á ÛÚ8 Jå -ßDK °5ûè,Pk [ íë¨(c)~nn¬ T8é ¬ 1/4 0R --§Æ÷ { >}zû±cÅyZ J
-
-  Ç^DÚ?úúRðÁ,|'pÖÀ/öO -- µ
- üóïsÃá 1/4 ÂÈd_D$+0 ú -À }]] -[ :^¤ý£¯' _.[ p/Ðö³%kåÞ'ë Äã - Ö << Øeâzÿ4 3/4|²|¹¬!!@7ðçËÅMTó ð>>,4oÔʯ´ -¸ Ø ÿ· óÊ' tµAß!îú¶ÿ ÒB 3/4{nv IEND(R)B` ======================================= --- /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/SearchPkgsResult.java Sun Jun 29 11:22:04 2014 UTC +++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/SearchPkgsResult.java Sun Aug 3 11:11:48 2014 UTC
@@ -15,6 +15,15 @@
         public String name;
         public Long modifyTimestamp;

+        /**
+ * <p>This will be true if the package has any icon data stored for it; + * regardless of the format of that icon. This can be used as a cue as + * to the value in using a specific URL to get a specific icon for the
+         * package or to use a generic icon.</p>
+         */
+
+        public boolean hasAnyPkgIcons;
+
         /**
* <p>This versions value should only contain the one item actually, but is
          * provided in this form to retain consistency with other API.</p>
=======================================
--- /haikudepotserver-docs/src/main/latex/docs/docs.tex Mon Jul 28 11:10:55 2014 UTC +++ /haikudepotserver-docs/src/main/latex/docs/docs.tex Sun Aug 3 11:11:48 2014 UTC
@@ -1,5 +1,5 @@
 % -----------
-% Copyright 2013, Andrew Lindesay
+% Copyright 2013-2014, Andrew Lindesay
 % Distributed under the terms of the MIT License.
 % -----------

@@ -59,6 +59,7 @@
 \input{part-overview}
 \input{part-datamodel}
 \input{part-userrating}
+\input{part-localization}
 \input{part-security}
 \input{part-config}
 \input{part-buildandrelease}
=======================================
--- /haikudepotserver-docs/src/main/latex/docs/part-api.tex Sun Jul 27 10:42:54 2014 UTC +++ /haikudepotserver-docs/src/main/latex/docs/part-api.tex Sun Aug 3 11:11:48 2014 UTC
@@ -257,6 +257,19 @@

 \framebox{\tt http://localhost:8080/pkgscreenshot/apr/add?format=png}

+\subsubsection{Medium-Term Maintenance}
+
+Medium-term maintenance includes tasks that should be undertaken every hour or so that clean-up disused resources. An example is removing expired password-reset tokens from the database. Medium-term maintenance is triggered externally (from a process such as {\it cron}) rather than on an internal scheduler in order to simplify a multi-instance deployment.
+
+\begin{itemize}
+\item HTTP Method : GET
+\item Path : /maintenance/mediumterm
+\item Expected HTTP Status Codes
+  \begin{itemize}
+  \item {\bf 200} : The maintenance request was accepted
+  \item {\bf *} : The maintenance job was not accepted
+  \end{itemize}
+\end{itemize}



=======================================
--- /haikudepotserver-docs/src/main/latex/docs/part-deployment.tex Sat Jun 28 10:23:44 2014 UTC +++ /haikudepotserver-docs/src/main/latex/docs/part-deployment.tex Sun Aug 3 11:11:48 2014 UTC
@@ -1,5 +1,5 @@
 % -----------
-% Copyright 2013, Andrew Lindesay
+% Copyright 2013-2014, Andrew Lindesay
 % Distributed under the terms of the MIT License.
 % -----------

@@ -44,7 +44,15 @@
 \subsection{Setting Up Repositories}
 \label{settinguprepositories}

-The application server will pull ``.hpkr'' files from remote repositories that contain information about the packages at that repository. Authenticated as root, it is possible to use the ``more'' link at the top of the home page to get to the repositories, to add a repository and to trigger the import of a repository. There also exists an HTTP GET invocation (see \ref{api-importrepositorydata}) that can be made to trigger the import of a repository from another system. +The application server will pull ``.hpkr'' files from remote repositories that contain information about the packages at that repository. Authenticated as root, it is possible to use the ``more'' link at the top of the home page to get to the repositories, to add a repository and to trigger the import of a repository. There also exists an HTTP GET invocation (see \ref{api-importrepositorydata}) that can be made to trigger the import of a repository from another system\footnote{Such as the HPKR assembly process}.
+
+\subsection{Maintenance Tasks}
+
+Some maintenance tasks are scheduled. These tasks are scheduled from outside the application server in order to simplify a multi-instance deployment topology. A simple approach to this is to schedule using the cron tool. This would require a ``crontab'' entry such as;
+
+ \framebox{\tt 14 * * * * curl "http://localhost:8080/maintenance/mediumterm"}
+
+ The host and port should be adjusted to suit your deployment environment.

 \subsection{Accessing the Web Environment}

=======================================
--- /haikudepotserver-packagefile/src/main/java/org/haikuos/pkg/tool/AttributeDumpTool.java Tue Apr 29 10:56:37 2014 UTC +++ /haikudepotserver-packagefile/src/main/java/org/haikuos/pkg/tool/AttributeDumpTool.java Sun Aug 3 11:11:48 2014 UTC
@@ -25,7 +25,7 @@

 public class AttributeDumpTool implements Runnable {

- protected static Logger logger = LoggerFactory.getLogger(AttributeDumpTool.class); + private static Logger LOGGER = LoggerFactory.getLogger(AttributeDumpTool.class);

@Option(name = "-f", required = true, usage = "the HPKR file is required")
     private File hpkrFile;
@@ -57,7 +57,7 @@
             attributeWriter.flush();
         }
         catch(Throwable th) {
-            logger.error("unable to dump attributes",th);
+            LOGGER.error("unable to dump attributes", th);
         }
         finally {
             if(null!=hpkrFileExtractor) {
=======================================
--- /haikudepotserver-packagefile/src/main/java/org/haikuos/pkg/tool/PkgDumpTool.java Tue Apr 29 10:56:37 2014 UTC +++ /haikudepotserver-packagefile/src/main/java/org/haikuos/pkg/tool/PkgDumpTool.java Sun Aug 3 11:11:48 2014 UTC
@@ -26,7 +26,7 @@

 public class PkgDumpTool {

- protected static Logger logger = LoggerFactory.getLogger(AttributeDumpTool.class); + protected static Logger LOGGER = LoggerFactory.getLogger(AttributeDumpTool.class);

@Option(name = "-f", required = true, usage = "the HPKR file is required")
     private File hpkrFile;
@@ -58,7 +58,7 @@
             pkgWriter.flush();
         }
         catch(Throwable th) {
-            logger.error("unable to dump packages",th);
+            LOGGER.error("unable to dump packages", th);
         }
         finally {
             if(null!=hpkrFileExtractor) {
=======================================
--- /haikudepotserver-parent/pom.xml    Mon Jul 28 19:42:23 2014 UTC
+++ /haikudepotserver-parent/pom.xml    Sun Aug  3 11:11:48 2014 UTC
@@ -6,6 +6,13 @@
     <packaging>pom</packaging>
     <version>1.0.2-SNAPSHOT</version>

+    <licenses>
+        <license>
+            <name>The MIT License (MIT)</name>
+            <url>http://opensource.org/licenses/MIT</url>
+        </license>
+    </licenses>
+
     <properties>

         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
=======================================
--- /haikudepotserver-webapp/pom.xml    Sat Jul 26 10:22:06 2014 UTC
+++ /haikudepotserver-webapp/pom.xml    Sun Aug  3 11:11:48 2014 UTC
@@ -125,6 +125,7 @@
             <artifactId>spring-test</artifactId>
             <scope>test</scope>
         </dependency>
+        <!-- spring-context-support is required for mail integration -->
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-context-support</artifactId>
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/AuthorizationApiImpl.java Thu Jul 24 11:35:00 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/AuthorizationApiImpl.java Sun Aug 3 11:11:48 2014 UTC
@@ -35,7 +35,7 @@
 @Component
public class AuthorizationApiImpl extends AbstractApiImpl implements AuthorizationApi {

- protected static Logger logger = LoggerFactory.getLogger(AuthorizationApiImpl.class); + protected static Logger LOGGER = LoggerFactory.getLogger(AuthorizationApiImpl.class);

     @Resource
     ServerRuntime serverRuntime;
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/MiscellaneousApiImpl.java Thu Jul 24 11:35:00 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/MiscellaneousApiImpl.java Sun Aug 3 11:11:48 2014 UTC
@@ -31,7 +31,7 @@
 @Component
public class MiscellaneousApiImpl extends AbstractApiImpl implements MiscellaneousApi {

- protected static Logger logger = LoggerFactory.getLogger(PkgApiImpl.class); + protected static Logger LOGGER = LoggerFactory.getLogger(PkgApiImpl.class);

public final static String RESOURCE_MESSAGES = "/messages%s.properties";

@@ -91,7 +91,7 @@
             throw new RuntimeException("test exception");
         }

- logger.warn("attempt to raise a test exception without being authenticated as root"); + LOGGER.warn("attempt to raise a test exception without being authenticated as root");

         return new RaiseExceptionResult();
     }
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java Sun Jun 29 11:22:04 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java Sun Aug 3 11:11:48 2014 UTC
@@ -55,7 +55,7 @@

     public final static int PKGPKGCATEGORIES_MAX = 3;

- protected static Logger logger = LoggerFactory.getLogger(PkgApiImpl.class); + protected static Logger LOGGER = LoggerFactory.getLogger(PkgApiImpl.class);

     @Resource
     ServerRuntime serverRuntime;
@@ -113,7 +113,7 @@
         User user = obtainAuthenticatedUser(context);

if(!authorizationService.check(context, user, pkg, Permission.PKG_EDITCATEGORIES)) { - logger.warn("attempt to configure the categories for package {}, but the user {} is not able to", pkg.getName(), user.getNickname()); + LOGGER.warn("attempt to configure the categories for package {}, but the user {} is not able to", pkg.getName(), user.getNickname());
             throw new AuthorizationFailureException();
         }

@@ -121,7 +121,7 @@
PkgCategory.getByCodes(context, updatePkgCategoriesRequest.pkgCategoryCodes));

if(pkgCategories.size() != updatePkgCategoriesRequest.pkgCategoryCodes.size()) {
-            logger.warn(
+            LOGGER.warn(
"request for {} categories yielded only {}; must be a code mismatch",
                     updatePkgCategoriesRequest.pkgCategoryCodes.size(),
                     pkgCategories.size());
@@ -156,9 +156,9 @@

         context.commitChanges();

-        logger.info(
+        LOGGER.info(
                 "did configure {} categories for pkg {}",
-                new Object[] {
+                new Object[]{
                         updatePkgCategoriesRequest.pkgCategoryCodes.size(),
                         pkg.getName(),
                 }
@@ -232,6 +232,7 @@
                         resultPkg.name = input.getPkg().getName();
resultPkg.modifyTimestamp = input.getPkg().getModifyTimestamp().getTime(); resultPkg.derivedRating = input.getPkg().getDerivedRating(); + resultPkg.hasAnyPkgIcons = !input.getPkg().getPkgIcons().isEmpty();

SearchPkgsResult.PkgVersion resultVersion = new SearchPkgsResult.PkgVersion();
                         resultVersion.major = input.getMajor();
@@ -260,7 +261,7 @@
                 }
         ));

- logger.info("search for pkgs found {} results", result.items.size()); + LOGGER.info("search for pkgs found {} results", result.items.size());

         return result;
     }
@@ -352,7 +353,7 @@
             shouldIncrement = null==previouslyIncremented;

             if(!shouldIncrement) {
-                logger.info(
+                LOGGER.info(
"would have incremented the view counter for '{}', but the client '{}' already did this recently",
                         pkgVersion.getPkg().toString(),
                         remoteIdentifier);
@@ -362,7 +363,7 @@
         if(shouldIncrement) {
             pkgVersion.incrementViewCounter();
             context.commitChanges();
- logger.info("did increment the view counter for '{}'", pkgVersion.getPkg().toString()); + LOGGER.info("did increment the view counter for '{}'", pkgVersion.getPkg().toString());
         }

         if(null!=cacheKey) {
@@ -577,7 +578,7 @@
         User user = obtainAuthenticatedUser(context);

if(!authorizationService.check(context, user, pkg, Permission.PKG_EDITICON)) { - logger.warn("attempt to configure the icon for package {}, but the user {} is not able to", pkg.getName(), user.getNickname()); + LOGGER.warn("attempt to configure the icon for package {}, but the user {} is not able to", pkg.getName(), user.getNickname());
             throw new AuthorizationFailureException();
         }

@@ -655,7 +656,7 @@

         context.commitChanges();

-        logger.info(
+        LOGGER.info(
                 "did configure icons for pkg {} (updated {}, removed {})",
                 pkg.getName(),
                 updated,
@@ -677,7 +678,7 @@
         User user = obtainAuthenticatedUser(context);

if(!authorizationService.check(context, user, pkg, Permission.PKG_EDITICON)) { - logger.warn("attempt to remove the icon for package {}, but the user {} is not able to", pkg.getName(), user.getNickname()); + LOGGER.warn("attempt to remove the icon for package {}, but the user {} is not able to", pkg.getName(), user.getNickname());
             throw new AuthorizationFailureException();
         }

@@ -691,7 +692,7 @@

         context.commitChanges();

-        logger.info("did remove icons for pkg {}",pkg.getName());
+        LOGGER.info("did remove icons for pkg {}", pkg.getName());

         return new RemovePkgIconResult();
     }
@@ -778,7 +779,7 @@
         context.deleteObjects(screenshotOptional.get());
         context.commitChanges();

- logger.info("did remove the screenshot {} on package {}", removePkgScreenshotRequest.code, pkg.getName()); + LOGGER.info("did remove the screenshot {} on package {}", removePkgScreenshotRequest.code, pkg.getName());

         return new RemovePkgScreenshotResult();
     }
@@ -801,7 +802,7 @@
         pkg.reorderPkgScreenshots(reorderPkgScreenshotsRequest.codes);
         context.commitChanges();

- logger.info("did reorder the screenshots on package {}", pkg.getName()); + LOGGER.info("did reorder the screenshots on package {}", pkg.getName());

         return new ReorderPkgScreenshotsResult();
     }
@@ -880,7 +881,7 @@

         context.commitChanges();

-        logger.info(
+        LOGGER.info(
"did update the localization for pkg {} in architecture {} for {} natural languages",
                 pkg.getName(),
                 architecture.getCode(),
@@ -1106,11 +1107,11 @@
                     }
             );

-            logger.info(
+            LOGGER.info(
"did search and find {} pkg versions for get bulk pkg; fetch in {}ms, marshall in {}ms",
                     pkgVersions.size(),
                     postFetchMs - preFetchMs,
-                    System.currentTimeMillis()-postFetchMs);
+                    System.currentTimeMillis() - postFetchMs);

         }

=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/RepositoryApiImpl.java Wed Jun 4 11:36:29 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/RepositoryApiImpl.java Sun Aug 3 11:11:48 2014 UTC
@@ -37,7 +37,7 @@
 @Component
public class RepositoryApiImpl extends AbstractApiImpl implements RepositoryApi {

- protected static Logger logger = LoggerFactory.getLogger(RepositoryApiImpl.class); + protected static Logger LOGGER = LoggerFactory.getLogger(RepositoryApiImpl.class);

     @Resource
     ServerRuntime serverRuntime;
@@ -204,14 +204,14 @@

if(repositoryOptional.get().getActive() != updateRepositoryRequest.active) { repositoryOptional.get().setActive(updateRepositoryRequest.active); - logger.info("did set the active flag on repository {} to {}", updateRepositoryRequest.code,updateRepositoryRequest.active); + LOGGER.info("did set the active flag on repository {} to {}", updateRepositoryRequest.code, updateRepositoryRequest.active);
                     }

                     break;

                 case URL:
repositoryOptional.get().setUrl(updateRepositoryRequest.url); - logger.info("did set the url on repository {} to {}", updateRepositoryRequest.code,updateRepositoryRequest.url); + LOGGER.info("did set the url on repository {} to {}", updateRepositoryRequest.code, updateRepositoryRequest.url);
                     break;

                 default:
@@ -223,7 +223,7 @@
             context.commitChanges();
         }
         else {
- logger.info("update repository {} with no changes made", updateRepositoryRequest.code); + LOGGER.info("update repository {} with no changes made", updateRepositoryRequest.code);
         }

         return new UpdateRepositoryResult();
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/UserApiImpl.java Tue Jul 8 09:00:54 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/UserApiImpl.java Sun Aug 3 11:11:48 2014 UTC
@@ -41,7 +41,7 @@
 @Component
 public class UserApiImpl extends AbstractApiImpl implements UserApi {

- protected static Logger logger = LoggerFactory.getLogger(UserApiImpl.class); + protected static Logger LOGGER = LoggerFactory.getLogger(UserApiImpl.class);

     @Resource
     ServerRuntime serverRuntime;
@@ -108,7 +108,7 @@

user.get().setNaturalLanguage(naturalLanguageOptional.get());

- logger.info("will update the natural language on the user {} to {}", user.get().toString(), naturalLanguageOptional.get().toString()); + LOGGER.info("will update the natural language on the user {} to {}", user.get().toString(), naturalLanguageOptional.get().toString());

                     break;

@@ -135,7 +135,7 @@

         if(context.hasChanges()) {
             context.commitChanges();
-            logger.info("did update the user {}", user.get().toString());
+            LOGGER.info("did update the user {}", user.get().toString());

// if a user is made active or inactive will have some impact on the user-ratings.

@@ -143,7 +143,7 @@
List<String> pkgNames = userRatingOrchestrationService.pkgNamesEffectedByUserActiveStateChange(
                         context, user.get());

-                logger.info(
+                LOGGER.info(
"will update user rating derivation for {} packages owing to active state change on user {}",
                         pkgNames.size(),
                         user.get().toString());
@@ -155,7 +155,7 @@

         }
         else {
- logger.info("no changes in updating the user {}", user.get().toString()); + LOGGER.info("no changes in updating the user {}", user.get().toString());
         }

         return new UpdateUserResult();
@@ -220,7 +220,7 @@
user.setPasswordHash(authenticationService.hashPassword(user, createUserRequest.passwordClear));
         context.commitChanges();

-        logger.info("data create user; {}",user.getNickname());
+        LOGGER.info("data create user; {}", user.getNickname());

         return new CreateUserResult();
     }
@@ -303,10 +303,10 @@
             ObjectContext context = serverRuntime.getContext();
             User user = User.getByObjectId(context, userOidOptional.get());
             result.token = authenticationService.generateToken(user);
-            logger.info("did renew token for user; {}", user.toString());
+            LOGGER.info("did renew token for user; {}", user.toString());
         }
         else {
-            logger.info("unable to renew token");
+            LOGGER.info("unable to renew token");
         }

         return result;
@@ -337,7 +337,7 @@
         User targetUser = targetUserOptional.get();

if(!authorizationService.check(context, authUser, targetUserOptional.get(), Permission.USER_CHANGEPASSWORD)) { - logger.info("the logged in user {} is not allowed to change the password of another user {}",authUser.getNickname(),changePasswordRequest.nickname); + LOGGER.info("the logged in user {} is not allowed to change the password of another user {}", authUser.getNickname(), changePasswordRequest.nickname);
             throw new AuthorizationFailureException();
         }

@@ -376,7 +376,7 @@
// if the old password does not match to the user then we should present this // as a validation failure rather than an authorization failure.

- logger.info("the supplied old password is invalid for the user {}", changePasswordRequest.nickname); + LOGGER.info("the supplied old password is invalid for the user {}", changePasswordRequest.nickname);

throw new ValidationException(new ValidationFailure("oldPasswordClear", "mismatched"));
             }
@@ -384,7 +384,7 @@

targetUser.setPasswordHash(authenticationService.hashPassword(targetUser, changePasswordRequest.newPasswordClear));
         context.commitChanges();
- logger.info("did change password for user {}", changePasswordRequest.nickname); + LOGGER.info("did change password for user {}", changePasswordRequest.nickname);

         return new ChangePasswordResult();
     }
@@ -454,7 +454,7 @@
passwordResetOrchestrationService.initiate(initiatePasswordResetRequest.email);
         }
         catch(Throwable th) {
-            logger.error("unable to initiate password reset",th);
+            LOGGER.error("unable to initiate password reset", th);
         }

         return new InitiatePasswordResetResult();
@@ -477,7 +477,7 @@
                     completePasswordResetRequest.passwordClear);
         }
         catch(Throwable th) {
-            logger.error("unable to complete password reset",th);
+            LOGGER.error("unable to complete password reset", th);
         }

         return new CompletePasswordResetResult();
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/UserRatingApiImpl.java Sun Jun 29 11:22:04 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/UserRatingApiImpl.java Sun Aug 3 11:11:48 2014 UTC
@@ -34,7 +34,7 @@
 @Component
public class UserRatingApiImpl extends AbstractApiImpl implements UserRatingApi {

- protected static Logger logger = LoggerFactory.getLogger(UserApiImpl.class); + protected static Logger LOGGER = LoggerFactory.getLogger(UserApiImpl.class);

     @Resource
     ServerRuntime serverRuntime;
@@ -226,12 +226,12 @@
Optional<User> authenticatedUserOptional = tryObtainAuthenticatedUser(context);

         if(!authenticatedUserOptional.isPresent()) {
- logger.warn("only authenticated users are able to add user ratings"); + LOGGER.warn("only authenticated users are able to add user ratings");
             throw new AuthorizationFailureException();
         }

if(!authenticatedUserOptional.get().getNickname().equals(userOptional.get().getNickname())) { - logger.warn("it is not allowed to add a user rating for another user"); + LOGGER.warn("it is not allowed to add a user rating for another user");
             throw new AuthorizationFailureException();
         }

@@ -288,7 +288,7 @@

         context.commitChanges();

-        logger.info(
+        LOGGER.info(
                 "did create user rating for user {} on package {}",
                 userOptional.get().toString(),
                 pkgOptional.get().toString());
@@ -318,7 +318,7 @@
                 authenticatedUser,
                 userRatingOptional.get(),
                 Permission.USERRATING_EDIT)) {
- logger.error("unable to edit the userrating as {}", authenticatedUser.toString()); + LOGGER.error("unable to edit the userrating as {}", authenticatedUser.toString());
             throw new AuthorizationFailureException();
         }

@@ -378,7 +378,7 @@

         }

-        logger.info(
+        LOGGER.info(
                 "did update user rating for user {} on package {}",
                 userRatingOptional.get().getUser().toString(),
userRatingOptional.get().getPkgVersion().getPkg().toString());
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/captcha/DatabaseCaptchaRepository.java Tue Apr 29 10:56:37 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/captcha/DatabaseCaptchaRepository.java Sun Aug 3 11:11:48 2014 UTC
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013, Andrew Lindesay
+ * Copyright 2013-2014, Andrew Lindesay
  * Distributed under the terms of the MIT License.
  */

@@ -27,7 +27,7 @@

 public class DatabaseCaptchaRepository implements CaptchaRepository {

- protected static Logger logger = LoggerFactory.getLogger(DatabaseCaptchaRepository.class); + protected static Logger LOGGER = LoggerFactory.getLogger(DatabaseCaptchaRepository.class);

     private ServerRuntime serverRuntime;

@@ -73,7 +73,7 @@
         if(responseOptional.isPresent()) {
             objectContext.deleteObjects(responseOptional.get());
             objectContext.commitChanges();
- logger.info("did delete captcha response with token; {}", token); + LOGGER.info("did delete captcha response with token; {}", token);
             return true;
         }

@@ -114,7 +114,7 @@

         objectContext.commitChanges();

-        logger.info("stored captcha response with token {}",token);
+        LOGGER.info("stored captcha response with token {}", token);
     }

 }
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/mail/MailTemplateLoader.java Tue Jul 8 09:00:54 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/mail/MailTemplateLoader.java Sun Aug 3 11:11:48 2014 UTC
@@ -29,7 +29,7 @@

public class MailTemplateLoader implements TemplateLoader, ResourceLoaderAware {

- protected static Logger logger = LoggerFactory.getLogger(MailTemplateLoader.class); + protected static Logger LOGGER = LoggerFactory.getLogger(MailTemplateLoader.class);

     private final static String BASE = "classpath:/mail/";

=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/passwordreset/PasswordResetOrchestrationService.java Thu Jul 24 11:35:00 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/passwordreset/PasswordResetOrchestrationService.java Sun Aug 3 11:11:48 2014 UTC
@@ -40,7 +40,7 @@
 @Service
 public class PasswordResetOrchestrationService {

- protected static Logger logger = LoggerFactory.getLogger(PasswordResetOrchestrationService.class); + protected static Logger LOGGER = LoggerFactory.getLogger(PasswordResetOrchestrationService.class);

     private final static String MAIL_SUBJECT = "passwordreset-subject";
     private final static String MAIL_PLAINTEXT = "passwordreset-plaintext";
@@ -141,20 +141,20 @@
         List<User> users = User.findByEmail(context, email);

         if (users.isEmpty()) {
- logger.warn("attempt to send password reset token to {}, but there are no users associated with this email address"); + LOGGER.warn("attempt to send password reset token to {}, but there are no users associated with this email address");
         } else {

             int count = 0;

-            logger.info("will create tokens and invite; {}", email);
+            LOGGER.info("will create tokens and invite; {}", email);

             for(User user : users) {
                 if(!user.getActive()) {
- logger.warn("it is not possible to send a password reset to an inactive user; {}", user.toString()); + LOGGER.warn("it is not possible to send a password reset to an inactive user; {}", user.toString());
                 }
                 else {
                     if (user.getIsRoot()) {
- logger.warn("it is not possible to send a password reset to a root user; {}", user.toString()); + LOGGER.warn("it is not possible to send a password reset to a root user; {}", user.toString());
                     } else {
                         createTokenAndInvite(user);
                         count++;
@@ -162,7 +162,7 @@
                 }
             }

- logger.info("did create tokens and invite; {} - sent {}", email,count); + LOGGER.info("did create tokens and invite; {} - sent {}", email, count);
         }
     }

@@ -198,18 +198,18 @@
                                     context.deleteObjects(token);
                                     context.commitChanges();

- logger.info("did reset the password for; {}", user.toString()); + LOGGER.info("did reset the password for; {}", user.toString());
                                 } else {
- logger.warn("the password has been supplied as invalid; will ignore"); + LOGGER.warn("the password has been supplied as invalid; will ignore");
                                 }

                             } else {
- logger.warn("the user having their password reset is inactive; will ignore"); + LOGGER.warn("the user having their password reset is inactive; will ignore");
                             }

                         }
                         else {
- logger.warn("the token used to reset the password is expired; will ignore"); + LOGGER.warn("the token used to reset the password is expired; will ignore");
                         }
                     } finally {

@@ -222,21 +222,21 @@
                         if (deleteTokenOptional.isPresent()) {
deleteContext.deleteObjects(deleteTokenOptional.get());
                             deleteContext.commitChanges();
- logger.info("did delete user password reset token {} after having processed it", tokenCode); + LOGGER.info("did delete user password reset token {} after having processed it", tokenCode);
                         }

                     }

                 } else {
- logger.warn("unable to find the user password reset token {}; will ignore", tokenCode); + LOGGER.warn("unable to find the user password reset token {}; will ignore", tokenCode);
                 }

             } else {
- logger.warn("the code has been supplied as null when attempting to reset a password; will ignore"); + LOGGER.warn("the code has been supplied as null when attempting to reset a password; will ignore");
             }
         }
         catch(Throwable th) {
-            logger.error("unable to reset the password from a token",th);
+            LOGGER.error("unable to reset the password from a token", th);
         }
     }

@@ -257,12 +257,12 @@
List<UserPasswordResetToken> tokens = (List<UserPasswordResetToken>) context.performQuery(query);

         if(tokens.isEmpty()) {
-            logger.debug("no expired tokens to delete");
+            LOGGER.debug("no expired tokens to delete");
         }
         else {
context.deleteObjects(tokens.toArray(new UserPasswordResetToken[tokens.size()]));
             context.commitChanges();
-            logger.info("did delete {} expired tokens", tokens.size());
+            LOGGER.info("did delete {} expired tokens", tokens.size());
         }

     }
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgOrchestrationService.java Thu Jul 24 11:35:00 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgOrchestrationService.java Sun Aug 3 11:11:48 2014 UTC
@@ -47,7 +47,7 @@
 @Service
 public class PkgOrchestrationService {

- protected static Logger logger = LoggerFactory.getLogger(PkgOrchestrationService.class); + protected static Logger LOGGER = LoggerFactory.getLogger(PkgOrchestrationService.class);

     protected static int SCREENSHOT_SIDE_LIMIT = 1500;

@@ -408,17 +408,17 @@
ImageHelper.Size pngSize = imageHelper.derivePngSize(imageData);

             if(null==pngSize) {
- logger.warn("attempt to set the bitmap (png) package icon for package {}, but the size was invalid; it is not a valid png image",pkg.getName()); + LOGGER.warn("attempt to set the bitmap (png) package icon for package {}, but the size was invalid; it is not a valid png image", pkg.getName());
                 throw new BadPkgIconException();
             }

             if(!pngSize.areSides(16) && !pngSize.areSides(32)) {
- logger.warn("attempt to set the bitmap (png) package icon for package {}, but the size was invalid; it must be either 32x32 or 16x16 px, but was {}",pkg.getName(),pngSize.toString()); + LOGGER.warn("attempt to set the bitmap (png) package icon for package {}, but the size was invalid; it must be either 32x32 or 16x16 px, but was {}", pkg.getName(), pngSize.toString());
                 throw new BadPkgIconException();
             }

             if(null!=expectedSize && !pngSize.areSides(expectedSize)) {
- logger.warn("attempt to set the bitmap (png) package icon for package {}, but the size did not match the expected size",pkg.getName()); + LOGGER.warn("attempt to set the bitmap (png) package icon for package {}, but the size did not match the expected size", pkg.getName());
                 throw new BadPkgIconException();
             }

@@ -428,7 +428,7 @@
         else {
if(MediaType.MEDIATYPE_HAIKUVECTORICONFILE.equals(mediaType.getCode())) { if(!imageHelper.looksLikeHaikuVectorIconFormat(imageData)) { - logger.warn("attempt to set the vector (hvif) package icon for package {}, but the data does not look like hvif",pkg.getName()); + LOGGER.warn("attempt to set the vector (hvif) package icon for package {}, but the data does not look like hvif", pkg.getName());
                     throw new BadPkgIconException();
                 }
                 pkgIconOptional = pkg.getPkgIcon(mediaType, null);
@@ -457,10 +457,10 @@
         pkg.setModifyTimestamp(new java.util.Date());

         if(null!=size) {
- logger.info("the icon {}px for package {} has been updated", size, pkg.getName()); + LOGGER.info("the icon {}px for package {} has been updated", size, pkg.getName());
         }
         else {
- logger.info("the icon for package {} has been updated", pkg.getName()); + LOGGER.info("the icon for package {} has been updated", pkg.getName());
         }

         return pkgIconOptional.get();
@@ -531,7 +531,7 @@
         ImageHelper.Size size =  imageHelper.derivePngSize(pngData);

         if(null==size) {
- logger.warn("attempt to store a screenshot image that is not a png"); + LOGGER.warn("attempt to store a screenshot image that is not a png");
             throw new BadPkgScreenshotException();
         }

@@ -539,7 +539,7 @@
         // 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()); + LOGGER.warn("attempt to store a screenshot image that is too large; " + size.toString());
             throw new BadPkgScreenshotException();
         }

@@ -570,7 +570,7 @@

         pkg.setModifyTimestamp(new java.util.Date());

- logger.info("a screenshot #{} has been added to package {} ({})", ordering, pkg.getName(), screenshot.getCode()); + LOGGER.info("a screenshot #{} has been added to package {} ({})", ordering, pkg.getName(), screenshot.getCode());

         return screenshot;
     }
@@ -617,7 +617,7 @@
             persistedPkg.setName(pkg.getName());
             persistedPkg.setActive(Boolean.TRUE);

- logger.info("the package {} did not exist; will create",pkg.getName()); + LOGGER.info("the package {} did not exist; will create", pkg.getName());
         }
         else {

@@ -700,7 +700,7 @@
                         NaturalLanguage.getAllExceptEnglish(objectContext),
                         false).size();

-                logger.info(
+                LOGGER.info(
"replicated {} natural language localizations when creating new version of package {}",
                         naturalLanguagesReplicated,
                         pkg.getName());
@@ -720,7 +720,7 @@
persistedLatestExistingPkgVersion.get().setIsLatest(false);
                 }
                 else {
-                    logger.warn(
+                    LOGGER.warn(
"imported a package version {} which is older or the same as the existing {}",
                             persistedPkgVersionCoords,
                             persistedLatestExistingPkgVersionCoords);
@@ -730,13 +730,13 @@
                 persistedPkgVersion.setIsLatest(true);
             }

-            logger.info(
+            LOGGER.info(
"the version {} of package {} did not exist; will create",
                     pkg.getVersion().toString(),
                     pkg.getName());
         }

-        logger.debug("have processed package {}",pkg.toString());
+        LOGGER.debug("have processed package {}", pkg.toString());

     }

=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgIconController.java Thu Jul 24 11:35:00 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgIconController.java Sun Aug 3 11:11:48 2014 UTC
@@ -26,8 +26,10 @@
 import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.context.ServletContextAware;

 import javax.annotation.Resource;
+import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.InputStream;
@@ -41,9 +43,9 @@

 @Controller
 @RequestMapping("/pkgicon")
-public class PkgIconController extends AbstractController {
+public class PkgIconController extends AbstractController implements ServletContextAware {

- protected static Logger logger = LoggerFactory.getLogger(PkgIconController.class); + protected static Logger LOGGER = LoggerFactory.getLogger(PkgIconController.class);

     public final static String KEY_PKGNAME = "pkgname";
     public final static String KEY_FORMAT = "format";
@@ -58,17 +60,23 @@

     @Resource
     AuthorizationService authorizationService;
+
+    private ServletContext servletContext;
+
+    public void setServletContext(ServletContext servletContext) {
+        this.servletContext = servletContext;
+    }

private LoadingCache<Integer, byte[]> genericBitmapIcons = CacheBuilder.newBuilder()
             .maximumSize(10)
             .build(
                     new CacheLoader<Integer, byte[]>() {
public byte[] load(@SuppressWarnings("NullableProblems") Integer size) { - String resource = String.format("/img/generic/generic%d.png", size); + String resource = String.format("img/generic%d.png", size);
                             InputStream inputStream = null;

                             try {
- inputStream = this.getClass().getResourceAsStream(resource); + inputStream = servletContext.getResourceAsStream(resource);

                                 if(null==inputStream) {
throw new IllegalStateException(String.format("the resource; %s was not able to be found, but should be in the application build product", resource));
@@ -104,14 +112,14 @@
= org.haikuos.haikudepotserver.dataobjects.MediaType.getByExtension(context, format);

         if(!mediaTypeOptional.isPresent()) {
- logger.warn("attempt to request icon of format '{}', but this format was not recognized",format); + LOGGER.warn("attempt to request icon of format '{}', but this format was not recognized", format);
             throw new MissingOrBadFormat();
         }

         Optional<Pkg> pkg = Pkg.getByName(context, pkgName);

         if(!pkg.isPresent()) {
- logger.debug("request for icon for package '{}', but no such package was able to be found",pkgName); + LOGGER.debug("request for icon for package '{}', but no such package was able to be found", pkgName);
             throw new PkgNotFound();
         }

@@ -130,6 +138,7 @@

                 byte[] data = genericBitmapIcons.getUnchecked(size);
response.setHeader(HttpHeaders.CONTENT_LENGTH,Integer.toString(data.length)); + response.setHeader(HttpHeaders.CACHE_CONTROL,"public, max-age=3600");
                 response.setContentType(mediaTypeOptional.get().getCode());

                 if(requestMethod == RequestMethod.GET) {
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgScreenshotController.java Sat Jul 12 08:36:41 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/controller/PkgScreenshotController.java Sun Aug 3 11:11:48 2014 UTC
@@ -37,7 +37,7 @@
 @RequestMapping("/pkgscreenshot")
 public class PkgScreenshotController extends AbstractController {

- protected static Logger logger = LoggerFactory.getLogger(PkgScreenshotController.class); + protected static Logger LOGGER = LoggerFactory.getLogger(PkgScreenshotController.class);

public final static String HEADER_SCREENSHOTCODE = "X-HaikuDepotServer-ScreenshotCode";

@@ -245,7 +245,7 @@
         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"); + 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();
         }

@@ -258,7 +258,7 @@
                     pkg.get()).getCode();
         }
         catch(SizeLimitReachedException sizeLimit) {
- logger.warn("attempt to load in a screenshot larger than the size limit"); + LOGGER.warn("attempt to load in a screenshot larger than the size limit");
             throw new MissingOrBadFormat();
         }
         catch(BadPkgScreenshotException badIcon) {
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/repository/RepositoryImportService.java Thu Jul 24 11:35:00 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/repository/RepositoryImportService.java Sun Aug 3 11:11:48 2014 UTC
@@ -41,7 +41,7 @@

public class RepositoryImportService extends AbstractLocalBackgroundProcessingService {

- protected static Logger logger = LoggerFactory.getLogger(RepositoryImportService.class); + protected static Logger LOGGER = LoggerFactory.getLogger(RepositoryImportService.class);

     @Resource
     ServerRuntime serverRuntime;
@@ -77,10 +77,10 @@
                     }
                 }).isPresent()) {
executor.submit(new ImportRepositoryDataJobRunnable(this, job)); - logger.info("have submitted job to import repository data; {}", job.toString()); + LOGGER.info("have submitted job to import repository data; {}", job.toString());
         }
         else {
- logger.info("ignoring job to import repository data as there is already one waiting; {}", job.toString()); + LOGGER.info("ignoring job to import repository data as there is already one waiting; {}", job.toString());
         }
     }

@@ -108,13 +108,13 @@
temporaryFile = File.createTempFile(job.getCode()+"__import",".hpkr"); Resources.asByteSource(url).copyTo(Files.asByteSink(temporaryFile));

- logger.debug("did copy data for repository {} ({}) to temporary file",job.getCode(),url.toString()); + LOGGER.debug("did copy data for repository {} ({}) to temporary file", job.getCode(), url.toString());

org.haikuos.pkg.HpkrFileExtractor fileExtractor = new org.haikuos.pkg.HpkrFileExtractor(temporaryFile); PkgIterator pkgIterator = new PkgIterator(fileExtractor.getPackageAttributesIterator());

             long startTimeMs = System.currentTimeMillis();
- logger.info("will process data for repository {}",job.getCode()); + LOGGER.info("will process data for repository {}", job.getCode());

             while (pkgIterator.hasNext()) {
ObjectContext pkgImportContext = serverRuntime.getContext();
@@ -122,21 +122,21 @@
                 pkgImportContext.commitChanges();
             }

- logger.info("did process data for repository {} in {}ms",job.getCode(),System.currentTimeMillis()-startTimeMs); + LOGGER.info("did process data for repository {} in {}ms", job.getCode(), System.currentTimeMillis() - startTimeMs);

             transaction.commit();
         }
         catch(Throwable th) {

             transaction.setRollbackOnly();
- logger.error("a problem has arisen processing a repository file for repository "+job.getCode()+" from url '"+url.toString()+"'",th); + LOGGER.error("a problem has arisen processing a repository file for repository " + job.getCode() + " from url '" + url.toString() + "'", th);

         }
         finally {

             if(null!=temporaryFile && temporaryFile.exists()) {
                 if(!temporaryFile.delete()) {
- logger.error("unable to delete the file; {}"+temporaryFile.getAbsolutePath()); + LOGGER.error("unable to delete the file; {}" + temporaryFile.getAbsolutePath());
                 }
             }

=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/repository/RepositoryOrchestrationService.java Sun May 11 12:08:29 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/repository/RepositoryOrchestrationService.java Sun Aug 3 11:11:48 2014 UTC
@@ -26,17 +26,11 @@
 @Service
 public class RepositoryOrchestrationService {

- protected static Logger logger = LoggerFactory.getLogger(RepositoryOrchestrationService.class); + protected static Logger LOGGER = LoggerFactory.getLogger(RepositoryOrchestrationService.class);

     // ------------------------------
     // SEARCH

-    // [apl 11.may.2014]
- // SelectQuery has no means of getting a count. This is a bit of an annoying limitation, but can be worked around - // by using EJBQL. However converting from an Expression to EJBQL has a problem (see CAY-1932) so for the time - // being, just use EJBQL directly by assembling strings and convert back later.
-
- // NOTE; raw EJBQL can be replaced with Expressions once CAY-1932 is fixed.
     private String prepareWhereClause(
             List<Object> parameterAccumulator,
             ObjectContext context,
@@ -68,7 +62,6 @@
         return Joiner.on(" AND ").join(whereExpressions);
     }

- // NOTE; raw EJBQL can be replaced with Expressions once CAY-1932 is fixed. public List<Repository> search(ObjectContext context, RepositorySearchSpecification search) {
         Preconditions.checkNotNull(search);
         Preconditions.checkNotNull(context);
@@ -90,7 +83,6 @@
         return (List<Repository>) context.performQuery(ejbqlQuery);
     }

- // NOTE; raw EJBQL can be replaced with Expressions once CAY-1932 is fixed. public long total(ObjectContext context, RepositorySearchSpecification search) {
         Preconditions.checkNotNull(search);
         Preconditions.checkNotNull(context);
@@ -112,82 +104,5 @@
throw new IllegalStateException("expected 1 row from count query, but got "+result.size());
         }
     }
-
-
-
-// private SelectQuery prepare(ObjectContext context, RepositorySearchSpecification search) {
-//        Preconditions.checkNotNull(search);
-//        Preconditions.checkNotNull(context);
-//
-//        List<Expression> expressions = Lists.newArrayList();
-//
-//        if(null!=search.getExpression()) {
-//            switch(search.getExpressionType()) {
-//                case CONTAINS:
-//                    expressions.add(ExpressionFactory.likeIgnoreCaseExp(
-//                            Repository.CODE_PROPERTY,
-// "%" + LikeHelper.ESCAPER.escape(search.getExpression()) + "%"));
-//                    break;
-//
-//                default:
-// throw new IllegalStateException("unsupported expression type; "+search.getExpressionType());
-//            }
-//        }
-//
-//        if(!search.getIncludeInactive()) {
-// expressions.add(ExpressionFactory.matchExp(Repository.ACTIVE_PROPERTY, Boolean.TRUE));
-//        }
-//
-//        Expression expression = null;
-//
-//        for(Expression e : expressions) {
-//            if(null==expression) {
-//                expression = e;
-//            }
-//            else {
-//                expression = expression.andExp(e);
-//            }
-//        }
-//
-//        return new SelectQuery(Repository.class, expression);
-//    }
-//
-// public List<Repository> search(ObjectContext context, RepositorySearchSpecification search) {
-//        Preconditions.checkNotNull(search);
-//        Preconditions.checkNotNull(context);
-//        Preconditions.checkState(search.getOffset() >= 0);
-//        Preconditions.checkState(search.getLimit() > 0);
-//
-//        SelectQuery selectQuery = prepare(context,search);
-//        selectQuery.setFetchLimit(search.getLimit());
-//        selectQuery.setFetchOffset(search.getOffset());
-// selectQuery.addOrdering(new Ordering(Repository.CODE_PROPERTY, SortOrder.ASCENDING));
-//
-//        //noinspection unchecked
-//        return (List<Repository>) context.performQuery(selectQuery);
-//    }
-//
-// public long total(ObjectContext context, RepositorySearchSpecification search) {
-//        Preconditions.checkNotNull(search);
-//        Preconditions.checkNotNull(context);
-//
-//        SelectQuery selectQuery = prepare(context,search);
-//        List<Object> parameters = Lists.newArrayList();
-// EJBQLQuery ejbQuery = new EJBQLQuery("SELECT COUNT(r) FROM Repository AS r WHERE " + selectQuery.getQualifier().toEJBQL(parameters,"r"));
-//
-//        for(int i=0;i<parameters.size();i++) {
-//            ejbQuery.setParameter(i+1, parameters.get(i));
-//        }
-//
-// @SuppressWarnings("unchecked") List<Number> result = context.performQuery(ejbQuery);
-//
-//        switch(result.size()) {
-//            case 1:
-//                return result.get(0).longValue();
-//
-//            default:
-// throw new IllegalStateException("expected 1 row from count query, but got "+result.size());
-//        }
-//    }

 }
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/repository/controller/RepositoryImportController.java Wed Jun 4 11:36:29 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/repository/controller/RepositoryImportController.java Sun Aug 3 11:11:48 2014 UTC
@@ -32,7 +32,7 @@
 @RequestMapping("/importrepositorydata")
 public class RepositoryImportController {

- protected static Logger logger = LoggerFactory.getLogger(RepositoryImportController.class); + protected static Logger LOGGER = LoggerFactory.getLogger(RepositoryImportController.class);

     public final static String KEY_CODE = "code";

@@ -46,7 +46,7 @@

         try {
             if(Strings.isNullOrEmpty(repositoryCode)) {
- logger.warn("attempt to import repository data service with no repository code supplied"); + LOGGER.warn("attempt to import repository data service with no repository code supplied");
                 response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8.toString()); response.getWriter().print(String.format("expected '%s' to have been a query argument to this resource\n",KEY_CODE));
@@ -59,7 +59,7 @@
             }
         }
         catch(Throwable th) {
-            logger.error("failed to accept import repository job",th);
+            LOGGER.error("failed to accept import repository job", th);

response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8.toString());
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthenticationFilter.java Sat Jul 26 10:22:06 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthenticationFilter.java Sun Aug 3 11:11:48 2014 UTC
@@ -41,7 +41,7 @@

 public class AuthenticationFilter implements Filter {

- protected static Logger logger = LoggerFactory.getLogger(AuthenticationFilter.class); + protected static Logger LOGGER = LoggerFactory.getLogger(AuthenticationFilter.class);

private static Pattern PATTERN_AUTHORIZATION_HEADER = Pattern.compile("^([A-Za-z0-9]+)\\s+(.+)$");

@@ -80,10 +80,10 @@
                             if (2 == parts.size()) {
authenticatedUserObjectId = authenticationService.authenticateByNicknameAndPassword(parts.get(0), parts.get(1));
                             } else {
- logger.warn("attempt to process an authorization header, but the username password is malformed; is not <username>:<password>"); + LOGGER.warn("attempt to process an authorization header, but the username password is malformed; is not <username>:<password>");
                             }
                         } else {
- logger.warn("attempt to process an authorization header, but the username password is malformed; being decoded from base64"); + LOGGER.warn("attempt to process an authorization header, but the username password is malformed; being decoded from base64");
                         }
                         break;

@@ -92,13 +92,13 @@
                         break;

                     default:
- logger.warn("attempt to process an authorization header, but the authorization method {} is unknown :. ignoring", authorizationMatcher.group(1)); + LOGGER.warn("attempt to process an authorization header, but the authorization method {} is unknown :. ignoring", authorizationMatcher.group(1));
                         break;

                 }
             }
             else {
- logger.warn("attempt to process an authorization header, but it is malformed :. ignoring"); + LOGGER.warn("attempt to process an authorization header, but it is malformed :. ignoring");
             }
         }

=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthenticationService.java Sat Jun 28 11:59:46 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthenticationService.java Sun Aug 3 11:11:48 2014 UTC
@@ -47,7 +47,7 @@
 @Service
 public class AuthenticationService {

- protected static Logger logger = LoggerFactory.getLogger(AuthenticationService.class); + protected static Logger LOGGER = LoggerFactory.getLogger(AuthenticationService.class);

     private final static String SUFFIX_JSONWEBTOKEN_SUBJECT = "@hds";

@@ -101,7 +101,7 @@

         if(Strings.isNullOrEmpty(jsonWebTokenSharedKey)) {
             jsonWebTokenSharedKey = UUID.randomUUID().toString();
- logger.warn("a shared key is not supplied so a random one has been created"); + LOGGER.warn("a shared key is not supplied so a random one has been created");
         }

jsonWebTokenSigner = new MACSigner(jsonWebTokenSharedKey.getBytes(Charsets.UTF_8));
@@ -169,15 +169,15 @@
result = Optional.fromNullable(userOptional.get().getObjectId());
                 }
                 else {
- logger.info("the authentication for the user; {} failed", nickname); + LOGGER.info("the authentication for the user; {} failed", nickname);
                 }
             }
             else {
-                logger.info("unable to find the user; {}", nickname);
+                LOGGER.info("unable to find the user; {}", nickname);
             }
         }
         else {
- logger.info("attempt to authenticate with no username or no password"); + LOGGER.info("attempt to authenticate with no username or no password");
         }

         return result;
@@ -268,7 +268,7 @@
         String issuer = claimsSet.getIssuer();

         if(null==issuer||!issuer.equals(jsonWebTokenIssuer)) {
- logger.info("rejected jwt authentication; the issuer '{}' on the jwt does not match the expected '{}'", issuer, jsonWebTokenIssuer); + LOGGER.info("rejected jwt authentication; the issuer '{}' on the jwt does not match the expected '{}'", issuer, jsonWebTokenIssuer);
         }
         else {
             java.util.Date issueTime = claimsSet.getIssueTime();
@@ -279,7 +279,7 @@
                             || null==expirationTime
                             || nowMillis < issueTime.getTime()
                             || nowMillis > expirationTime.getTime()) {
- logger.info("rejected jwt authentication; the issue time or expiration time are invalid or do not contain the current time"); + LOGGER.info("rejected jwt authentication; the issue time or expiration time are invalid or do not contain the current time");
             }
             else {
                 String subject = claimsSet.getSubject();
@@ -288,7 +288,7 @@
                         null==subject
| | !subject.endsWith(SUFFIX_JSONWEBTOKEN_SUBJECT) || subject.length() <= SUFFIX_JSONWEBTOKEN_SUBJECT.length()) { - logger.info("rejected jwt authentication; bad subject"); + LOGGER.info("rejected jwt authentication; bad subject");
                 }
                 else {

@@ -322,7 +322,7 @@
                         return Optional.of(signedJWT);
                     }
                     else {
- logger.error("attempt to use jwt that was unable to be verified"); + LOGGER.error("attempt to use jwt that was unable to be verified");
                     }
                 }
                 catch(JOSEException je) {
@@ -330,7 +330,7 @@
                 }
             }
             catch(ParseException pe) {
- logger.error("rejected malformed jwt that was unable to be parsed",pe); + LOGGER.error("rejected malformed jwt that was unable to be parsed", pe);
             }
         }

=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationPkgRuleOrchestrationService.java Mon Jul 28 10:13:14 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationPkgRuleOrchestrationService.java Sun Aug 3 11:11:48 2014 UTC
@@ -42,7 +42,7 @@
 @Service
 public class AuthorizationPkgRuleOrchestrationService {

- protected static Logger logger = LoggerFactory.getLogger(AuthorizationPkgRuleOrchestrationService.class); + protected static Logger LOGGER = LoggerFactory.getLogger(AuthorizationPkgRuleOrchestrationService.class);

     private static int LIMIT_GENERATECSV = 100;

@@ -243,7 +243,7 @@
         rule.setPermission(permission);
user.addToManyTarget(User.PERMISSION_USER_PKGS_PROPERTY, rule, true);
         rule.setPkg(pkg);
- logger.info("did create permission user repository; {},{},{}",permission,user,pkg); + LOGGER.info("did create permission user repository; {},{},{}", permission, user, pkg);

         return rule;
     }
@@ -262,9 +262,9 @@

         if (permissionUserPkgOptional.isPresent()) {
             context.deleteObjects(permissionUserPkgOptional.get());
- logger.info("did remove permission user package; {},{},{}",permission,user,pkg); + LOGGER.info("did remove permission user package; {},{},{}", permission, user, pkg);
         } else {
- logger.info("no permission user package already existed to remove; {},{},{}",permission,user,pkg); + LOGGER.info("no permission user package already existed to remove; {},{},{}", permission, user, pkg);
         }

     }
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/controller/AuthorizationPkgRuleController.java Sat Jul 26 10:22:06 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/controller/AuthorizationPkgRuleController.java Sun Aug 3 11:11:48 2014 UTC
@@ -27,7 +27,7 @@
 @RequestMapping("/secured/authorization/authorizationpkgrule")
public class AuthorizationPkgRuleController extends AbstractUserAuthenticationAware {

- protected static Logger logger = LoggerFactory.getLogger(AuthorizationPkgRuleController.class); + protected static Logger LOGGER = LoggerFactory.getLogger(AuthorizationPkgRuleController.class);

     @Resource
     ServerRuntime serverRuntime;
@@ -63,7 +63,7 @@
throw new RuntimeException("unable to produce the authorizationpkgrule csv download", ioe);
         }

-        logger.info("did generate the authorizationpkgrule csv download");
+        LOGGER.info("did generate the authorizationpkgrule csv download");

     }

=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/ImageHelper.java Tue Apr 29 10:56:37 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/ImageHelper.java Sun Aug 3 11:11:48 2014 UTC
@@ -11,7 +11,7 @@

 public class ImageHelper {

- protected static Logger logger = LoggerFactory.getLogger(ImageHelper.class); + protected static Logger LOGGER = LoggerFactory.getLogger(ImageHelper.class);

     private int HVIF_MAGIC[] = {
             0x6e, 0x63, 0x69, 0x66
@@ -40,7 +40,7 @@

         for(int i=0;i< HVIF_MAGIC.length;i++) {
             if((0xff & data[i]) != HVIF_MAGIC[i]) {
- logger.trace("the magic header is not present in the hvif data"); + LOGGER.trace("the magic header is not present in the hvif data");
                 return false;
             }
         }
@@ -64,7 +64,7 @@

         for(int i=0;i< PNG_MAGIC.length;i++) {
             if((0xff & data[i]) != PNG_MAGIC[i]) {
- logger.trace("the magic header is not present in the png data"); + LOGGER.trace("the magic header is not present in the png data");
                 return null;
             }
         }
@@ -77,7 +77,7 @@

         for(int i=0;i<PNG_IHDR.length;i++) {
             if((0xff & data[12+i]) != PNG_IHDR[i]) {
- logger.trace("the IHDR chunk is not present in the png data"); + LOGGER.trace("the IHDR chunk is not present in the png data");
                 return null;
             }
         }
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/VersionCoordinates.java Mon Jun 2 11:04:38 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/VersionCoordinates.java Sun Aug 3 11:11:48 2014 UTC
@@ -8,6 +8,10 @@
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;

+/**
+ * <p>This object models the version coordinates of a package.</p>
+ */
+
 public class VersionCoordinates {

     private String major;
=======================================
--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/db/migration/ManagedDatabase.java Tue Apr 29 10:56:37 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/support/db/migration/ManagedDatabase.java Sun Aug 3 11:11:48 2014 UTC
@@ -22,7 +22,7 @@

 public class ManagedDatabase {

- protected static Logger logger = LoggerFactory.getLogger(ManagedDatabase.class); + protected static Logger LOGGER = LoggerFactory.getLogger(ManagedDatabase.class);

     private DataSource dataSource;

@@ -63,9 +63,9 @@
         flyway.setLocations(String.format("db/%s/migration",getSchema()));
         flyway.setDataSource(dataSource);

-        logger.info("will migrate database to latest version...");
+        LOGGER.info("will migrate database to latest version...");
         flyway.migrate();
-        logger.info("did migrate database to latest version...");
+        LOGGER.info("did migrate database to latest version...");
     }

 }
=======================================
***Additional files exist in this changeset.***

==============================================================================
Revision: 91a16c955e95
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Sun Aug  3 21:19:01 2014 UTC
Log: + small fix to the breadcrumb service; search set to {} if there's no search

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

Modified:
/haikudepotserver-webapp/src/main/webapp/js/app/service/breadcrumbsservice.js

=======================================
--- /haikudepotserver-webapp/src/main/webapp/js/app/service/breadcrumbsservice.js Mon Jul 28 09:04:02 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/service/breadcrumbsservice.js Sun Aug 3 21:19:01 2014 UTC
@@ -226,6 +226,9 @@
                     if(item.search) {
                         $location.search(item.search);
                     }
+                    else {
+                        $location.search({});
+                    }
                 }
             }


==============================================================================
Revision: 98cfe0d1d372
Author:   Andrew Lindesay <apl@xxxxxxxxxxxxxx>
Date:     Mon Aug  4 00:20:12 2014 UTC
Log:      + small documentation change

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

Modified:
 /haikudepotserver-docs/src/main/latex/docs/part-localization.tex

=======================================
--- /haikudepotserver-docs/src/main/latex/docs/part-localization.tex Sun Aug 3 11:11:48 2014 UTC +++ /haikudepotserver-docs/src/main/latex/docs/part-localization.tex Mon Aug 4 00:20:12 2014 UTC
@@ -25,17 +25,25 @@

The mapping from the keys to text is done using java properties files. These property files are located in the source at;

-\framebox{\tt haikudepotserver-webapp/src/resources/messages*.properties}
+\framebox{\tt haikudepotserver-webapp/src/main/resources/messages*.properties}

Variants of the properties file for various natural languages can be found at this location and each file is suffixed by the code for the natural language. The default, with no suffix, is the English natural language.

If a key does not have a value specified for a specific natural language then it will fall back to the default of English.

+\subsection{Formatted HTML / Passive Content}
+
+Sometimes it is impractical to take plain-text strings and re-format them into complex layouts. In this case, segments of HTML can be used to insert pre-formatted content that is specific to a given natural language. These segments are located at;
+
+\framebox{\tt haikudepotserver-webapp/src/main/webapp/js/app/passivecontent/*.html}
+
+This is used, for example, in the ``about page''. These segments should use a containing element such as {\it div} in order to contain the material to be rendered. Files for different languages will be suffixed with the natural language.
+
 \subsection{Emails}

Emails are rendered from data models using the \href{http://freemarker.org/}{Freemarker} library. For each email there is a default which is the English natural language and then there may be variants for various natural languages. The Freemarker templates for email generation are located at;

-\framebox{\tt haikudepotserver-webapp/src/resources/email/*.ftl}
+\framebox{\tt haikudepotserver-webapp/src/main/resources/email/*.ftl}

 \subsection{Error Pages}

Other related posts:

  • » [haiku-depot-web] [haiku-depot-web-app] 3 new revisions pushed by haiku.li...@xxxxxxxxx on 2014-08-04 00:20 GMT - haiku-depot-web-app