master moved from f7eb9e811f2c to c9115c719b9d 6 new revisions: Revision: 71a042068116 Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Wed Dec 31 10:32:57 2014 UTCLog: split the pkg/category "report" into "export" / "import" functions...
https://code.google.com/p/haiku-depot-web-app/source/detail?r=71a042068116 Revision: 8f577ae37799 Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Fri Jan 2 10:56:12 2015 UTCLog: introduce a user interface for the package category coverage import pr...
https://code.google.com/p/haiku-depot-web-app/source/detail?r=8f577ae37799 Revision: ddd7d05babcd Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Sat Jan 3 09:08:22 2015 UTC Log: german translations for pkg category import process https://code.google.com/p/haiku-depot-web-app/source/detail?r=ddd7d05babcd Revision: a02e6acf3bf4 Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Sat Jan 3 09:24:53 2015 UTC Log: localization correction https://code.google.com/p/haiku-depot-web-app/source/detail?r=a02e6acf3bf4 Revision: 9aec7bcde339 Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Sat Jan 3 09:29:51 2015 UTC Log: version 1.0.14 https://code.google.com/p/haiku-depot-web-app/source/detail?r=9aec7bcde339 Revision: c9115c719b9d Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Sat Jan 3 09:29:51 2015 UTC Log: version 1.0.15-SNAPSHOT https://code.google.com/p/haiku-depot-web-app/source/detail?r=c9115c719b9d ============================================================================== Revision: 71a042068116 Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Wed Dec 31 10:32:57 2014 UTC Log: split the pkg/category "report" into "export" / "import" functions introduce integration tests for the "export" / "import" functions introduce functionality to show allow a default architecture to be selected https://code.google.com/p/haiku-depot-web-app/source/detail?r=71a042068116 Added:/haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageExportSpreadsheetJobRequest.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageExportSpreadsheetJobResult.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/model/JobRunnerException.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/AbstractPkgCategorySpreadsheetJobRunner.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgCategoryCoverageExportSpreadsheetJobRunner.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgCategoryCoverageImportSpreadsheetJobRunner.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/model/PkgCategoryCoverageExportSpreadsheetJobSpecification.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/model/PkgCategoryCoverageImportSpreadsheetJobSpecification.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/pkg/PkgCategoryCoverageExportSpreadsheetJobRunnerIT.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/pkg/PkgCategoryCoverageImportSpreadsheetJobRunnerIT.java /haikudepotserver-webapp/src/test/resources/sample-pkgcategorycoverageexportspreadsheet-generated.csv /haikudepotserver-webapp/src/test/resources/sample-pkgcategorycoverageimportspreadsheet-generated.csv /haikudepotserver-webapp/src/test/resources/sample-pkgcategorycoverageimportspreadsheet-supplied.csv
Deleted:/haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageSpreadsheetJobRequest.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageSpreadsheetJobResult.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgCategoryCoverageSpreadsheetJobRunner.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/model/PkgCategoryCoverageSpreadsheetJobSpecification.java
Modified:/haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/PkgApi.java
/haikudepotserver-rpm-common/src/main/resources/config__config.properties/haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/PkgVersionLocalization.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/AbstractJobRunner.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/JobOrchestrationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/JobRunner.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/LocalJobOrchestrationServiceImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/controller/JobController.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgOrchestrationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationService.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/model/Permission.java
/haikudepotserver-webapp/src/main/resources/messages.properties /haikudepotserver-webapp/src/main/resources/messages_de.properties /haikudepotserver-webapp/src/main/webapp/js/app/constants.js/haikudepotserver-webapp/src/main/webapp/js/app/controller/homecontroller.js
/haikudepotserver-webapp/src/main/webapp/js/app/controller/reports.html/haikudepotserver-webapp/src/main/webapp/js/app/controller/reportscontroller.js /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/AbstractIntegrationTest.java /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/job/TestJobOrchestrationServiceImpl.java
======================================= --- /dev/null+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageExportSpreadsheetJobRequest.java Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,9 @@ +/* + * Copyright 2014, Andrew Lindesay + * Distributed under the terms of the MIT License. + */ + +package org.haikuos.haikudepotserver.api1.model.pkg; + +public class QueuePkgCategoryCoverageExportSpreadsheetJobRequest { +} ======================================= --- /dev/null+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageExportSpreadsheetJobResult.java Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,19 @@ +/* + * Copyright 2014, Andrew Lindesay + * Distributed under the terms of the MIT License. + */ + +package org.haikuos.haikudepotserver.api1.model.pkg; + +public class QueuePkgCategoryCoverageExportSpreadsheetJobResult { + + public String guid; + + public QueuePkgCategoryCoverageExportSpreadsheetJobResult() { + } ++ public QueuePkgCategoryCoverageExportSpreadsheetJobResult(String guid) {
+ this.guid = guid; + } + +} ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/model/JobRunnerException.java Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,9 @@ +package org.haikuos.haikudepotserver.job.model; + +public class JobRunnerException extends Exception { + + public JobRunnerException(String message) { + super(message); + } + +} ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/AbstractPkgCategorySpreadsheetJobRunner.java Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,52 @@ +package org.haikuos.haikudepotserver.pkg; + +import com.google.common.base.Function; +import com.google.common.collect.Lists; +import org.apache.cayenne.configuration.server.ServerRuntime; +import org.haikuos.haikudepotserver.dataobjects.PkgCategory; +import org.haikuos.haikudepotserver.job.AbstractJobRunner; +import org.haikuos.haikudepotserver.job.model.JobSpecification; + +import javax.annotation.Resource; +import java.util.Collections; +import java.util.List; ++public abstract class AbstractPkgCategorySpreadsheetJobRunner<T extends JobSpecification>
+ extends AbstractJobRunner<T> { + + /**+ * <p>This string is inserted into a cell in order to indicate that the combination of the
+ * package on the row and the category on the column are true.</p> + */ + + protected static String MARKER = "*"; + + @Resource + protected ServerRuntime serverRuntime; + + @Resource + protected PkgOrchestrationService pkgOrchestrationService; + + protected List<String> getPkgCategoryCodes() { + return Lists.transform( + PkgCategory.getAll(serverRuntime.getContext()), + new Function<PkgCategory, String>() { + @Override + public String apply(PkgCategory input) { + return input.getCode(); + } + } + ); + } + + protected String[] getHeadingRow(List<String> pkgCategoryCodes) { + List<String> headings = Lists.newArrayList(); + headings.add("pkg-name"); + headings.add("any-summary"); + headings.add("none");+ Collections.addAll(headings, pkgCategoryCodes.toArray(new String[pkgCategoryCodes.size()]));
+ headings.add("action"); + return headings.toArray(new String[headings.size()]); + } + +} ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgCategoryCoverageExportSpreadsheetJobRunner.java Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,126 @@ +/* + * Copyright 2014, Andrew Lindesay + * Distributed under the terms of the MIT License. + */ + +package org.haikuos.haikudepotserver.pkg; + +import au.com.bytecode.opencsv.CSVWriter; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.net.MediaType; +import org.apache.cayenne.ObjectContext; +import org.apache.cayenne.query.PrefetchTreeNode; +import org.haikuos.haikudepotserver.dataobjects.Architecture; +import org.haikuos.haikudepotserver.dataobjects.Pkg; +import org.haikuos.haikudepotserver.dataobjects.PkgVersionLocalization; +import org.haikuos.haikudepotserver.job.JobOrchestrationService; +import org.haikuos.haikudepotserver.job.model.JobDataWithByteSink; +import org.haikuos.haikudepotserver.job.model.JobRunnerException;+import org.haikuos.haikudepotserver.pkg.model.PkgCategoryCoverageExportSpreadsheetJobSpecification;
+import org.haikuos.haikudepotserver.support.Callback; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.Collections; +import java.util.List; + +/**+ * <p>This report is a spreadsheet that covers basic details of each package.</p>
+ */ + +@Component+public class PkgCategoryCoverageExportSpreadsheetJobRunner extends AbstractPkgCategorySpreadsheetJobRunner<PkgCategoryCoverageExportSpreadsheetJobSpecification> {
++ private static Logger LOGGER = LoggerFactory.getLogger(PkgCategoryCoverageExportSpreadsheetJobRunner.class);
+ + @Override + public void run( + JobOrchestrationService jobOrchestrationService,+ PkgCategoryCoverageExportSpreadsheetJobSpecification specification)
+ throws IOException, JobRunnerException { + + Preconditions.checkArgument(null!=jobOrchestrationService); + assert null!=jobOrchestrationService; + Preconditions.checkArgument(null!=specification); + + final ObjectContext context = serverRuntime.getContext(); + + // this will register the outbound data against the job.+ JobDataWithByteSink jobDataWithByteSink = jobOrchestrationService.storeGeneratedData(
+ specification.getGuid(), + "download", + MediaType.CSV_UTF_8.toString()); + + try(+ OutputStream outputStream = jobDataWithByteSink.getByteSink().openBufferedStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+ CSVWriter writer = new CSVWriter(outputStreamWriter, ',') + ) { + + // headers + + final List<String> pkgCategoryCodes = getPkgCategoryCodes(); + + List<String> headings = Lists.newArrayList(); + headings.add("pkg-name"); + headings.add("any-summary"); + headings.add("none");+ Collections.addAll(headings, pkgCategoryCodes.toArray(new String[pkgCategoryCodes.size()]));
+ headings.add("action"); + + long startMs = System.currentTimeMillis(); ++ writer.writeNext(headings.toArray(new String[headings.size()]));
+ + // stream out the packages. + + PrefetchTreeNode treeNode = new PrefetchTreeNode(); + treeNode.addPath(Pkg.PKG_PKG_CATEGORIES_PROPERTY); ++ LOGGER.info("will produce category coverage spreadsheet report");
+ + int count = pkgOrchestrationService.each( + context, + treeNode,+ Architecture.getAllExceptByCode(context, Collections.singleton(Architecture.CODE_SOURCE)),
+ new Callback<Pkg>() { + @Override + public boolean process(Pkg pkg) { + List<String> cols = Lists.newArrayList();+ Optional<PkgVersionLocalization> locOptional = Optional.absent();
+ + if(null!=pkg) {+ locOptional = PkgVersionLocalization.getAnyPkgVersionLocalizationForPkg(context, pkg);
+ } + + cols.add(pkg.getName());+ cols.add(locOptional.isPresent() ? locOptional.get().getSummary() : ""); + cols.add(pkg.getPkgPkgCategories().isEmpty() ? MARKER : "");
++ for (String pkgCategoryCode : pkgCategoryCodes) { + cols.add(pkg.getPkgPkgCategory(pkgCategoryCode).isPresent() ? MARKER : "");
+ } + + cols.add(""); // no action+ writer.writeNext(cols.toArray(new String[cols.size()]));
+ return true; // keep going! + } + } + ); + + LOGGER.info(+ "did produce category coverage spreadsheet report for {} packages in {}ms",
+ count, + System.currentTimeMillis() - startMs); + + } + + } + +} ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgCategoryCoverageImportSpreadsheetJobRunner.java Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,202 @@ +package org.haikuos.haikudepotserver.pkg; + +import au.com.bytecode.opencsv.CSVReader; +import au.com.bytecode.opencsv.CSVWriter; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.net.MediaType; +import org.apache.cayenne.ObjectContext; +import org.apache.cayenne.access.Transaction; +import org.haikuos.haikudepotserver.dataobjects.Pkg; +import org.haikuos.haikudepotserver.dataobjects.PkgCategory; +import org.haikuos.haikudepotserver.job.JobOrchestrationService; +import org.haikuos.haikudepotserver.job.model.JobDataWithByteSink; +import org.haikuos.haikudepotserver.job.model.JobDataWithByteSource; +import org.haikuos.haikudepotserver.job.model.JobRunnerException;+import org.haikuos.haikudepotserver.pkg.model.PkgCategoryCoverageImportSpreadsheetJobSpecification;
+import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.util.Arrays; +import java.util.List; + +@Component +public class PkgCategoryCoverageImportSpreadsheetJobRunner+ extends AbstractPkgCategorySpreadsheetJobRunner<PkgCategoryCoverageImportSpreadsheetJobSpecification> {
++ private static Logger LOGGER = LoggerFactory.getLogger(PkgCategoryCoverageImportSpreadsheetJobRunner.class);
+ + /**+ * <p>For the import process, this enum describes the action that was taken for a given import line.</p>
+ */ + + private enum Action { + NOACTION, + INVALID, + UPDATED, + NOTFOUND + } + + @Override + public void run( + JobOrchestrationService jobOrchestrationService,+ PkgCategoryCoverageImportSpreadsheetJobSpecification specification)
+ throws IOException, JobRunnerException { + + Preconditions.checkArgument(null != jobOrchestrationService); + assert null!=jobOrchestrationService; + Preconditions.checkArgument(null!=specification);+ Preconditions.checkArgument(null!=specification.getInputDataGuid(), "missing imput data guid on specification");
+ + // this will register the outbound data against the job.+ JobDataWithByteSink jobDataWithByteSink = jobOrchestrationService.storeGeneratedData(
+ specification.getGuid(), + "download", + MediaType.CSV_UTF_8.toString()); ++ // if there is input data then feed it in and process it to manipulate the packages'
+ // categories. ++ Optional<JobDataWithByteSource> jobDataWithByteSourceOptional = jobOrchestrationService.tryObtainData(specification.getInputDataGuid());
+ + if(!jobDataWithByteSourceOptional.isPresent()) {+ throw new IllegalStateException("the job data was not able to be found for guid; " + specification.getInputDataGuid());
+ } + + try(+ OutputStream outputStream = jobDataWithByteSink.getByteSink().openBufferedStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+ CSVWriter writer = new CSVWriter(outputStreamWriter, ',');+ InputStream inputStream = jobDataWithByteSourceOptional.get().getByteSource().openStream(); + InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
+ CSVReader reader = new CSVReader(inputStreamReader); + ) { + + // headers + + List<String> pkgCategoryCodes = getPkgCategoryCodes(); + String[] headings = getHeadingRow(pkgCategoryCodes); ++ // read in the first row of the input and check the headings are there to quasi-validate
+ // that the input is not some random rubbish. + + String[] row = reader.readNext(); + + if(headings.length != row.length) {+ throw new JobRunnerException("wrong number of header columns in input");
+ } + + if(!Arrays.equals(row,headings)) { + throw new JobRunnerException("mismatched input headers"); + } + + writer.writeNext(headings); + + // start a cayenne long-running txn+ Transaction transaction = serverRuntime.getDataDomain().createTransaction();
+ Transaction.bindThreadTransaction(transaction); + + try { + + while (null != (row = reader.readNext())) { + if (0 != row.length) { ++ ObjectContext rowContext = serverRuntime.getContext();
+ + Action action = Action.NOACTION; ++ if (row.length < headings.length - 1) { // -1 because it is possible to omit the action column.
+ action = Action.INVALID;+ LOGGER.warn("inconsistent number of cells on line");
+ } else { + String pkgName = row[0]; + // 1; display + boolean isNone = MARKER.equals(row[2]); ++ Optional<Pkg> pkgOptional = Pkg.getByName(rowContext, pkgName); + List<String> selectedPkgCateogryCodes = Lists.newArrayList();
+ + if (pkgOptional.isPresent()) { ++ for (int i = 0; i < pkgCategoryCodes.size(); i++) {
+ if (MARKER.equals(row[3 + i].trim())) { + + if(isNone) { + action = Action.INVALID;+ LOGGER.warn("line for package {} has 'none' marked as well as an actual category", row[0]);
+ } ++ selectedPkgCateogryCodes.add(pkgCategoryCodes.get(i));
+ } + } + + if(action == Action.NOACTION) {+ List<PkgCategory> selectedPkgCategories = PkgCategory.getByCodes(rowContext, selectedPkgCateogryCodes);
++ if (selectedPkgCategories.size() != selectedPkgCateogryCodes.size()) { + throw new IllegalStateException("one or more of the package category codes was not able to be found");
+ } ++ if (pkgOrchestrationService.updatePkgCategories(
+ rowContext, + pkgOptional.get(), + selectedPkgCategories)) { + action = Action.UPDATED; + rowContext.commitChanges();+ LOGGER.debug("did update for package {}", row[0]);
+ } + } + + } + else { + action = Action.NOTFOUND;+ LOGGER.debug("unable to find the package for {}", row[0]);
+ } + + } ++ // copy the row back verbatim, but with the action result at the
+ // end. + + List<String> rowOutput = Lists.newArrayList(row); + + while (rowOutput.size() < headings.length) { + rowOutput.add(""); + } + + rowOutput.remove(rowOutput.size()-1); + rowOutput.add(action.name()); ++ writer.writeNext(rowOutput.toArray(new String[rowOutput.size()]));
+ } + + } + + transaction.commit(); + } + catch(Throwable th) { + transaction.setRollbackOnly();+ LOGGER.error("a problem has arisen importing package categories from a spreadsheet", th);
+ } + finally { + Transaction.bindThreadTransaction(null); ++ if (Transaction.STATUS_MARKED_ROLLEDBACK == transaction.getStatus()) {
+ try { + transaction.rollback(); + } + catch(Exception e) { + // ignore + } + } + + } + + } + + } + +} ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/model/PkgCategoryCoverageExportSpreadsheetJobSpecification.java Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,16 @@ +package org.haikuos.haikudepotserver.pkg.model; + +import org.haikuos.haikudepotserver.job.model.AbstractJobSpecification; +import org.haikuos.haikudepotserver.job.model.JobSpecification; +import org.springframework.util.ObjectUtils; ++public class PkgCategoryCoverageExportSpreadsheetJobSpecification extends AbstractJobSpecification {
+ + @Override + public boolean isEquivalent(JobSpecification other) { + return+ PkgCategoryCoverageImportSpreadsheetJobSpecification.class.isAssignableFrom(other.getClass()) + && ObjectUtils.nullSafeEquals(other.getOwnerUserNickname(), getOwnerUserNickname());
+ } + +} ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/model/PkgCategoryCoverageImportSpreadsheetJobSpecification.java Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,48 @@ +/* + * Copyright 2014, Andrew Lindesay + * Distributed under the terms of the MIT License. + */ + +package org.haikuos.haikudepotserver.pkg.model; + +import com.google.common.base.Strings; +import org.haikuos.haikudepotserver.job.model.AbstractJobSpecification; +import org.haikuos.haikudepotserver.job.model.JobSpecification; +import org.springframework.util.ObjectUtils; + +import java.util.Collection; +import java.util.Collections; ++public class PkgCategoryCoverageImportSpreadsheetJobSpecification extends AbstractJobSpecification {
+ + /**+ * <p>This identifies the spreadsheet input data that can be used to work off.</p>
+ */ + + private String inputDataGuid; + + public String getInputDataGuid() { + return inputDataGuid; + } + + public void setInputDataGuid(String inputDataGuid) { + this.inputDataGuid = inputDataGuid; + } + + public Collection<String> getSuppliedDataGuids() { + if(!Strings.isNullOrEmpty(inputDataGuid)) { + return Collections.singleton(inputDataGuid); + } + + return super.getSuppliedDataGuids(); + } + + @Override + public boolean isEquivalent(JobSpecification other) { + return+ PkgCategoryCoverageImportSpreadsheetJobSpecification.class.isAssignableFrom(other.getClass()) + && getSuppliedDataGuids().equals(other.getSuppliedDataGuids()) + && ObjectUtils.nullSafeEquals(other.getOwnerUserNickname(), getOwnerUserNickname());
+ } + +} ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/pkg/PkgCategoryCoverageExportSpreadsheetJobRunnerIT.java Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,66 @@ +package org.haikuos.haikudepotserver.pkg; + +import com.google.common.base.Charsets; +import com.google.common.base.Optional; +import com.google.common.collect.Iterables; +import com.google.common.io.ByteSource; +import junit.framework.Assert; +import org.haikuos.haikudepotserver.AbstractIntegrationTest; +import org.haikuos.haikudepotserver.IntegrationTestSupportService; +import org.haikuos.haikudepotserver.job.JobOrchestrationService; +import org.haikuos.haikudepotserver.job.model.JobDataWithByteSource; +import org.haikuos.haikudepotserver.job.model.JobSnapshot;+import org.haikuos.haikudepotserver.pkg.model.PkgCategoryCoverageExportSpreadsheetJobSpecification;
+import org.junit.Test; +import org.springframework.test.context.ContextConfiguration; + +import javax.annotation.Resource; +import java.io.BufferedReader; +import java.io.IOException; + +@ContextConfiguration({ + "classpath:/spring/servlet-context.xml", + "classpath:/spring/test-context.xml" +})+public class PkgCategoryCoverageExportSpreadsheetJobRunnerIT extends AbstractIntegrationTest {
+ + @Resource + private IntegrationTestSupportService integrationTestSupportService; + + @Resource + private JobOrchestrationService jobOrchestrationService; + + /**+ * <p>Uses the sample data and checks that the output from the report matches a captured, sensible-looking
+ * previous run.</p> + */ + + @Test + public void testRun() throws IOException { + + integrationTestSupportService.createStandardTestData(); + + // ------------------------------------ + Optional<String> guidOptional = jobOrchestrationService.submit( + new PkgCategoryCoverageExportSpreadsheetJobSpecification(), + JobOrchestrationService.CoalesceMode.NONE); + // ------------------------------------ ++ jobOrchestrationService.awaitJobConcludedUninterruptibly(guidOptional.get(), 10000); + Optional<? extends JobSnapshot> snapshotOptional = jobOrchestrationService.tryGetJob(guidOptional.get()); + Assert.assertEquals(snapshotOptional.get().getStatus(), JobSnapshot.Status.FINISHED);
++ String dataGuid = Iterables.getOnlyElement(snapshotOptional.get().getGeneratedDataGuids()); + JobDataWithByteSource jobSource = jobOrchestrationService.tryObtainData(dataGuid).get(); + ByteSource expectedByteSource = getResourceByteSource("/sample-pkgcategorycoverageexportspreadsheet-generated.csv");
+ + try(+ BufferedReader jobReader = jobSource.getByteSource().asCharSource(Charsets.UTF_8).openBufferedStream(); + BufferedReader sampleReader = expectedByteSource.asCharSource(Charsets.UTF_8).openBufferedStream()
+ ) { + assertEqualsLineByLine(sampleReader, jobReader); + } + + } + +} ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/pkg/PkgCategoryCoverageImportSpreadsheetJobRunnerIT.java Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,94 @@ +package org.haikuos.haikudepotserver.pkg; + +import com.google.common.base.Charsets; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.io.ByteSource; +import com.google.common.net.MediaType; +import junit.framework.Assert; +import org.apache.cayenne.ObjectContext; +import org.fest.assertions.Assertions; +import org.haikuos.haikudepotserver.AbstractIntegrationTest; +import org.haikuos.haikudepotserver.IntegrationTestSupportService; +import org.haikuos.haikudepotserver.dataobjects.Pkg; +import org.haikuos.haikudepotserver.dataobjects.PkgPkgCategory; +import org.haikuos.haikudepotserver.job.JobOrchestrationService; +import org.haikuos.haikudepotserver.job.model.JobDataWithByteSource; +import org.haikuos.haikudepotserver.job.model.JobSnapshot;+import org.haikuos.haikudepotserver.pkg.model.PkgCategoryCoverageImportSpreadsheetJobSpecification;
+import org.junit.Test; +import org.springframework.test.context.ContextConfiguration; + +import javax.annotation.Resource; +import java.io.BufferedReader; +import java.io.IOException; +import java.util.Set; + +@ContextConfiguration({ + "classpath:/spring/servlet-context.xml", + "classpath:/spring/test-context.xml" +})+public class PkgCategoryCoverageImportSpreadsheetJobRunnerIT extends AbstractIntegrationTest {
+ + @Resource + private IntegrationTestSupportService integrationTestSupportService; + + @Resource + private JobOrchestrationService jobOrchestrationService; + + @Test + public void testRun() throws IOException { + + integrationTestSupportService.createStandardTestData(); ++ PkgCategoryCoverageImportSpreadsheetJobSpecification spec = new PkgCategoryCoverageImportSpreadsheetJobSpecification();
+ spec.setInputDataGuid(jobOrchestrationService.storeSuppliedData( + "input", + MediaType.CSV_UTF_8.toString(),+ getResourceByteSource("/sample-pkgcategorycoverageimportspreadsheet-supplied.csv")
+ ).getGuid()); + + // ------------------------------------+ Optional<String> guidOptional = jobOrchestrationService.submit(spec,JobOrchestrationService.CoalesceMode.NONE);
+ // ------------------------------------ ++ jobOrchestrationService.awaitJobConcludedUninterruptibly(guidOptional.get(), 10000); + Optional<? extends JobSnapshot> snapshotOptional = jobOrchestrationService.tryGetJob(guidOptional.get()); + Assert.assertEquals(snapshotOptional.get().getStatus(), JobSnapshot.Status.FINISHED);
++ String dataGuid = Iterables.getOnlyElement(snapshotOptional.get().getGeneratedDataGuids()); + JobDataWithByteSource jobSource = jobOrchestrationService.tryObtainData(dataGuid).get(); + ByteSource expectedByteSource = getResourceByteSource("/sample-pkgcategorycoverageimportspreadsheet-generated.csv");
+ + try(+ BufferedReader jobReader = jobSource.getByteSource().asCharSource(Charsets.UTF_8).openBufferedStream(); + BufferedReader sampleReader = expectedByteSource.asCharSource(Charsets.UTF_8).openBufferedStream()
+ ) { + assertEqualsLineByLine(sampleReader, jobReader); + } ++ // one of the packages was changed; check that the change is in the database successfully.
+ + { + ObjectContext context = serverRuntime.getContext(); + Optional<Pkg> pkgOptional = Pkg.getByName(context, "pkg1");+ Set<String> pkg1PkgCategoryCodes = ImmutableSet.copyOf(Iterables.transform(
+ pkgOptional.get().getPkgPkgCategories(), + new Function<PkgPkgCategory, String>() { + + @Override + public String apply(PkgPkgCategory input) { + return input.getPkgCategory().getCode(); + } + } + )); ++ Assertions.assertThat(pkg1PkgCategoryCodes).isEqualTo(ImmutableSet.of("audio","graphics"));
+ + } + + } + +} ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/test/resources/sample-pkgcategorycoverageexportspreadsheet-generated.csv Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,5 @@ +"pkg-name","any-summary","none","audio","business","development","education","games","graphics","internetandnetwork","productivity","scienceandmathematics","systemandutilities","video","action" +"pkg1","pkg1Version2SummaryEnglish_persimon","","","","","","","*","","","","","","" +"pkg2","sample summary","*","","","","","","","","","","","","" +"pkg3","sample summary","*","","","","","","","","","","","","" +"pkgany","sample summary","*","","","","","","","","","","","","" ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/test/resources/sample-pkgcategorycoverageimportspreadsheet-generated.csv Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,6 @@ +"pkg-name","any-summary","none","audio","business","development","education","games","graphics","internetandnetwork","productivity","scienceandmathematics","systemandutilities","video","action" +"pkg1","pkg1Version2SummaryEnglish_persimon","","*","","","","","*","","","","","","UPDATED"+"notexisting","sample summary","","","*","*","*","","","","","","","","NOTFOUND"
+"pkg3","sample summary","*","","","","","","","","","","","","NOACTION" +"pkgany","sample summary","*","","*","","*","","","","","","","","INVALID" +"badline","","","","","","","","","","","","","","INVALID" ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/test/resources/sample-pkgcategorycoverageimportspreadsheet-supplied.csv Wed Dec 31 10:32:57 2014 UTC
@@ -0,0 +1,6 @@ +"pkg-name","any-summary","none","audio","business","development","education","games","graphics","internetandnetwork","productivity","scienceandmathematics","systemandutilities","video","action" +"pkg1","pkg1Version2SummaryEnglish_persimon","","*","","","","","*","","","","","","" +"notexisting","sample summary","","","*","*","*","","","","","","","","" +"pkg3","sample summary","*","","","","","","","","","","","","" +"pkgany","sample summary","*","","*","","*","","","","","","","","" +badline =======================================--- /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageSpreadsheetJobRequest.java Sat Dec 20 09:47:27 2014 UTC
+++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2014, Andrew Lindesay - * Distributed under the terms of the MIT License. - */ - -package org.haikuos.haikudepotserver.api1.model.pkg; - -public class QueuePkgCategoryCoverageSpreadsheetJobRequest { -} =======================================--- /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageSpreadsheetJobResult.java Sat Dec 20 09:47:27 2014 UTC
+++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2014, Andrew Lindesay - * Distributed under the terms of the MIT License. - */ - -package org.haikuos.haikudepotserver.api1.model.pkg; - -public class QueuePkgCategoryCoverageSpreadsheetJobResult { - - public String guid; - - public QueuePkgCategoryCoverageSpreadsheetJobResult() { - } - - public QueuePkgCategoryCoverageSpreadsheetJobResult(String guid) { - this.guid = guid; - } - -} =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgCategoryCoverageSpreadsheetJobRunner.java Sat Dec 20 09:47:27 2014 UTC
+++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2014, Andrew Lindesay - * Distributed under the terms of the MIT License. - */ - -package org.haikuos.haikudepotserver.pkg; - -import au.com.bytecode.opencsv.CSVWriter; -import com.google.common.base.Function; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.net.MediaType; -import org.apache.cayenne.ObjectContext; -import org.apache.cayenne.configuration.server.ServerRuntime; -import org.apache.cayenne.exp.Expression; -import org.apache.cayenne.exp.ExpressionFactory; -import org.apache.cayenne.query.PrefetchTreeNode; -import org.apache.cayenne.query.SelectQuery; -import org.haikuos.haikudepotserver.dataobjects.*; -import org.haikuos.haikudepotserver.job.AbstractJobRunner; -import org.haikuos.haikudepotserver.job.JobOrchestrationService; -import org.haikuos.haikudepotserver.job.model.JobDataWithByteSink;-import org.haikuos.haikudepotserver.pkg.model.PkgCategoryCoverageSpreadsheetJobSpecification;
-import org.haikuos.haikudepotserver.support.Callback; -import org.haikuos.haikudepotserver.support.cayenne.ExpressionHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.util.Collections; -import java.util.List; - -/**- * <p>This report is a spreadsheet that covers basic details of each package.</p>
- */ - -@Component-public class PkgCategoryCoverageSpreadsheetJobRunner extends AbstractJobRunner<PkgCategoryCoverageSpreadsheetJobSpecification> {
-- private static Logger LOGGER = LoggerFactory.getLogger(PkgCategoryCoverageSpreadsheetJobRunner.class);
- - /**- * <p>This string is inserted into a cell in order to indicate that the combination of the
- * package on the row and the category on the column are true.</p> - */ - - private static String MARKER = "*"; - - @Resource - private ServerRuntime serverRuntime; - - @Resource - private PkgOrchestrationService pkgOrchestrationService; - - /**- * <p>This will go out and find the first package localization it can find on the latest package
- * versions.</p> - */ -- private Optional<PkgVersionLocalization> getAnyPkgVersionLocalizationForPkg(ObjectContext context, Pkg pkg) {
- - List<Expression> expressions = Lists.newArrayList(); - - expressions.add(ExpressionFactory.matchExp(- PkgVersionLocalization.PKG_VERSION_PROPERTY + "." + PkgVersion.PKG_PROPERTY + ".",
- pkg)); - - expressions.add(ExpressionFactory.matchExp(- PkgVersionLocalization.PKG_VERSION_PROPERTY + "." + PkgVersion.IS_LATEST_PROPERTY,
- true)); - - expressions.add(ExpressionFactory.matchExp(- PkgVersionLocalization.PKG_VERSION_PROPERTY + "." + PkgVersion.ACTIVE_PROPERTY,
- true)); - - SelectQuery query = new SelectQuery( - PkgVersionLocalization.class, - ExpressionHelper.andAll(expressions)); -- List<PkgVersionLocalization> locs = (List<PkgVersionLocalization>) context.performQuery(query);
- - if(locs.isEmpty()) { - return Optional.absent(); - } - - return Optional.of(locs.get(0)); - } - - @Override - public void run( - JobOrchestrationService jobOrchestrationService,- PkgCategoryCoverageSpreadsheetJobSpecification specification) throws IOException {
- - Preconditions.checkArgument(null!=jobOrchestrationService); - assert null!=jobOrchestrationService; - Preconditions.checkArgument(null!=specification); - - final ObjectContext context = serverRuntime.getContext(); - - // this will register the outbound data against the job.- JobDataWithByteSink jobDataWithByteSink = jobOrchestrationService.storeGeneratedData(
- specification.getGuid(), - "download", - MediaType.CSV_UTF_8.toString()); - - try(- OutputStream outputStream = jobDataWithByteSink.getByteSink().openBufferedStream(); - OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
- CSVWriter writer = new CSVWriter(outputStreamWriter, ',') - ) { - - // headers - - final List<String> pkgCategoryCodes = Lists.transform( - PkgCategory.getAll(context), - new Function<PkgCategory, String>() { - @Override - public String apply(PkgCategory input) { - return input.getCode(); - } - } - ); - - List<String> headings = Lists.newArrayList(); - headings.add("pkg-name"); - headings.add("any-summary"); - headings.add("none");- Collections.addAll(headings, pkgCategoryCodes.toArray(new String[pkgCategoryCodes.size()]));
-- writer.writeNext(headings.toArray(new String[headings.size()]));
- - // stream out the packages. - - PrefetchTreeNode treeNode = new PrefetchTreeNode(); - treeNode.addPath(Pkg.PKG_PKG_CATEGORIES_PROPERTY); - - long startMs = System.currentTimeMillis();- LOGGER.info("will produce category coverage spreadsheet report");
- - int count = pkgOrchestrationService.each( - context, - treeNode,- Architecture.getAllExceptByCode(context, Collections.singleton(Architecture.CODE_SOURCE)),
- new Callback<Pkg>() { - @Override - public boolean process(Pkg pkg) {- Optional<PkgVersionLocalization> locOptional = getAnyPkgVersionLocalizationForPkg(context, pkg);
- - List<String> cols = Lists.newArrayList(); - cols.add(pkg.getName());- cols.add(locOptional.isPresent() ? locOptional.get().getSummary() : ""); - cols.add(pkg.getPkgPkgCategories().isEmpty() ? MARKER : "");
-- for (String pkgCategoryCode : pkgCategoryCodes) { - cols.add(pkg.getPkgPkgCategory(pkgCategoryCode).isPresent() ? MARKER : "");
- } -- writer.writeNext(cols.toArray(new String[cols.size()]));
- - return true; - } - }); - - LOGGER.info(- "did produce category coverage spreadsheet report for {} packages in {}ms",
- count, - System.currentTimeMillis() - startMs); - - } - - } - -} =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/model/PkgCategoryCoverageSpreadsheetJobSpecification.java Sat Dec 20 09:47:27 2014 UTC
+++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2014, Andrew Lindesay - * Distributed under the terms of the MIT License. - */ - -package org.haikuos.haikudepotserver.pkg.model; - -import org.haikuos.haikudepotserver.job.model.AbstractJobSpecification; -import org.haikuos.haikudepotserver.job.model.JobSpecification; -import org.springframework.util.ObjectUtils; --public class PkgCategoryCoverageSpreadsheetJobSpecification extends AbstractJobSpecification {
- - @Override - public boolean isEquivalent(JobSpecification other) {- if(PkgCategoryCoverageSpreadsheetJobSpecification.class.isAssignableFrom(other.getClass())) { - return ObjectUtils.nullSafeEquals(other.getOwnerUserNickname(), getOwnerUserNickname());
- } - - return false; - } - -} =======================================--- /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/PkgApi.java Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/PkgApi.java Wed Dec 31 10:32:57 2014 UTC
@@ -145,7 +145,7 @@ * job.</p> */- QueuePkgCategoryCoverageSpreadsheetJobResult queuePkgCategoryCoverageSpreadsheetJob(QueuePkgCategoryCoverageSpreadsheetJobRequest request); + QueuePkgCategoryCoverageExportSpreadsheetJobResult queuePkgCategoryCoverageExportSpreadsheetJob(QueuePkgCategoryCoverageExportSpreadsheetJobRequest request);
/*** <p>Enqueues a request on behalf of the current user to produce a spreadsheet showing which packages have icons
=======================================--- /haikudepotserver-rpm-common/src/main/resources/config__config.properties Fri Oct 3 10:31:27 2014 UTC +++ /haikudepotserver-rpm-common/src/main/resources/config__config.properties Wed Dec 31 10:32:57 2014 UTC
@@ -9,6 +9,8 @@ deployment.isproduction=false +architecture.default.code=x86_gcc2 + # ------------------------------------------- # database connection =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java Wed Dec 31 10:32:57 2014 UTC
@@ -29,10 +29,7 @@ import org.haikuos.haikudepotserver.dataobjects.PkgVersionUrl; import org.haikuos.haikudepotserver.job.JobOrchestrationService; import org.haikuos.haikudepotserver.pkg.PkgOrchestrationService;-import org.haikuos.haikudepotserver.pkg.model.PkgCategoryCoverageSpreadsheetJobSpecification; -import org.haikuos.haikudepotserver.pkg.model.PkgIconSpreadsheetJobSpecification; -import org.haikuos.haikudepotserver.pkg.model.PkgProminenceAndUserRatingSpreadsheetJobSpecification;
-import org.haikuos.haikudepotserver.pkg.model.PkgSearchSpecification; +import org.haikuos.haikudepotserver.pkg.model.*; import org.haikuos.haikudepotserver.security.AuthorizationService; import org.haikuos.haikudepotserver.security.model.Permission; import org.haikuos.haikudepotserver.support.VersionCoordinates; @@ -162,30 +159,7 @@throw new ObjectNotFoundException(PkgCategory.class.getSimpleName(), null);
}- // now go through and delete any of those pkg relationships to packages that are already present - // and which are no longer required. Also remove those that we already have from the list.
-- for(PkgPkgCategory pkgPkgCategory : ImmutableList.copyOf(pkg.getPkgPkgCategories())) {
- if(!pkgCategories.contains(pkgPkgCategory.getPkgCategory())) {- pkg.removeToManyTarget(Pkg.PKG_PKG_CATEGORIES_PROPERTY, pkgPkgCategory, true);
- context.deleteObjects(pkgPkgCategory); - } - else { - pkgCategories.remove(pkgPkgCategory.getPkgCategory()); - } - } -- // now any remaining in the pkgCategories will need to be added to the pkg.
- - for(PkgCategory pkgCategory : pkgCategories) {- PkgPkgCategory pkgPkgCategory = context.newObject(PkgPkgCategory.class);
- pkgPkgCategory.setPkgCategory(pkgCategory);- pkg.addToManyTarget(Pkg.PKG_PKG_CATEGORIES_PROPERTY, pkgPkgCategory, true);
- } - - // now save and finish. - - pkg.setModifyTimestamp();+ pkgOrchestrationService.updatePkgCategories(context, pkg, pkgCategories);
context.commitChanges(); @@ -1168,7 +1142,7 @@ } @Override- public QueuePkgCategoryCoverageSpreadsheetJobResult queuePkgCategoryCoverageSpreadsheetJob(QueuePkgCategoryCoverageSpreadsheetJobRequest request) { + public QueuePkgCategoryCoverageExportSpreadsheetJobResult queuePkgCategoryCoverageExportSpreadsheetJob(QueuePkgCategoryCoverageExportSpreadsheetJobRequest request) {
Preconditions.checkArgument(null!=request); final ObjectContext context = serverRuntime.getContext(); @@ -1179,15 +1153,15 @@ context, user.orNull(), null, - Permission.BULK_PKGCATEGORYCOVERAGESPREADSHEETREPORT)) { + Permission.BULK_PKGCATEGORYCOVERAGEEXPORTSPREADSHEET)) {LOGGER.warn("attempt to access a bulk category coverage spreadsheet report, but was unauthorized");
throw new AuthorizationFailureException(); }- PkgCategoryCoverageSpreadsheetJobSpecification spec = new PkgCategoryCoverageSpreadsheetJobSpecification(); + PkgCategoryCoverageExportSpreadsheetJobSpecification spec = new PkgCategoryCoverageExportSpreadsheetJobSpecification();
spec.setOwnerUserNickname(user.get().getNickname()); - return new QueuePkgCategoryCoverageSpreadsheetJobResult( + return new QueuePkgCategoryCoverageExportSpreadsheetJobResult(jobOrchestrationService.submit(spec,JobOrchestrationService.CoalesceMode.QUEUEDANDSTARTED).orNull());
} =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/PkgVersionLocalization.java Mon Jul 28 09:04:02 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/dataobjects/PkgVersionLocalization.java Wed Dec 31 10:32:57 2014 UTC
@@ -5,11 +5,59 @@ package org.haikuos.haikudepotserver.dataobjects; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import org.apache.cayenne.ObjectContext; +import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.ExpressionFactory; +import org.apache.cayenne.query.Ordering; +import org.apache.cayenne.query.SelectQuery; +import org.apache.cayenne.query.SortOrder;import org.haikuos.haikudepotserver.dataobjects.auto._PkgVersionLocalization; import org.haikuos.haikudepotserver.dataobjects.support.CreateAndModifyTimestamped;
+import org.haikuos.haikudepotserver.support.cayenne.ExpressionHelper; + +import java.util.List;public class PkgVersionLocalization extends _PkgVersionLocalization implements CreateAndModifyTimestamped {
+ public static Optional<PkgVersionLocalization> getAnyPkgVersionLocalizationForPkg(ObjectContext context, Pkg pkg) {
+ + List<Expression> expressions = Lists.newArrayList(); + String pvProp = PkgVersionLocalization.PKG_VERSION_PROPERTY; + + expressions.add(ExpressionFactory.matchExp( + pvProp + "." + PkgVersion.PKG_PROPERTY + ".", + pkg)); + + expressions.add(ExpressionFactory.matchExp( + pvProp + "." + PkgVersion.IS_LATEST_PROPERTY, + true)); + + expressions.add(ExpressionFactory.matchExp( + pvProp + "." + PkgVersion.ACTIVE_PROPERTY, + true)); ++ // the ordering is only important in order to ensure that integration tests are repeatable.
+ + SelectQuery query = new SelectQuery( + PkgVersionLocalization.class, + ExpressionHelper.andAll(expressions), + ImmutableList.of(+ new Ordering(pvProp + "." + PkgVersion.IS_LATEST_PROPERTY,SortOrder.DESCENDING), + new Ordering(pvProp + "." + PkgVersion.ARCHITECTURE_PROPERTY, SortOrder.DESCENDING)
+ )); ++ List<PkgVersionLocalization> locs = (List<PkgVersionLocalization>) context.performQuery(query);
+ + if(locs.isEmpty()) { + return Optional.absent(); + } + + return Optional.of(locs.get(0)); + } + public boolean equalsForContent(PkgVersionLocalization other) { return getSummary().equals(other.getSummary()) =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/AbstractJobRunner.java Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/AbstractJobRunner.java Wed Dec 31 10:32:57 2014 UTC
@@ -6,6 +6,7 @@ package org.haikuos.haikudepotserver.job; import org.haikuos.haikudepotserver.job.model.JobSpecification; +import org.haikuos.haikudepotserver.job.model.JobRunnerException; import javax.annotation.Resource; import java.io.IOException; @@ -36,6 +37,7 @@ } @Override- public abstract void run(JobOrchestrationService jobOrchestrationService, T specification) throws IOException; + public abstract void run(JobOrchestrationService jobOrchestrationService, T specification)
+ throws IOException, JobRunnerException; } =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/JobOrchestrationService.java Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/JobOrchestrationService.java Wed Dec 31 10:32:57 2014 UTC
@@ -26,6 +26,12 @@ QUEUED, QUEUEDANDSTARTED } + + /**+ * <p>This method will block until the job is no longer queued or started.</p>
+ */ + + void awaitJobConcludedUninterruptibly(String guid, long timeout); Optional<String> submit( JobSpecification specification, =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/JobRunner.java Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/JobRunner.java Wed Dec 31 10:32:57 2014 UTC
@@ -6,6 +6,7 @@ package org.haikuos.haikudepotserver.job; import org.haikuos.haikudepotserver.job.model.JobSpecification; +import org.haikuos.haikudepotserver.job.model.JobRunnerException; import java.io.IOException; @@ -24,6 +25,6 @@ String getJobTypeCode();- void run(JobOrchestrationService jobOrchestrationService, T specification) throws IOException; + void run(JobOrchestrationService jobOrchestrationService, T specification) throws IOException, JobRunnerException;
} =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/LocalJobOrchestrationServiceImpl.java Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/LocalJobOrchestrationServiceImpl.java Wed Dec 31 10:32:57 2014 UTC
@@ -15,9 +15,7 @@ import org.haikuos.haikudepotserver.support.DateTimeHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; +import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; import java.io.InputStream; @@ -34,7 +32,7 @@ public class LocalJobOrchestrationServiceImpl extends AbstractService - implements ApplicationContextAware, JobOrchestrationService { + implements JobOrchestrationService {protected static Logger LOGGER = LoggerFactory.getLogger(JobOrchestrationService.class);
@@ -48,11 +46,8 @@private ArrayBlockingQueue<Runnable> runnables = Queues.newArrayBlockingQueue(SIZE_QUEUE);
- /**- * <p>Contains a mapping from the job type code to a suitable runner for that type code.</p>
- */ - - private Map<String,JobRunner> jobRunners; + @Autowired + private List<JobRunner> jobRunners; /** * <p>Contains a mapping from the GUID to the job.</p> @@ -66,16 +61,9 @@ private Set<JobData> datas = Sets.newHashSet(); - private ApplicationContext applicationContext; -public void setJobDataStorageService(JobDataStorageService dataStorageService) {
this.dataStorageService = dataStorageService; } - - @Override- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext; - }private synchronized Collection<Job> findJobsWithStatuses(final EnumSet<JobSnapshot.Status> statuses) { Preconditions.checkArgument(null!=statuses, "the status must be supplied to filter the job run states");
@@ -101,10 +89,55 @@ // ------------------------------ // RUN JOBS - private Optional<JobRunner> getJobRunner(String jobTypeCode) { + private boolean existsAndIsQueuedOrStarted(String guid) {+ Optional<? extends JobSnapshot> jobSnapshotOptional = tryGetJob(guid);
+ + if(!jobSnapshotOptional.isPresent()) { + return false; + } + + switch(jobSnapshotOptional.get().getStatus()) { + case QUEUED: + case STARTED: + return true; + + default: + return false; + } + + } + + @Override+ public void awaitJobConcludedUninterruptibly(String guid, long timeout) {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(guid)); + Preconditions.checkArgument(timeout > 0); + long ms = System.currentTimeMillis(); + + while(System.currentTimeMillis() - ms < timeout + && existsAndIsQueuedOrStarted(guid)) { + synchronized(this) { + try { + wait(timeout); + } + catch(InterruptedException ie) { + Thread.currentThread().interrupt(); + } + } + } + } + + private Optional<JobRunner> getJobRunner(final String jobTypeCode) { Preconditions.checkArgument(!Strings.isNullOrEmpty(jobTypeCode));Preconditions.checkState(null!=jobRunners,"the job runners must be configured - was this started up properly?");
- return Optional.fromNullable(jobRunners.get(jobTypeCode)); + return Iterables.tryFind( + jobRunners, + new Predicate<JobRunner>() { + @Override + public boolean apply(JobRunner input) { + return input.getJobTypeCode().equals(jobTypeCode); + } + } + ); } private Job submit(JobSpecification specification) { @@ -449,6 +482,8 @@ job.setStartTimestamp(); LOGGER.info("{}; start", job.getJobSpecification().toString()); + + notifyAll(); } public synchronized void setJobFinishTimestamp(String guid) { @@ -460,6 +495,8 @@ job.setFinishTimestamp(); LOGGER.info("{}; finish", job.getJobSpecification().toString()); + + notifyAll(); } public synchronized void setJobRunQueuedTimestamp(String guid) { @@ -471,6 +508,8 @@ job.setQueuedTimestamp(); LOGGER.info("{}; queued", job.getJobSpecification().toString()); + + notifyAll(); } @Override @@ -483,6 +522,8 @@ job.setFailTimestamp(); LOGGER.info("{}; fail", job.getJobSpecification().toString()); + + notifyAll(); } @Override @@ -494,6 +535,7 @@ case STARTED: job.setCancelTimestamp();LOGGER.info("{}; cancelled", job.getJobSpecification().toString());
+ notifyAll(); break; default: @@ -519,6 +561,8 @@ } job.setProgressPercent(progressPercent); + + notifyAll(); } // ------------------------------ @@ -532,16 +576,6 @@ LOGGER.info("will start service"); jobs = Maps.newHashMap(); - - jobRunners = Maps.newHashMap(); -- for(JobRunner jobRunner : applicationContext.getBeansOfType(JobRunner.class).values()) {
- jobRunners.put(jobRunner.getJobTypeCode(), jobRunner); - LOGGER.info( - "registered job runner; {} ({})", - jobRunner.getJobTypeCode(), - jobRunner.getClass().getSimpleName()); - } executor = new ThreadPoolExecutor( 0, // core pool size =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/controller/JobController.java Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/controller/JobController.java Wed Dec 31 10:32:57 2014 UTC
@@ -6,7 +6,9 @@ package org.haikuos.haikudepotserver.job.controller; import com.google.common.base.Optional; +import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import com.google.common.io.ByteSource; import com.google.common.net.HttpHeaders; import com.google.common.net.MediaType; import org.apache.cayenne.ObjectContext; @@ -23,14 +25,13 @@ import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.InputStream; /*** <p>The job controller allows for upload and download of binary data related to jobs; for example, there are
@@ -46,6 +47,8 @@ public final static String KEY_GUID = "guid"; + public final static String KEY_USECODE = "usecode"; + @Resource private JobOrchestrationService jobOrchestrationService; @@ -55,8 +58,42 @@ @Resource private AuthorizationService authorizationService; + /**+ * <p>This URL can be used to supply data that can be used with a job to be run as an input to the
+ * job.</p> + */ + + @RequestMapping(value = "/jobdata", method = RequestMethod.POST) + @ResponseBody + public String supplyData( + final HttpServletRequest request,+ @RequestHeader(value = HttpHeaders.CONTENT_TYPE, required = false) String contentType, + @RequestParam(value = KEY_USECODE, required = false) String useCode)
+ throws IOException { + + Preconditions.checkArgument(null!=request); + assert null!=request; + + JobData data = jobOrchestrationService.storeSuppliedData( + useCode,+ !Strings.isNullOrEmpty(contentType) ? contentType : MediaType.OCTET_STREAM.toString(),
+ new ByteSource() { + @Override + public InputStream openStream() throws IOException { + return request.getInputStream(); + } + } + ); + + return data.getGuid(); + } + + /**+ * <p>This URL can be used to download job data that has resulted from a job being run.</p>
+ */ +@RequestMapping(value = "/jobdata/{" + KEY_GUID + "}/download", method = RequestMethod.GET)
- public void data( + public void downloadGeneratedData( HttpServletResponse response, @PathVariable(value = KEY_GUID) String guid) throws IOException{ =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgOrchestrationService.java Wed Nov 26 09:34:57 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/pkg/PkgOrchestrationService.java Wed Dec 31 10:32:57 2014 UTC
@@ -1194,5 +1194,54 @@ return Collections.emptyList(); } + // ------------------------------ + // MISC + + /**+ * <p>This method will update the {@link org.haikuos.haikudepotserver.dataobjects.PkgCategory} set in the + * nominated {@link org.haikuos.haikudepotserver.dataobjects.Pkg} such that the supplied set are the + * categories for the package. It will do this by adding and removing relationships between the package
+ * and the categories.</p> + * @return true if a change was made. + */ ++ public boolean updatePkgCategories(ObjectContext context, Pkg pkg, List<PkgCategory> pkgCategories) {
+ Preconditions.checkArgument(null!=context); + Preconditions.checkArgument(null!=pkg); + Preconditions.checkArgument(null!=pkgCategories); + + boolean didChange = false; ++ // now go through and delete any of those pkg relationships to packages that are already present + // and which are no longer required. Also remove those that we already have from the list.
++ for(PkgPkgCategory pkgPkgCategory : ImmutableList.copyOf(pkg.getPkgPkgCategories())) {
+ if(!pkgCategories.contains(pkgPkgCategory.getPkgCategory())) {+ pkg.removeToManyTarget(Pkg.PKG_PKG_CATEGORIES_PROPERTY, pkgPkgCategory, true);
+ context.deleteObjects(pkgPkgCategory); + didChange = true; + } + else { + pkgCategories.remove(pkgPkgCategory.getPkgCategory()); + } + } ++ // now any remaining in the pkgCategories will need to be added to the pkg.
+ + for(PkgCategory pkgCategory : pkgCategories) {+ PkgPkgCategory pkgPkgCategory = context.newObject(PkgPkgCategory.class);
+ pkgPkgCategory.setPkgCategory(pkgCategory);+ pkg.addToManyTarget(Pkg.PKG_PKG_CATEGORIES_PROPERTY, pkgPkgCategory, true);
+ didChange = true; + } + + // now save and finish. + + if(didChange) { + pkg.setModifyTimestamp(); + } + + return didChange; + } } =======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationService.java Sun Dec 7 09:15:14 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/AuthorizationService.java Wed Dec 31 10:32:57 2014 UTC
@@ -218,9 +218,12 @@ case BULK_PKGPROMINENCEANDUSERRATINGSPREADSHEETREPORT: case BULK_PKGICONSPREADSHEETREPORT: - case BULK_PKGCATEGORYCOVERAGESPREADSHEETREPORT: + case BULK_PKGCATEGORYCOVERAGEEXPORTSPREADSHEET: return null!=authenticatedUser; + case BULK_PKGCATEGORYCOVERAGEIMPORTSPREADSHEET:+ return null!=authenticatedUser && authenticatedUser.getIsRoot();
+ case BULK_USERRATINGSPREADSHEETREPORT_ALL:return null!=authenticatedUser && authenticatedUser.getIsRoot();
=======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/model/Permission.java Sun Dec 7 09:15:14 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/security/model/Permission.java Wed Dec 31 10:32:57 2014 UTC
@@ -33,7 +33,8 @@ PKG_EDITVERSIONLOCALIZATION(TargetType.PKG), PKG_EDITPROMINENCE(TargetType.PKG), - BULK_PKGCATEGORYCOVERAGESPREADSHEETREPORT(null), + BULK_PKGCATEGORYCOVERAGEEXPORTSPREADSHEET(null), + BULK_PKGCATEGORYCOVERAGEIMPORTSPREADSHEET(null), BULK_PKGPROMINENCEANDUSERRATINGSPREADSHEETREPORT(null), BULK_PKGICONSPREADSHEETREPORT(null), BULK_USERRATINGSPREADSHEETREPORT_PKG(TargetType.PKG), =======================================--- /haikudepotserver-webapp/src/main/resources/messages.properties Sun Dec 21 08:33:27 2014 UTC +++ /haikudepotserver-webapp/src/main/resources/messages.properties Wed Dec 31 10:32:57 2014 UTC
@@ -411,7 +411,7 @@ reporting.didreject.description=The report couldn't be enqueued; \ possibly because there is an equivalent report running already.-reporting.pkgcategorycoveragespreadsheetreport.title=Package category coverage report +reporting.pkgcategorycoverageexportspreadsheet.title=Package category coverage report reporting.pkgprominenceanduserratingspreadsheetreport.title=Package prominence and user rating report
reporting.pkgiconspreadsheetreport.title=Package icon report reporting.userratingspreadsheetreportall.title=Report of all user ratings @@ -424,7 +424,7 @@ job.jobtype.passwordresetmaintenance.title=Password Reset Maintenance job.jobtype.pkgrepositoryimport.title=Package Repository Importjob.jobtype.pkgprominenceanduserratingspreadsheet.title=Package Prominence and User Ratings Spreadsheet -job.jobtype.pkgcategorycoveragespreadsheet.title=Package Category Coverage Spreadsheet +job.jobtype.pkgcategorycoverageexportspreadsheet.title=Package Category Coverage Spreadsheet
job.jobtype.pkgiconspreadsheet.title=Package Icons Spreadsheet job.jobtype.userratingspreadsheet.title=User Rating Spreadsheet =======================================--- /haikudepotserver-webapp/src/main/resources/messages_de.properties Sun Dec 21 08:33:27 2014 UTC +++ /haikudepotserver-webapp/src/main/resources/messages_de.properties Wed Dec 31 10:32:57 2014 UTC
@@ -403,7 +403,7 @@ die entsprechende URL erzeugen, die dann mit einer Feed-Sammel-Software \ genutzt werden kann.-reporting.pkgcategorycoveragespreadsheetreport.title=Verteilung der Pakete nach Kategorien +reporting.pkgcategorycoverageexportspreadsheet.title=Verteilung der Pakete nach Kategorien reporting.pkgprominenceanduserratingspreadsheetreport.title=Empfehlungsstufen und Bewertungen der Pakete
reporting.pkgiconspreadsheetreport.title=Icons der Pakete reporting.userratingspreadsheetreportall.title=Alle Bewertungen @@ -412,7 +412,7 @@ job.jobtype.passwordresetmaintenance.title=Kennwort zurücksetzen job.jobtype.pkgrepositoryimport.title=Depots-Importjob.jobtype.pkgprominenceanduserratingspreadsheet.title=Tabelle der Empfehlungsstufen und Paket-Bewertungen -job.jobtype.pkgcategorycoveragespreadsheet.title=Tabelle der Verteilung der Pakete nach Kategorien +job.jobtype.pkgcategorycoverageexportspreadsheet.title=Tabelle der Verteilung der Pakete nach Kategorien
job.jobtype.pkgiconspreadsheet.title=Tabelle der Paket-Icons job.jobtype.userratingspreadsheet.title=Tabelle aller Bewertungen =======================================--- /haikudepotserver-webapp/src/main/webapp/js/app/constants.js Sun Dec 7 09:15:14 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/constants.js Wed Dec 31 10:32:57 2014 UTC
@@ -14,7 +14,7 @@ RECENT_DAYS : 90, - ARCHITECTURE_CODE_DEFAULT : 'x86', + ARCHITECTURE_CODE_DEFAULT : 'x86_gcc2', ENDPOINT_API_V1_REPOSITORY : '/api/v1/repository', ENDPOINT_API_V1_PKG : '/api/v1/pkg', =======================================--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/homecontroller.js Wed Sep 3 09:55:22 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/homecontroller.js Wed Dec 31 10:32:57 2014 UTC
@@ -173,6 +173,10 @@ if($location.search()[KEY_ARCHITECTURECODE]) {$scope.selectedArchitecture = _.findWhere(data,{ code : $location.search()[KEY_ARCHITECTURECODE] });
} + + if(!$scope.selectedArchitecture) {+ $scope.selectedArchitecture = _.findWhere(data,{ code : constants.ARCHITECTURE_CODE_DEFAULT });
+ } if(!$scope.selectedArchitecture) {$scope.selectedArchitecture = $scope.architectures[0];
=======================================--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/reports.html Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/reports.html Wed Dec 31 10:32:57 2014 UTC
@@ -7,9 +7,9 @@ <div class="content-container"> <ul>- <li show-if-permission="'BULK_PKGCATEGORYCOVERAGESPREADSHEETREPORT'">
- <a href="" ng-click="goPkgCategoryCoverageSpreadsheetReport()">- <message key="reporting.pkgcategorycoveragespreadsheetreport.title"></message> + <li show-if-permission="'BULK_PKGCATEGORYCOVERAGEEXPORTSPREADSHEET'">
+ <a href="" ng-click="goPkgCategoryCoverageExportSpreadsheet()">+ <message key="reporting.pkgcategorycoverageexportspreadsheet.title"></message>
</a> </li><li show-if-permission="'BULK_PKGPROMINENCEANDUSERRATINGSPREADSHEETREPORT'">
=======================================--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/reportscontroller.js Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/reportscontroller.js Wed Dec 31 10:32:57 2014 UTC
@@ -73,8 +73,8 @@ ); } - $scope.goPkgCategoryCoverageSpreadsheetReport = function() { - goBasicPkgReport('queuePkgCategoryCoverageSpreadsheetJob'); + $scope.goPkgCategoryCoverageExportSpreadsheet = function() {+ goBasicPkgReport('queuePkgCategoryCoverageExportSpreadsheetJob');
};$scope.goPkgProminenceAndUserRatingSpreadsheetReport = function() {
=======================================--- /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/AbstractIntegrationTest.java Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/AbstractIntegrationTest.java Wed Dec 31 10:32:57 2014 UTC
@@ -7,7 +7,8 @@ import com.google.common.base.Optional; import com.google.common.base.Preconditions; -import com.google.common.io.ByteStreams; +import com.google.common.io.ByteSource; +import junit.framework.Assert; import org.apache.cayenne.ObjectContext; import org.apache.cayenne.ObjectId; import org.apache.cayenne.configuration.server.ServerRuntime; @@ -24,6 +25,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import javax.annotation.Resource; +import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; @@ -31,6 +33,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.Map; +import java.util.Objects; /*** <p>This superclass of all of the tests has a hook to run before each integration test. The hook will
@@ -63,16 +66,39 @@ @Resource protected CapturingMailSender mailSender; - protected byte[] getResourceData(String path) throws IOException {+ protected void assertEqualsLineByLine(BufferedReader expected, BufferedReader actual) throws IOException {
+ String expectedLine; + String actualLine;- try (InputStream inputStream = this.getClass().getResourceAsStream(path)) {
+ do { + expectedLine = expected.readLine(); + actualLine = actual.readLine(); - if(null==inputStream) {- throw new IllegalStateException("unable to find the test resource; "+path);
+ if(!Objects.equals(expectedLine, actualLine)) {+ Assert.fail("mismatch expected and actual; [" + expectedLine + "] [" + actualLine + "]");
+ } + } + while(null!=expectedLine || null!=actualLine); + } + + protected ByteSource getResourceByteSource(final String path) { + return new ByteSource() { + @Override + public InputStream openStream() throws IOException {+ InputStream result = this.getClass().getResourceAsStream(path);
+ + if (null == result) {+ throw new IllegalStateException("unable to find the test resource; " + path);
+ } + + return result; + } + }; + } - return ByteStreams.toByteArray(inputStream); - } + protected byte[] getResourceData(String path) throws IOException { + return getResourceByteSource(path).read(); }private String getDatabaseName(Connection connection) throws SQLException {
=======================================--- /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/job/TestJobOrchestrationServiceImpl.java Sat Dec 20 09:47:27 2014 UTC +++ /haikudepotserver-webapp/src/test/java/org/haikuos/haikudepotserver/job/TestJobOrchestrationServiceImpl.java Wed Dec 31 10:32:57 2014 UTC
@@ -197,4 +197,10 @@public Optional<JobDataWithByteSource> tryObtainData(String guid) throws IOException {
return Optional.absent(); } + + @Override+ public void awaitJobConcludedUninterruptibly(String guid, long timeout) {
+ // ignore + } + } ============================================================================== Revision: 8f577ae37799 Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Fri Jan 2 10:56:12 2015 UTCLog: introduce a user interface for the package category coverage import process
https://code.google.com/p/haiku-depot-web-app/source/detail?r=8f577ae37799 Added:/haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageImportSpreadsheetJobRequest.java /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageImportSpreadsheetJobResult.java /haikudepotserver-webapp/src/main/webapp/js/app/controller/pkgcategorycoverageimportspreadsheet.html /haikudepotserver-webapp/src/main/webapp/js/app/controller/pkgcategorycoverageimportspreadsheetcontroller.js
/haikudepotserver-webapp/src/main/webapp/js/app/service/jobsservice.js Modified:/haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/PkgApi.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/LocalJobOrchestrationServiceImpl.java /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/controller/JobController.java
/haikudepotserver-webapp/src/main/resources/messages.properties/haikudepotserver-webapp/src/main/webapp/js/app/controller/rootoperations.html /haikudepotserver-webapp/src/main/webapp/js/app/controller/rootoperationscontroller.js
/haikudepotserver-webapp/src/main/webapp/js/app/routes.js/haikudepotserver-webapp/src/main/webapp/js/app/service/breadcrumbfactoryservice.js
/haikudepotserver-webapp/src/main/webapp/js/app/service/userstateservice.js ======================================= --- /dev/null+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageImportSpreadsheetJobRequest.java Fri Jan 2 10:56:12 2015 UTC
@@ -0,0 +1,12 @@ +/* + * Copyright 2015, Andrew Lindesay + * Distributed under the terms of the MIT License. + */ + +package org.haikuos.haikudepotserver.api1.model.pkg; + +public class QueuePkgCategoryCoverageImportSpreadsheetJobRequest { + + public String inputDataGuid; + +} ======================================= --- /dev/null+++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/model/pkg/QueuePkgCategoryCoverageImportSpreadsheetJobResult.java Fri Jan 2 10:56:12 2015 UTC
@@ -0,0 +1,19 @@ +/* + * Copyright 2015, Andrew Lindesay + * Distributed under the terms of the MIT License. + */ + +package org.haikuos.haikudepotserver.api1.model.pkg; + +public class QueuePkgCategoryCoverageImportSpreadsheetJobResult { + + public String guid; + + public QueuePkgCategoryCoverageImportSpreadsheetJobResult() { + } ++ public QueuePkgCategoryCoverageImportSpreadsheetJobResult(String guid) {
+ this.guid = guid; + } + +} ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/pkgcategorycoverageimportspreadsheet.html Fri Jan 2 10:56:12 2015 UTC
@@ -0,0 +1,29 @@ +<breadcrumbs></breadcrumbs> + +<div class="content-container"> + + <form name="specificationForm" novalidate="novalidate"> ++ <label for="import-data-file"><message key="pkgCategoryCoverageImportSpreadsheet.importDataFile.title"></message></label> + <div class="form-control-group" ng-class="deriveFormControlsContainerClasses('importDataFile')"> + <input id="import-data-file" name="importDataFile" type="file" ng-model="specification.importDataFile" file-supply required></input> + <error-messages key-prefix="pkgCategoryCoverageImportSpreadsheet.importDataFile" error="specificationForm.importDataFile.$error"></error-messages>
+ </div> + + <div class="form-action-container"> + <button + ng-disabled="specificationForm.$invalid" + ng-click="goQueue()" + type="submit" + class="main-action">+ <message key="pkgCategoryCoverageImportSpreadsheet.action.title"></message>
+ </button> + </div> + + </form> + +</div> + +<div class="footer"></div> +<spinner spin="shouldSpin()"></spinner> + ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/pkgcategorycoverageimportspreadsheetcontroller.js Fri Jan 2 10:56:12 2015 UTC
@@ -0,0 +1,103 @@ +/* + * Copyright 2015, Andrew Lindesay + * Distributed under the terms of the MIT License. + */ + +angular.module('haikudepotserver').controller( + 'PkgCategoryCoverageImportSpreadsheetController', + [ + '$scope','$log','$location','$routeParams', + 'jsonRpc','constants','pkgIcon','errorHandling', + 'breadcrumbs','breadcrumbFactory','pkg','jobs', + function( + $scope,$log,$location,$routeParams, + jsonRpc,constants,pkgIcon,errorHandling, + breadcrumbs,breadcrumbFactory,pkg,jobs) { + + var IMPORT_SIZE_LIMIT = 256 * 1024; // 100k + + $scope.specification = { + importDataFile : undefined + }; + + $scope.amQueueing = false; + + $scope.shouldSpin = function() { + return $scope.amQueueing; + }; + + $scope.deriveFormControlsContainerClasses = function(name) {+ return $scope.specificationForm[name].$invalid ? ['form-control-group-error'] : [];
+ }; + + function refreshBreadcrumbItems() { + breadcrumbs.mergeCompleteStack([ + breadcrumbFactory.createHome(), + breadcrumbFactory.createRootOperations(),+ breadcrumbFactory.createPkgCategoryCoverageImportSpreadsheet()
+ ]); + } + + refreshBreadcrumbItems(); ++ // This function will check to make sure that the file is not too large or too small to be a valid
+ // input for this importation process. + + function validateImportDataFile(file, model) {+ model.$setValidity('badsize',undefined==file || (file.size
24 && file.size < IMPORT_SIZE_LIMIT));
+ } + + function importDataFileDidChange() {+ validateImportDataFile($scope.specification.importDataFile, $scope.specificationForm['importDataFile']);
+ } + + $scope.$watch('specification.importDataFile', function() { + importDataFileDidChange(); + }); + ++ // This function will take the data from the form and load in the new pkg icons
+ + $scope.goQueue = function() { + + if($scope.specificationForm.$invalid) {+ throw Error('expected the import of package categories only to be possible if the form is valid');
+ } + + $scope.amQueueing = true; ++ // uploads the import data to the server so it can be used later.
+ + jobs.supplyData($scope.specification.importDataFile).then( + function(guid) {+ $log.info('did upload import data to the server; ' + guid);
+ + jsonRpc.call( + constants.ENDPOINT_API_V1_PKG, + "queuePkgCategoryCoverageImportSpreadsheetJob", + [{ inputDataGuid: guid }] + ).then( + function(result) {+ $log.info('did queue pkg category coverage import spreadsheet job; ' + result.guid); + breadcrumbs.pushAndNavigate(breadcrumbFactory.createViewJob({ guid:result.guid }));
+ $scope.amQueueing = false; + }, + function(err) { + $scope.amQueueing = false; + errorHandling.handleJsonRpcError(err); + } + ); + + }, + function() {+ $log.error('failed to upload import data to the server');
+ errorHandling.navigateToError(); + $scope.amQueueing = false; + } + ); + + }; // goQueue + + } + ] +); ======================================= --- /dev/null+++ /haikudepotserver-webapp/src/main/webapp/js/app/service/jobsservice.js Fri Jan 2 10:56:12 2015 UTC
@@ -0,0 +1,108 @@ +/* + * Copyright 2015, Andrew Lindesay + * Distributed under the terms of the MIT License. + */ + +/**+ * <p>This service provides functionality for accessing and updating job data.</p>
+ */ + +angular.module('haikudepotserver').factory('jobs', + [ + '$log','$q','$http', + function($log,$q,$http) { + + var errorCodes = { + BADREQUEST : 400, + UNKNOWN : -1 + }; + + var headers = {}; + + function setHeader(name, value) { + if(!name || !name.length) { + throw Error('the name of the http header is required'); + } + + if(!value || !value.length) { + delete headers[name]; + } + else { + headers[name] = value; + } + } + + /**+ * <p>Uploads the file so that it can be used as input for a job. It will return a GUID reference to the
+ * data if the upload was successful.</p> + */ + + function supplyData(file) { + + if(!file) {+ throw Error('the file must be supplied to provide data for the upload.');
+ } + + var deferred = $q.defer(); + + $http({ + cache: false, + method: 'POST', + url: '/secured/jobdata',+ headers: _.extend({ 'Content-Type' : 'application/octet-stream' },headers),
+ data: file + }) + .success(function(data,status,header,config) { + var code = header('X-HaikuDepotServer-DataGuid'); + + if(!code || !code.length) {+ throw Error('the data guid should have been supplied back from supplying data');
+ } + + deferred.resolve(code); + }) + .error(function(data,status) { + switch(status) { + case 200: + deferred.resolve(); + break; + + case 400: // bad request + deferred.reject(errorCodes.BADREQUEST); + break; + + default: + deferred.reject(errorCodes.UNKNOWN); + break; + + } + }); + + return deferred.promise; + + } + + return { ++ // these are errors that may be returned to the caller below. They match to the HTTP status codes
+ // used, but this should not be relied upon. + + errorCodes : errorCodes, + + setHeader : function(name, value) { + setHeader(name, value); + }, ++ // this function will upload the data from the supplied file to the server and will return a GUID + // that acts as a token to represent the data for subsequent API calls. The returned data is
+ // provided via a promise. + + supplyData : function(file) { + return supplyData(file); + } + + }; + + } + ] +); =======================================--- /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/PkgApi.java Wed Dec 31 10:32:57 2014 UTC +++ /haikudepotserver-api1/src/main/java/org/haikuos/haikudepotserver/api1/PkgApi.java Fri Jan 2 10:56:12 2015 UTC
@@ -1,5 +1,5 @@ /* - * Copyright 2013-2014, Andrew Lindesay + * Copyright 2013-2015, Andrew Lindesay * Distributed under the terms of the MIT License. */ @@ -147,6 +147,14 @@QueuePkgCategoryCoverageExportSpreadsheetJobResult queuePkgCategoryCoverageExportSpreadsheetJob(QueuePkgCategoryCoverageExportSpreadsheetJobRequest request);
+ /**+ * <P>Enqueues a request on behalf od the current user to import package data from a spreadsheet that is uploaded + * to the server. It does this and also produces an outbound spreadsheet of the result.</P> + * @throws org.haikuos.haikudepotserver.api1.support.ObjectNotFoundException in the case that the data identified by GUID does not exist.
+ */ ++ QueuePkgCategoryCoverageImportSpreadsheetJobResult queuePkgCategoryCoverageImportSpreadsheetJob(QueuePkgCategoryCoverageImportSpreadsheetJobRequest request) throws ObjectNotFoundException;
+ /*** <p>Enqueues a request on behalf of the current user to produce a spreadsheet showing which packages have icons * associated with them. See the {@link org.haikuos.haikudepotserver.api1.JobApi} for details on how to control the
=======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java Wed Dec 31 10:32:57 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/api1/PkgApiImpl.java Fri Jan 2 10:56:12 2015 UTC
@@ -1,5 +1,5 @@ /* - * Copyright 2013-2014, Andrew Lindesay + * Copyright 2013-2015, Andrew Lindesay * Distributed under the terms of the MIT License. */ @@ -28,6 +28,7 @@ import org.haikuos.haikudepotserver.dataobjects.PkgVersionLocalization; import org.haikuos.haikudepotserver.dataobjects.PkgVersionUrl; import org.haikuos.haikudepotserver.job.JobOrchestrationService; +import org.haikuos.haikudepotserver.job.model.JobData; import org.haikuos.haikudepotserver.pkg.PkgOrchestrationService; import org.haikuos.haikudepotserver.pkg.model.*; import org.haikuos.haikudepotserver.security.AuthorizationService; @@ -1154,7 +1155,7 @@ user.orNull(), null, Permission.BULK_PKGCATEGORYCOVERAGEEXPORTSPREADSHEET)) {- LOGGER.warn("attempt to access a bulk category coverage spreadsheet report, but was unauthorized"); + LOGGER.warn("attempt to access a package category coverage export spreadsheet, but was unauthorized");
throw new AuthorizationFailureException(); } @@ -1164,6 +1165,43 @@ return new QueuePkgCategoryCoverageExportSpreadsheetJobResult(jobOrchestrationService.submit(spec,JobOrchestrationService.CoalesceMode.QUEUEDANDSTARTED).orNull());
} + + @Override+ public QueuePkgCategoryCoverageImportSpreadsheetJobResult queuePkgCategoryCoverageImportSpreadsheetJob( + QueuePkgCategoryCoverageImportSpreadsheetJobRequest request) throws ObjectNotFoundException { + Preconditions.checkArgument(null!=request,"the request must be supplied"); + Preconditions.checkArgument(!Strings.isNullOrEmpty(request.inputDataGuid), "the input data must be identified by guid");
+ + final ObjectContext context = serverRuntime.getContext(); + + Optional<User> user = tryObtainAuthenticatedUser(context); + + if(!authorizationService.check( + context, + user.orNull(), + null, + Permission.BULK_PKGCATEGORYCOVERAGEIMPORTSPREADSHEET)) {+ LOGGER.warn("attempt to import package categories, but was not authorized");
+ throw new AuthorizationFailureException(); + } + + // now check that the data is present. ++ Optional<JobData> dataOptional = jobOrchestrationService.tryGetData(request.inputDataGuid);
+ + if(!dataOptional.isPresent()) {+ throw new ObjectNotFoundException(JobData.class.getSimpleName(), request.inputDataGuid);
+ } + + // setup and go ++ PkgCategoryCoverageImportSpreadsheetJobSpecification spec = new PkgCategoryCoverageImportSpreadsheetJobSpecification();
+ spec.setOwnerUserNickname(user.get().getNickname()); + spec.setInputDataGuid(request.inputDataGuid); + + return new QueuePkgCategoryCoverageImportSpreadsheetJobResult(+ jobOrchestrationService.submit(spec, JobOrchestrationService.CoalesceMode.NONE).orNull());
+ } @Overridepublic QueuePkgIconSpreadsheetJobResult queuePkgIconSpreadsheetJob(QueuePkgIconSpreadsheetJobRequest request) {
=======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/LocalJobOrchestrationServiceImpl.java Wed Dec 31 10:32:57 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/LocalJobOrchestrationServiceImpl.java Fri Jan 2 10:56:12 2015 UTC
@@ -776,6 +776,9 @@ long len; try(InputStream inputStream = byteSource.openStream()) { + + // TODO; constrain this to a sensible size + len = dataStorageService.put(guid).writeFrom(inputStream);data = new JobData(guid, JobDataType.SUPPLIED, useCode, mediaTypeCode);
=======================================--- /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/controller/JobController.java Wed Dec 31 10:32:57 2014 UTC +++ /haikudepotserver-webapp/src/main/java/org/haikuos/haikudepotserver/job/controller/JobController.java Fri Jan 2 10:56:12 2015 UTC
@@ -1,5 +1,5 @@ /* - * Copyright 2014, Andrew Lindesay + * Copyright 2014-2015, Andrew Lindesay * Distributed under the terms of the MIT License. */ @@ -43,6 +43,10 @@ @RequestMapping("/secured") public class JobController extends AbstractController {+ private final static long MAX_SUPPLY_DATA_LENGTH = 1 * 1024 * 1024; // 1MB
++ public final static String HEADER_DATAGUID = "X-HaikuDepotServer-DataGuid";
+protected static Logger LOGGER = LoggerFactory.getLogger(JobController.class);
public final static String KEY_GUID = "guid"; @@ -65,14 +69,30 @@ @RequestMapping(value = "/jobdata", method = RequestMethod.POST) @ResponseBody - public String supplyData( + public void supplyData( final HttpServletRequest request, + final HttpServletResponse response,@RequestHeader(value = HttpHeaders.CONTENT_TYPE, required = false) String contentType, @RequestParam(value = KEY_USECODE, required = false) String useCode)
throws IOException { Preconditions.checkArgument(null!=request); assert null!=request; + + int length = request.getContentLength(); + + if(-1 != length && length > MAX_SUPPLY_DATA_LENGTH) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + } + + ObjectContext context = serverRuntime.getContext(); + + Optional<User> user = tryObtainAuthenticatedUser(context); + + if(!user.isPresent()) {+ LOGGER.warn("attempt to supply job data with no authenticated user");
+ throw new JobDataAuthorizationFailure(); + } JobData data = jobOrchestrationService.storeSuppliedData( useCode, @@ -85,7 +105,8 @@ } ); - return data.getGuid(); + response.setStatus(HttpServletResponse.SC_OK); + response.setHeader(HEADER_DATAGUID, data.getGuid()); } /** =======================================--- /haikudepotserver-webapp/src/main/resources/messages.properties Wed Dec 31 10:32:57 2014 UTC +++ /haikudepotserver-webapp/src/main/resources/messages.properties Fri Jan 2 10:56:12 2015 UTC
@@ -54,6 +54,7 @@ breadcrumb.reports.title=Reports breadcrumb.listJobs.title=List Jobs breadcrumb.viewJob.title=View Job +breadcrumb.pkgCategoryCoverageImportSpreadsheet.title=Import Pkg Categories about.info.title=Information about.info.version=Version {0} @@ -346,6 +347,11 @@exists. It may be that the exact same rule was already present or it may be that a less \
specific rule already existed. +pkgCategoryCoverageImportSpreadsheet.importDataFile.title=Import Data+pkgCategoryCoverageImportSpreadsheet.importDataFile.required=The import data is required to import from.
+pkgCategoryCoverageImportSpreadsheet.action.title=Import + + banner.action.more=About 'Haiku Depot Server' banner.action.authenticate=User login banner.action.createUser=Register new user =======================================--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/rootoperations.html Tue Dec 9 09:53:59 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/rootoperations.html Fri Jan 2 10:56:12 2015 UTC
@@ -28,6 +28,7 @@<li><a href="" ng-click="goPaginationControlPlayground()">Pagination playground</a></li> <li><a href="" ng-click="goRaiseExceptionInLocalRuntime()">Raise test exception in javascript environment</a></li> <li><a href="" ng-click="goRaiseExceptionInServerRuntime()">Raise test exception on server via json-rpc</a></li> + <li><a href="" ng-click="goPkgCategoryCoverageImportSpreadsheet()">Import package categories</a></li>
<li><a href="" ng-click="goJobs()">List jobs</a></li> </ul> =======================================--- /haikudepotserver-webapp/src/main/webapp/js/app/controller/rootoperationscontroller.js Sun Dec 7 09:15:14 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/controller/rootoperationscontroller.js Fri Jan 2 10:56:12 2015 UTC
@@ -1,5 +1,5 @@ /* - * Copyright 2014, Andrew Lindesay + * Copyright 2014-2015, Andrew Lindesay * Distributed under the terms of the MIT License. */ @@ -94,6 +94,10 @@breadcrumbs.pushAndNavigate(breadcrumbFactory.createListJobs());
}; + $scope.goPkgCategoryCoverageImportSpreadsheet = function() {+ breadcrumbs.pushAndNavigate(breadcrumbFactory.createPkgCategoryCoverageImportSpreadsheet());
+ }; + // ------------------- // TEST ERROR HANDLING TESTING =======================================--- /haikudepotserver-webapp/src/main/webapp/js/app/routes.js Tue Dec 9 09:49:00 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/routes.js Fri Jan 2 10:56:12 2015 UTC
@@ -1,5 +1,5 @@ /* - * Copyright 2013-2014, Andrew Lindesay + * Copyright 2013-2015, Andrew Lindesay * Distributed under the terms of the MIT License. */ @@ -13,6 +13,7 @@ $routeProvider .when('/rootoperations',{controller:'RootOperationsController',templateUrl:'/js/app/controller/rootoperations.html'}) .when('/jobs',{controller:'ListJobsController',templateUrl:'/js/app/controller/listjobs.html'}) + .when('/pkgcategorycoverageimportspreadsheet',{controller:'PkgCategoryCoverageImportSpreadsheetController',templateUrl:'/js/app/controller/pkgcategorycoverageimportspreadsheet.html'}) .when('/job/:guid',{controller:'ViewJobController',templateUrl:'/js/app/controller/viewjob.html'}) .when('/reports',{controller:'ReportsController',templateUrl:'/js/app/controller/reports.html'}) .when('/pkg/feed/builder',{controller:'PkgFeedBuilderController',templateUrl:'/js/app/controller/pkgfeedbuilder.html'}) =======================================--- /haikudepotserver-webapp/src/main/webapp/js/app/service/breadcrumbfactoryservice.js Tue Dec 9 09:49:00 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/service/breadcrumbfactoryservice.js Fri Jan 2 10:56:12 2015 UTC
@@ -1,5 +1,5 @@ /* - * Copyright 2014, Andrew Lindesay + * Copyright 2014-2015, Andrew Lindesay * Distributed under the terms of the MIT License. */ @@ -429,6 +429,13 @@ return applyDefaults({ titleKey : 'breadcrumb.viewJob.title', path : '/job/' + job.guid + }); + }, + + createPkgCategoryCoverageImportSpreadsheet : function() { + return applyDefaults({+ titleKey : 'breadcrumb.pkgCategoryCoverageImportSpreadsheet.title',
+ path : '/pkgcategorycoverageimportspreadsheet' }); } =======================================--- /haikudepotserver-webapp/src/main/webapp/js/app/service/userstateservice.js Sun Jul 27 10:55:51 2014 UTC +++ /haikudepotserver-webapp/src/main/webapp/js/app/service/userstateservice.js Fri Jan 2 10:56:12 2015 UTC
@@ -1,5 +1,5 @@ /* - * Copyright 2013-2014, Andrew Lindesay + * Copyright 2013-2015, Andrew Lindesay * Distributed under the terms of the MIT License. */ @@ -15,11 +15,11 @@ [ '$log','$q','$rootScope','$timeout','$window', 'jsonRpc','pkgScreenshot','errorHandling', - 'constants','referenceData', + 'constants','referenceData','jobs', function( $log,$q,$rootScope,$timeout,$window, jsonRpc,pkgScreenshot,errorHandling, - constants,referenceData) { + constants,referenceData,jobs) { var SIZE_CHECKED_PERMISSION_CACHE = 25; var SAMPLESIZE_TIMESTAMPS_OF_LAST_TOKEN_RENEWALS = 10; @@ -61,6 +61,7 @@jsonRpc.setHeader('Authorization', authenticationContent); pkgScreenshot.setHeader('Authorization', authenticationContent); + jobs.setHeader('Authorization', authenticationContent);
} else {$log.info('cannot set the token because the user state is not compatible with the token');
============================================================================== Revision: ddd7d05babcd Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Sat Jan 3 09:08:22 2015 UTC Log: german translations for pkg category import process https://code.google.com/p/haiku-depot-web-app/source/detail?r=ddd7d05babcd Modified: /haikudepotserver-webapp/src/main/resources/messages_de.properties =======================================--- /haikudepotserver-webapp/src/main/resources/messages_de.properties Wed Dec 31 10:32:57 2014 UTC +++ /haikudepotserver-webapp/src/main/resources/messages_de.properties Sat Jan 3 09:08:22 2015 UTC
@@ -52,6 +52,7 @@ breadcrumb.reports.title=Berichte breadcrumb.listJobs.title=Aufträge auflisten breadcrumb.viewJob.title=Auftrag+breadcrumb.pkgCategoryCoverageImportSpreadsheet.title=Paket-Kategorien importieren
about.info.title=Information about.info.version=Version {0} @@ -403,6 +404,10 @@ die entsprechende URL erzeugen, die dann mit einer Feed-Sammel-Software \ genutzt werden kann. +pkgCategoryCoverageImportSpreadsheet.importDataFile.title=Datei+pkgCategoryCoverageImportSpreadsheet.importDataFile.required=Für den Import wird eine Datei benötigt.
+pkgCategoryCoverageImportSpreadsheet.action.title=Importieren +reporting.pkgcategorycoverageexportspreadsheet.title=Verteilung der Pakete nach Kategorien reporting.pkgprominenceanduserratingspreadsheetreport.title=Empfehlungsstufen und Bewertungen der Pakete
reporting.pkgiconspreadsheetreport.title=Icons der Pakete ============================================================================== Revision: a02e6acf3bf4 Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Sat Jan 3 09:24:53 2015 UTC Log: localization correction https://code.google.com/p/haiku-depot-web-app/source/detail?r=a02e6acf3bf4 Modified: /haikudepotserver-webapp/src/main/resources/messages.properties /haikudepotserver-webapp/src/main/resources/messages_de.properties =======================================--- /haikudepotserver-webapp/src/main/resources/messages.properties Fri Jan 2 10:56:12 2015 UTC +++ /haikudepotserver-webapp/src/main/resources/messages.properties Sat Jan 3 09:24:53 2015 UTC
@@ -431,6 +431,7 @@ job.jobtype.pkgrepositoryimport.title=Package Repository Importjob.jobtype.pkgprominenceanduserratingspreadsheet.title=Package Prominence and User Ratings Spreadsheet job.jobtype.pkgcategorycoverageexportspreadsheet.title=Package Category Coverage Spreadsheet +job.jobtype.pkgcategorycoverageimportspreadsheet.title=Package Category Coverage Spreadsheet Import
job.jobtype.pkgiconspreadsheet.title=Package Icons Spreadsheet job.jobtype.userratingspreadsheet.title=User Rating Spreadsheet =======================================--- /haikudepotserver-webapp/src/main/resources/messages_de.properties Sat Jan 3 09:08:22 2015 UTC +++ /haikudepotserver-webapp/src/main/resources/messages_de.properties Sat Jan 3 09:24:53 2015 UTC
@@ -418,6 +418,7 @@ job.jobtype.pkgrepositoryimport.title=Depots-Importjob.jobtype.pkgprominenceanduserratingspreadsheet.title=Tabelle der Empfehlungsstufen und Paket-Bewertungen job.jobtype.pkgcategorycoverageexportspreadsheet.title=Tabelle der Verteilung der Pakete nach Kategorien +job.jobtype.pkgcategorycoverageimportspreadsheet.title=Paket-Kategorien importieren
job.jobtype.pkgiconspreadsheet.title=Tabelle der Paket-Icons job.jobtype.userratingspreadsheet.title=Tabelle aller Bewertungen ============================================================================== Revision: 9aec7bcde339 Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Sat Jan 3 09:29:51 2015 UTC Log: version 1.0.14 https://code.google.com/p/haiku-depot-web-app/source/detail?r=9aec7bcde339 Modified: /haikudepotserver-api1/pom.xml /haikudepotserver-docs/pom.xml /haikudepotserver-packagefile/pom.xml /haikudepotserver-parent/pom.xml /haikudepotserver-rpm-common/pom.xml /haikudepotserver-rpm-parent/pom.xml /haikudepotserver-rpm-production/pom.xml /haikudepotserver-rpm-test/pom.xml /haikudepotserver-webapp/pom.xml /pom.xml ======================================= --- /haikudepotserver-api1/pom.xml Sun Dec 21 09:33:53 2014 UTC +++ /haikudepotserver-api1/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14-SNAPSHOT</version> + <version>1.0.14</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-docs/pom.xml Sun Dec 21 09:33:53 2014 UTC +++ /haikudepotserver-docs/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14-SNAPSHOT</version> + <version>1.0.14</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-packagefile/pom.xml Sun Dec 21 09:33:53 2014 UTC +++ /haikudepotserver-packagefile/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14-SNAPSHOT</version> + <version>1.0.14</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-parent/pom.xml Sun Dec 21 09:33:53 2014 UTC +++ /haikudepotserver-parent/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <groupId>org.haikuos</groupId> <artifactId>haikudepotserver-parent</artifactId> <packaging>pom</packaging> - <version>1.0.14-SNAPSHOT</version> + <version>1.0.14</version> <licenses> <license> ======================================= --- /haikudepotserver-rpm-common/pom.xml Sun Dec 21 09:33:53 2014 UTC +++ /haikudepotserver-rpm-common/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14-SNAPSHOT</version> + <version>1.0.14</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-rpm-parent/pom.xml Sun Dec 21 09:33:53 2014 UTC +++ /haikudepotserver-rpm-parent/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14-SNAPSHOT</version> + <version>1.0.14</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-rpm-production/pom.xml Sun Dec 21 09:33:53 2014 UTC +++ /haikudepotserver-rpm-production/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-rpm-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-rpm-parent</relativePath> - <version>1.0.14-SNAPSHOT</version> + <version>1.0.14</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-rpm-test/pom.xml Sun Dec 21 09:33:53 2014 UTC +++ /haikudepotserver-rpm-test/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-rpm-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-rpm-parent</relativePath> - <version>1.0.14-SNAPSHOT</version> + <version>1.0.14</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-webapp/pom.xml Sun Dec 21 09:33:53 2014 UTC +++ /haikudepotserver-webapp/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14-SNAPSHOT</version> + <version>1.0.14</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /pom.xml Sun Dec 21 09:33:53 2014 UTC +++ /pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <groupId>org.haikuos</groupId> <artifactId>haikudepotserver</artifactId> <packaging>pom</packaging> - <version>1.0.14-SNAPSHOT</version> + <version>1.0.14</version> <modules> <module>haikudepotserver-api1</module> ============================================================================== Revision: c9115c719b9d Author: Andrew Lindesay <apl@xxxxxxxxxxxxxx> Date: Sat Jan 3 09:29:51 2015 UTC Log: version 1.0.15-SNAPSHOT https://code.google.com/p/haiku-depot-web-app/source/detail?r=c9115c719b9d Modified: /haikudepotserver-api1/pom.xml /haikudepotserver-docs/pom.xml /haikudepotserver-packagefile/pom.xml /haikudepotserver-parent/pom.xml /haikudepotserver-rpm-common/pom.xml /haikudepotserver-rpm-parent/pom.xml /haikudepotserver-rpm-production/pom.xml /haikudepotserver-rpm-test/pom.xml /haikudepotserver-webapp/pom.xml /pom.xml ======================================= --- /haikudepotserver-api1/pom.xml Sat Jan 3 09:29:51 2015 UTC +++ /haikudepotserver-api1/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14</version> + <version>1.0.15-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-docs/pom.xml Sat Jan 3 09:29:51 2015 UTC +++ /haikudepotserver-docs/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14</version> + <version>1.0.15-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-packagefile/pom.xml Sat Jan 3 09:29:51 2015 UTC +++ /haikudepotserver-packagefile/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14</version> + <version>1.0.15-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-parent/pom.xml Sat Jan 3 09:29:51 2015 UTC +++ /haikudepotserver-parent/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <groupId>org.haikuos</groupId> <artifactId>haikudepotserver-parent</artifactId> <packaging>pom</packaging> - <version>1.0.14</version> + <version>1.0.15-SNAPSHOT</version> <licenses> <license> ======================================= --- /haikudepotserver-rpm-common/pom.xml Sat Jan 3 09:29:51 2015 UTC +++ /haikudepotserver-rpm-common/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14</version> + <version>1.0.15-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-rpm-parent/pom.xml Sat Jan 3 09:29:51 2015 UTC +++ /haikudepotserver-rpm-parent/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14</version> + <version>1.0.15-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-rpm-production/pom.xml Sat Jan 3 09:29:51 2015 UTC +++ /haikudepotserver-rpm-production/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-rpm-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-rpm-parent</relativePath> - <version>1.0.14</version> + <version>1.0.15-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-rpm-test/pom.xml Sat Jan 3 09:29:51 2015 UTC +++ /haikudepotserver-rpm-test/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-rpm-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-rpm-parent</relativePath> - <version>1.0.14</version> + <version>1.0.15-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /haikudepotserver-webapp/pom.xml Sat Jan 3 09:29:51 2015 UTC +++ /haikudepotserver-webapp/pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <artifactId>haikudepotserver-parent</artifactId> <groupId>org.haikuos</groupId> <relativePath>../haikudepotserver-parent</relativePath> - <version>1.0.14</version> + <version>1.0.15-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> ======================================= --- /pom.xml Sat Jan 3 09:29:51 2015 UTC +++ /pom.xml Sat Jan 3 09:29:51 2015 UTC @@ -5,7 +5,7 @@ <groupId>org.haikuos</groupId> <artifactId>haikudepotserver</artifactId> <packaging>pom</packaging> - <version>1.0.14</version> + <version>1.0.15-SNAPSHOT</version> <modules> <module>haikudepotserver-api1</module>