From f73d2bbfc84a55f1837aab4e751bec3c616b285a Mon Sep 17 00:00:00 2001 From: Michael Ritter Date: Thu, 19 Mar 2026 03:05:39 -0600 Subject: [PATCH 01/12] Update for 8.3.0 (#345) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 516e2c307..21cc16b55 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ Root - 8.3.0-RC.3 + 8.3.0 ${revision} ${basedir}/tmp csmake From 0d22b0d9974ab6c33bbf0c66b7b6a09cfa1a41f0 Mon Sep 17 00:00:00 2001 From: Michael Ritter Date: Tue, 24 Mar 2026 11:00:57 -0600 Subject: [PATCH 02/12] Bump 9.0.0-SNAPSHOT (#347) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 21cc16b55..53c6597c3 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ Root - 8.3.0 + 9.0.0-SNAPSHOT ${revision} ${basedir}/tmp csmake From fd311461c33774e95c6f1833ead7e5de72ea4a85 Mon Sep 17 00:00:00 2001 From: Michael Ritter Date: Fri, 29 May 2026 12:51:20 -0600 Subject: [PATCH 03/12] DRYD-1633: Update to Java 17 (#348) (#350) * Update compile target to JDK 17 * Remove references to internal APIs * Remove unused war module --- .../webui/userdetails/UserDetailsReset.java | 3 +- pom.xml | 16 +- .../csp/persistence/file/TestGeneral.java | 371 ------------------ war-entry/build.xml | 45 --- war-entry/pom.xml | 169 -------- war-entry/src/main/java/README.txt | 0 .../src/main/resources/META-INF/MANIFEST.MF | 5 - .../src/main/webapp/META-INF/context.xml | 4 - war-entry/src/main/webapp/WEB-INF/web.xml | 62 --- 9 files changed, 4 insertions(+), 671 deletions(-) delete mode 100644 tomcat-main/src/test/java/org/collectionspace/chain/csp/persistence/file/TestGeneral.java delete mode 100644 war-entry/build.xml delete mode 100644 war-entry/pom.xml delete mode 100644 war-entry/src/main/java/README.txt delete mode 100644 war-entry/src/main/resources/META-INF/MANIFEST.MF delete mode 100644 war-entry/src/main/webapp/META-INF/context.xml delete mode 100644 war-entry/src/main/webapp/WEB-INF/web.xml diff --git a/cspi-webui/src/main/java/org/collectionspace/chain/csp/webui/userdetails/UserDetailsReset.java b/cspi-webui/src/main/java/org/collectionspace/chain/csp/webui/userdetails/UserDetailsReset.java index 670b8484d..dadae9aaa 100644 --- a/cspi-webui/src/main/java/org/collectionspace/chain/csp/webui/userdetails/UserDetailsReset.java +++ b/cspi-webui/src/main/java/org/collectionspace/chain/csp/webui/userdetails/UserDetailsReset.java @@ -93,7 +93,6 @@ private Boolean doEmail(String csid, String emailparam, Request in, JSONObject u else{ recipients[0] = ed.getToAddress(); } - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); boolean debug = false; Properties props = new Properties(); @@ -491,4 +490,4 @@ public void run(Object in, String[] tail) throws UIException { public void configure() throws ConfigException {} public void configure(WebUI ui,Spec spec) {} -} \ No newline at end of file +} diff --git a/pom.xml b/pom.xml index 53c6597c3..f49616a8d 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ 9.0.0-SNAPSHOT ${revision} + 17 ${basedir}/tmp csmake UTF-8 @@ -45,7 +46,6 @@ cspi-installation tomcat-main - war-entry @@ -230,19 +230,9 @@ org.apache.maven.plugins maven-compiler-plugin - 3.1 + 3.15.0 - 1.7 - 1.7 - true - - - - org.mortbay.jetty - maven-jetty-plugin - 6.1.26 - - chain + ${java.version} diff --git a/tomcat-main/src/test/java/org/collectionspace/chain/csp/persistence/file/TestGeneral.java b/tomcat-main/src/test/java/org/collectionspace/chain/csp/persistence/file/TestGeneral.java deleted file mode 100644 index 498f55838..000000000 --- a/tomcat-main/src/test/java/org/collectionspace/chain/csp/persistence/file/TestGeneral.java +++ /dev/null @@ -1,371 +0,0 @@ -/* Copyright 2010 University of Cambridge - * Licensed under the Educational Community License (ECL), Version 2.0. You may not use this file except in - * compliance with this License. - * - * You may obtain a copy of the ECL 2.0 License at https://source.collectionspace.org/collection-space/LICENSE.txt - */ -package org.collectionspace.chain.csp.persistence.file; - -import static org.junit.Assert.*; - -import java.util.Date; -import java.util.HashSet; -import java.util.Properties; -import java.util.Set; - -import java.security.Security; - -import javax.mail.Message; -import javax.mail.MessagingException; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.internet.AddressException; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; - -import org.collectionspace.chain.csp.persistence.TestBase; -import org.collectionspace.chain.csp.webui.userdetails.UserDetailsReset; -import org.json.JSONArray; -import org.json.JSONObject; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.mortbay.jetty.testing.HttpTester; -import org.mortbay.jetty.testing.ServletTester; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This provides general tests for the WebAPP that are not covered with the more specific tests such as TestNameThroughWebapp - * @author - * - */ -public class TestGeneral { - private static final Logger log=LoggerFactory.getLogger(TestGeneral.class); - private static TestBase tester = new TestBase(); - static ServletTester jetty; - static { - try{ - jetty=tester.setupJetty(); - } - catch(Exception ex){ - log.error("TestGeneral: Could not set up jetty! " + ex.getLocalizedMessage()); - } - } - - @BeforeClass public static void testInitialise() throws Exception { - HttpTester out = tester.GETData(TestBase.AUTHS_INIT_PATH, jetty); - log.info(out.getContent()); - } - - @AfterClass public static void testStop() throws Exception { - tester.stopJetty(jetty); - } - - - private final static String testStr2 = "{\"accessionNumber\":\"OBJNUM\",\"description\":\"DESCRIPTION\",\"descInscriptionInscriber\":\"INSCRIBER\",\"objectNumber\":\"1\",\"objectTitle\":\"TITLE\",\"comments\":\"COMMENTS\",\"distinguishingFeatures\":\"DISTFEATURES\",\"responsibleDepartment\":\"DEPT\",\"objectName\":\"OBJNAME\"}"; - private final static Date d = new Date(); - private final static String urnTestJoe = "{\"fields\":{\"responsibleDepartment\":\"\",\"dimensionMeasurementUnit\":\"\",\"objectNumber\":\"TestObject\",\"title\":\"Test Title for urn test object\",\"objectName\":\"Test Object for urn test object\",\"inscriptionContentInscriber\":\"urn:cspace:org.collectionspace.demo:personauthority:id(de0d959d-2923-4123-830d):person:id(8a6bf9d8-6dc4-4c78-84e9)'Joe+Adamson'\"},\"csid\":\"\"}"; - - - //@Test - public void test2() throws Exception{ - - JSONObject user = new JSONObject(); - user.put("userid", "admin@testsci.collectionspace.org"); - user.put("password", "Administrator"); - - //ServletTester jetty=setupJetty("testsci", user); - //ServletTester jetty=setupJetty(false,"tenant2.xml"); - // http://nightly.collectionspace.org/collectionspace/tenant/core/invokereport/88b3bdb5-a7fd-4e39-aaa1 - // String csid = "/reporting/search?doctype=Acquisition"; - //uispec(jetty,"/generator?quantity=10&maxrelationships=10&startvalue=0&extraprefix=Related","acquisition.uispec"); - // String csid = "/generator?quantity=10&maxrelationships=10&startvalue=0&extraprefix=Related"; - // String csid = "/cataloging/termList/dateEarliestSingleEra"; -// String csid = "/role/08a84ce3-9236-468b-b8c2-66d07706b273"; - String csid = TestBase.MAIN_PERSON_INSTANCE_PATH; - //http://nightly.collectionspace.org/collectionspace/chain/vocabularies/location/source-vocab/relatedTerm -// String test = "{\"fields\":{\"lenderGroup\":[{\"_primary\":true}],\"loanPurposes\":[{\"loanPurpose\":\"\",\"_primary\":true}],\"updatedBys\":[{\"_primary\":true}],\"loanInNumbers\":[{\"_primary\":true}],\"updatedAtStart\":\"2011-09-05\"},\"operation\":\"or\"}"; - String test = "{\"termsUsed\":[],\"relations\":[],\"csid\":\"\",\"refobjs\":[],\"namespace\":\"person\"," + - "\"fields\":{\"surName\":\"\",\"birthPlace\":\"\",\"deathDate\":\"\",\"updatedBy\":\"admin@core.collectionspace.org\"," + - "\"nationalities\":[{\"_primary\":true,\"nationality\":\"\"}],\"shortIdentifier\":\"bobclampett\"," + - "\"schoolsOrStyles\":[{\"_primary\":true,\"schoolOrStyle\":\"\"}],\"title\":\"\",\"initials\":\"\"," + - "\"createdAt\":\"2011-10-10T13:46:44Z\",\"nameNote\":\"save something\",\"termStatus\":\"\",\"gender\":\"\",\"birthDate\":\"\",\"foreName\":\"\"," + - "\"groups\":[{\"_primary\":true,\"group\":\"\"}],\"recordtype\":\"person\",\"nameAdditions\":\"\"," + - "\"occupations\":[{\"occupation\":\"\",\"_primary\":true}],\"middleName\":\"\",\"bioNote\":\"\"," + - "\"csid\":\"79a356bd-17ab-47cf-8174\",\"deathPlace\":\"\",\"updatedAt\":\"2011-10-10T14:20:28Z\"," + - "\"createdBy\":\"admin@core.collectionspace.org\",\"equivalentContexts\":[],\"authorityid\":\"34d85e61-7d0f-4b37-a6c4\"," + - "\"displayName\":\"Bob Clampett\",\"salutation\":\"\"," + - "\"refid\":\"urn:cspace:core.collectionspace.org:personauthorities:name(person):item:name(bobclampett)'Bob Clampett'\"," + - "\"telephoneNumberGroup\":[{\"_primary\":true,\"telephoneNumberType\":\"\"}],\"emailGroup\":[{\"emailType\":\"\",\"_primary\":true}]," + - "\"faxNumberGroup\":[{\"_primary\":true,\"faxNumberType\":\"\"}],\"webAddressGroup\":[{\"_primary\":true,\"webAddressType\":\"\"}]," + - "\"addressGroup\":[{\"_primary\":true,\"addressType\":\"\"}]," + - "\"narrowerContexts\":[{\"_primary\":true,\"narrowerContext\":\"urn:cspace:core.collectionspace.org:personauthorities:name(person):item:name(tommix)'Tom Mix'\"}]," + - "\"relatedTerms\":[{\"_primary\":true}]," + - "\"broaderContext\":\"urn:cspace:core.collectionspace.org:personauthorities:name(person):item:name(georgebancroft)'George Bancroft'\"}}"; - HttpTester out; - //loanedObjectStatus - - //out = jettyDo(jetty, "GET", "/tenant/testsci/authorities/vocab/initialize", null); - - //out = jettyDo(jetty, "GET", "/tenant/testsci/cataloging/uispec", null); - - //out = GETData(csid, jetty); - out = tester.POSTData(csid, test, jetty); - -// DELETEData("/users/c990a163-ef62-4f06-95ae-c362d3fac9ff",jetty); - //JSONObject fields=new JSONObject(out.getContent()).getJSONObject("fields"); - //cspace-services/personauthorities/5c642112-f75a-43b4-aff8/items/0e07e795-fb9d-4f39-a848/ - //HttpTester out2=jettyDo(jetty,"POST","/chain/upload",null); - // - log.info(out.getContent()); - - } - - - - /* XXX I don't think this is tetsing what it needs to */ - /** - * Writes a series of Objects then does a Read using a trailing slash - * and checks each object is found - */ - @Test public void testTrailingSlashOkayOnList() throws Exception { - - // clear (avoid paging) - JSONArray items=null; - - - HttpTester out1 = tester.POSTData("/cataloging",tester.makeSimpleRequest(testStr2),jetty); - HttpTester out2 = tester.POSTData("/cataloging",tester.makeSimpleRequest(testStr2),jetty); - HttpTester out3 = tester.POSTData("/cataloging",tester.makeSimpleRequest(testStr2),jetty); - // Read with a trailing slash - HttpTester out = tester.GETData("/cataloging/",jetty); - - // Build up a list of items returned - JSONObject result=new JSONObject(out.getContent()); - items=result.getJSONArray("items"); - Set files=new HashSet(); - - int pgSz = 100; - int pgNum = 0; - String objtype = "cataloging"; - String itemmarker = "items"; - boolean exists = false; - boolean end = false; - // Page through - do { - out = tester.GETData("/" + objtype + "/?pageNum=" + pgNum + "&pageSize=" + pgSz, jetty); - assertEquals(200, out.getStatus()); - - /* create list of files */ - - JSONObject result1 = new JSONObject(out.getContent()); - JSONArray items1 = result1.getJSONArray(itemmarker); - if (items1.length() > 0) { - for (int i = 0; i < items1.length(); i++) { - files.add("/" + objtype + "/" - + items1.getJSONObject(i).getString("csid")); - } - } else { - end = true; - } - - exists = files.contains(out1.getHeader("Location")) && files.contains(out2.getHeader("Location")) && files.contains(out3.getHeader("Location")); - pgNum++; - } while (!end && !exists); - /* clean up */ - tester.DELETEData(out1.getHeader("Location"),jetty); - tester.DELETEData(out2.getHeader("Location"),jetty); - tester.DELETEData(out3.getHeader("Location"),jetty); - - // Check each object is in the list - assertTrue(files.contains(out1.getHeader("Location"))); - assertTrue(files.contains(out2.getHeader("Location"))); - assertTrue(files.contains(out3.getHeader("Location"))); - - } - - - /** - * Sets up and sends email message providing you have set up the email address to send to - */ - @Test public void testEmail(){ - Boolean doIreallyWantToSpam = false; // set to true when you have configured the email addresses - /* please personalises these emails before sending - I don't want your spam. */ - String from = "admin@collectionspace.org"; - String[] recipients = {""}; - - String SMTP_HOST_NAME = "localhost"; - String SMTP_PORT = "25"; - String message = "Hi, Test Message Contents"; - String subject = "A test from collectionspace test suite"; - String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); //REM - Replace. This is pre-JDK 1.4 code, from the days when JSSE was a separate download. Fix the imports so they refer to the classes in javax.net.ssl If you really want to get hold of a specific instance, you can use Security.getProvider(name). You'll find the appropriate names in the providers documentation. - boolean debug = true; - - Properties props = new Properties(); - props.put("mail.smtp.host", SMTP_HOST_NAME); - //props.put("mail.smtp.auth", "true"); - props.put("mail.smtp.auth", "false"); - props.put("mail.debug", "true"); - props.put("mail.smtp.port", SMTP_PORT); - props.put("mail.smtp.socketFactory.port", SMTP_PORT); - props.put("mail.smtp.socketFactory.class", SSL_FACTORY); - props.put("mail.smtp.socketFactory.fallback", "false"); - - Session session = Session.getDefaultInstance(props); - - session.setDebug(debug); - if(doIreallyWantToSpam){ - - Message msg = new MimeMessage(session); - InternetAddress addressFrom; - try { - addressFrom = new InternetAddress(from); - msg.setFrom(addressFrom); - - InternetAddress[] addressTo = new InternetAddress[recipients.length]; - for (int i = 0; i < recipients.length; i++) { - addressTo[i] = new InternetAddress(recipients[i]); - } - msg.setRecipients(Message.RecipientType.TO, addressTo); - - // Setting the Subject and Content Type - msg.setSubject(subject); - msg.setContent(message, "text/plain"); - if(doIreallyWantToSpam){ - Transport.send(msg); - assertTrue(doIreallyWantToSpam); - } - } catch (AddressException e) { - log.debug(e.getMessage()); - assertTrue(false); - } catch (MessagingException e) { - log.debug(e.getMessage()); - assertTrue(false); - } - } - //assertTrue(doIreallyWantToSpam); - } - - /** - * Tests the extracted part of the URN is as expected - * @throws Exception - */ - @Test public void testDeURNedField() throws Exception { - - //create person authority to use - String personStr = "{\"shortIdentifier\":\"mytestperson\",\"personTermGroup\":[{\"termDisplayName\":\"TEST my test person\"}]}"; - - HttpTester out = tester.POSTData(TestBase.MAIN_PERSON_INSTANCE_PATH+"/",tester.makeSimpleRequest(personStr),jetty); - String person_url=out.getHeader("Location"); - JSONObject persondata = new JSONObject(out.getContent()); - String urn = persondata.getString("urn"); - - //assign person authority - JSONObject testdata = new JSONObject(urnTestJoe); - testdata.getJSONObject("fields").put("fieldCollectionPlace",urn); - - //create object - out = tester.POSTData("/cataloging/",testdata,jetty); - assertEquals(out.getMethod(),null); - String id=out.getHeader("Location"); - //read and check - out = tester.GETData(id,jetty); - JSONObject one = new JSONObject(tester.getFields(out.getContent())); - log.info(one.toString()); - assertEquals(one.get("fieldCollectionPlace"), urn); - //assertEquals(one.get("de-urned-fieldCollectionPlace"), "TEST my test person"); - - //clean up - tester.DELETEData(id,jetty); - - tester.DELETEData("/vocabularies/"+person_url,jetty); - - } - /** - * Checks a vocabulary (here a person) can be linked to an object - * @throws Exception - */ - @Test public void testTermsUsedVocab() throws Exception { - //create person authority to use - String personStr = "{\"personTermGroup\":[{\"termDisplayName\":\"TEST my test person\"}]}"; - HttpTester out = tester.POSTData(TestBase.MAIN_PERSON_INSTANCE_PATH+"/",tester.makeSimpleRequest(personStr),jetty); - String person_url=out.getHeader("Location"); - - - JSONObject persondata = new JSONObject(out.getContent()); - String urn = persondata.getString("urn"); - - //assign person authority - JSONObject testdata = new JSONObject(urnTestJoe); - testdata.getJSONObject("fields").put("contentPeople",urn); - - //create object - out = tester.POSTData("/cataloging/",testdata,jetty); - String id=out.getHeader("Location"); - - out = tester.GETData(id,jetty); - - // I believe the items below where copied from test above and are not needed - //JSONObject one = new JSONObject(getFields(out.getContent())); - - //assertEquals(one.get("contentPeople"), urn); - //assertEquals(one.get("de-urned-contentPeople"), "TEST my test person2"); - - //get the cataloging linked to the vocab item - - out = tester.GETData("/vocabularies"+person_url,jetty); - - //clean up - tester.DELETEData(id,jetty); - tester.DELETEData("/vocabularies/"+person_url,jetty); - } - - //@Test - no guarentee that the service layer created this report and put it where I could find it - public void testReports() throws Exception { - String uipath = "/acquisition/"; - String data = tester.acquisitionCreate(); - HttpTester out; - // Create - out = tester.POSTData(uipath, tester.makeSimpleRequest(data),jetty); - String id = out.getHeader("Location"); - // Retrieve - out = tester.jettyDo(jetty, "GET", "/tenant/core" + id, null); - - HttpTester out3 = tester.jettyDo(jetty, "GET", "/tenant/core/reporting/search/acquisition", null); - log.info(out3.getContent()); - - JSONObject one = new JSONObject(out.getContent()); - JSONObject list = new JSONObject(out3.getContent()); - - String reportcsid = list.getJSONArray("reportlist").getString(0); - String path = one.getString("csid"); - - JSONObject report = new JSONObject(); - report.put("docType", "acquisition"); - report.put("singleCSID", path); - report.put("mode", "single"); - JSONObject fields = new JSONObject(); - fields.put("fields", report); - - String url = "/invokereport/"+reportcsid; - - HttpTester out2 = tester.POSTData(url,fields.toString(),jetty,"GET"); - log.info(out2.getContent()); - assertEquals(200,out2.getStatus()); - log.info(Integer.toString(out2.getStatus())); - assertEquals("application/pdf",out2.getHeader("Content-Type")); - log.info(out2.getHeader("Content-Type")); - - // Delete - tester.DELETEData(id, jetty); - - - } - - - - - -} diff --git a/war-entry/build.xml b/war-entry/build.xml deleted file mode 100644 index 9ee5989b9..000000000 --- a/war-entry/build.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/war-entry/pom.xml b/war-entry/pom.xml deleted file mode 100644 index 00e52c2d5..000000000 --- a/war-entry/pom.xml +++ /dev/null @@ -1,169 +0,0 @@ - - - 4.0.0 - war-entry - war - war-entry - - - org.collectionspace - svcapp - ${revision} - - - - - tomcat - - true - - - - tomcat6x - ${env.CATALINA_HOME} - ${cspace.server.home}/lib - - - - nodeploy - - - tomcat6x - ${temp.war.location} - ${cspace.server.home}/lib - - - - - - - org.collectionspace - tomcat-main - ${project.version} - jar - - - - org.apache.maven - maven-archiver - 2.4.1 - - - - org.apache.maven.plugins - maven-war-plugin - 2.1.1 - - - - - collectionspace - - ../build.properties - - - - - ${project.basedir}/../tomcat-main/src/main/resources - - log4j.properties - - - - - - - - - maven-antrun-plugin - 1.7 - - - clean - - run - - - - - - - - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.1 - - - install - - exec - - - - - ant - -Dconfig_destination="${config.destination}" - - - - - diff --git a/war-entry/src/main/java/README.txt b/war-entry/src/main/java/README.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/war-entry/src/main/resources/META-INF/MANIFEST.MF b/war-entry/src/main/resources/META-INF/MANIFEST.MF deleted file mode 100644 index ec0be69c7..000000000 --- a/war-entry/src/main/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -Built-By: dan -Build-Jdk: 1.6.0_24 -Main-Class: org.collectionspace.chain.controller.CommandLine -Class-Path: WEB-INF/lib/tomcat-main-1.0-SNAPSHOT.jar WEB-INF/classes \ No newline at end of file diff --git a/war-entry/src/main/webapp/META-INF/context.xml b/war-entry/src/main/webapp/META-INF/context.xml deleted file mode 100644 index 53cd974c8..000000000 --- a/war-entry/src/main/webapp/META-INF/context.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/war-entry/src/main/webapp/WEB-INF/web.xml b/war-entry/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index f467ae562..000000000 --- a/war-entry/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - collectionspace chain - - - TenantServlet - org.collectionspace.chain.controller.TenantServlet - - - TenantUIServlet - org.collectionspace.chain.controller.TenantUIServlet - - - - TenantUIServlet - /ui/* - - - TenantServlet - /tenant/* - - - TenantServlet - /chain/* - - - - CharSetFilter - org.collectionspace.chain.controller.filters.CharSetFilter - - encodings - US-ASCII, UTF-8, EUC-KR, ISO-8859-15, ISO-8859-1 - - - inputEncodingParameterName - ie - - - - - CharSetFilter - /* - - - - - From f434c198cd9ce949860db07e2065efe34196b665 Mon Sep 17 00:00:00 2001 From: Spiros Dimopulos Date: Mon, 22 Jun 2026 10:30:51 +0300 Subject: [PATCH 04/12] DRYD-2073: Object Record > All Profiles > Add Home Location (#352) --- CHANGELOG.md | 6 ++++++ .../src/main/resources/defaults/base-collectionobject.xml | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 151573f9b..d72eb635d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CollectionSpace Application Changelog +## 9.0.0 + +### CollectionObject + +* Add home location group `homeLocationGroupList/homeLocationGroup` + ## 8.3.0 ### Authorities diff --git a/tomcat-main/src/main/resources/defaults/base-collectionobject.xml b/tomcat-main/src/main/resources/defaults/base-collectionobject.xml index 76d210d6a..45de63f52 100644 --- a/tomcat-main/src/main/resources/defaults/base-collectionobject.xml +++ b/tomcat-main/src/main/resources/defaults/base-collectionobject.xml @@ -121,6 +121,10 @@ + + + + From e550ef1da534cdae3b93e2a378a002c1af0cdf0b Mon Sep 17 00:00:00 2001 From: Michael Ritter Date: Tue, 7 Jul 2026 12:41:01 -0600 Subject: [PATCH 05/12] DRYD-2124: Set Release to JDK 21 (#354) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f49616a8d..a7fde8d82 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ 9.0.0-SNAPSHOT ${revision} - 17 + 21 ${basedir}/tmp csmake UTF-8 From 100a48652b75a371107d8664a5d410e69d6f8a39 Mon Sep 17 00:00:00 2001 From: Spiros Dimopulos Date: Tue, 14 Jul 2026 16:46:59 +0300 Subject: [PATCH 06/12] DRYD-2117: Procedure/Object > Ability to set Priority Image (#356) --- CHANGELOG.md | 4 ++++ .../src/main/resources/defaults/base-collectionobject.xml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d72eb635d..01f37dbce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ * Add home location group `homeLocationGroupList/homeLocationGroup` +### Media + +* Add repeatable field `priorityImageList/priorityImage` + ## 8.3.0 ### Authorities diff --git a/tomcat-main/src/main/resources/defaults/base-collectionobject.xml b/tomcat-main/src/main/resources/defaults/base-collectionobject.xml index 45de63f52..ed4efbed1 100644 --- a/tomcat-main/src/main/resources/defaults/base-collectionobject.xml +++ b/tomcat-main/src/main/resources/defaults/base-collectionobject.xml @@ -134,6 +134,10 @@ + + + + From dae45be19359acd7df8b2f0be6b73853cac32f97 Mon Sep 17 00:00:00 2001 From: Spiros Dimopulos Date: Tue, 14 Jul 2026 19:10:59 +0300 Subject: [PATCH 07/12] DRYD-2117: Procedure/Object > Ability to set Priority Image - Rename priority image to media priority (#358) --- CHANGELOG.md | 2 +- .../src/main/resources/defaults/base-collectionobject.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01f37dbce..75e80fd51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ ### Media -* Add repeatable field `priorityImageList/priorityImage` +* Add repeatable field `mediaPriorityList/mediaPriority` ## 8.3.0 diff --git a/tomcat-main/src/main/resources/defaults/base-collectionobject.xml b/tomcat-main/src/main/resources/defaults/base-collectionobject.xml index ed4efbed1..50519b85e 100644 --- a/tomcat-main/src/main/resources/defaults/base-collectionobject.xml +++ b/tomcat-main/src/main/resources/defaults/base-collectionobject.xml @@ -134,8 +134,8 @@ - - + + From bc76f89bee612f0a47e498777b27199658aa2706 Mon Sep 17 00:00:00 2001 From: Michael Ritter Date: Thu, 16 Jul 2026 14:57:14 -0600 Subject: [PATCH 08/12] DRYD-2002: Settings for Password Requirements (#355) --- .gitignore | 3 +- CHANGELOG.md | 8 +++ .../ServiceBindingsGeneration.java | 39 ++++++++++++- .../csp/schema/PasswordComplexityData.java | 55 +++++++++++++++++++ .../chain/csp/schema/Spec.java | 15 +++++ .../services/ServicesStorageGenerator.java | 2 +- .../csp/persistence/services/TenantSpec.java | 2 +- pom.xml | 27 --------- .../src/main/resources/defaults/settings.xml | 36 +++++++----- 9 files changed, 141 insertions(+), 46 deletions(-) create mode 100644 cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/PasswordComplexityData.java diff --git a/.gitignore b/.gitignore index bc270d068..3b6482882 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ tomcat-main/plugins/ tomcat-main/nb-configuration.xml tomcat-main/nbactions-debug.xml cspi-schema/dumpedTrees/ +cspi-schema/logs/ *.bak target/ .DS_Store @@ -17,4 +18,4 @@ war-entry/tmp/ *.xlsx .vscode .factorypath -.flattened-pom.xml \ No newline at end of file +.flattened-pom.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 75e80fd51..804e5e611 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## 9.0.0 +### Build + +* Update to JDK 21 + +### Settings + +* Add password complexity requirements to tenant settings.xml + ### CollectionObject * Add home location group `homeLocationGroupList/homeLocationGroup` diff --git a/cspi-installation/src/main/java/org/collectionspace/chain/installation/ServiceBindingsGeneration.java b/cspi-installation/src/main/java/org/collectionspace/chain/installation/ServiceBindingsGeneration.java index c5d53e2a1..bdd144e58 100644 --- a/cspi-installation/src/main/java/org/collectionspace/chain/installation/ServiceBindingsGeneration.java +++ b/cspi-installation/src/main/java/org/collectionspace/chain/installation/ServiceBindingsGeneration.java @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.Set; +import org.apache.commons.io.FileUtils; import org.collectionspace.chain.csp.persistence.services.TenantSpec; import org.collectionspace.chain.csp.persistence.services.TenantSpec.RemoteClient; import org.collectionspace.chain.csp.schema.EmailData; @@ -16,6 +17,7 @@ import org.collectionspace.chain.csp.schema.Group; import org.collectionspace.chain.csp.schema.Instance; import org.collectionspace.chain.csp.schema.Option; +import org.collectionspace.chain.csp.schema.PasswordComplexityData; import org.collectionspace.chain.csp.schema.Record; import org.collectionspace.chain.csp.schema.Repeat; import org.collectionspace.chain.csp.schema.Spec; @@ -31,7 +33,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.commons.io.FileUtils; public class ServiceBindingsGeneration { private static final Logger log = LoggerFactory.getLogger(ServiceBindingsGeneration.class); @@ -200,6 +201,8 @@ private String doServiceBindingsCommon(String serviceBindingVersion) { // Set the bindings for email notifications makeEmailBindings(ele); + makePasswordComplexityBindings(ele); + makeUiBindings(ele); // add in if required @@ -452,7 +455,6 @@ private void makeEmailBindings(Element tenantBindingElement) { // into seconds; otherwise, ignore the 'daysvalid' field and use the configured 'tokenExpirationSeconds' value. // Element ele = passwordResetElement.addElement(new QName("tokenExpirationSeconds", nstenant)); - Integer secondsValid = emailData.getTokenExpirationDays() * 60 * 60 * 24; // Convert days into seconds ele.addText(emailData.getTokenExpirationSeconds().toString()); } @@ -473,6 +475,39 @@ private void makeEmailBindings(Element tenantBindingElement) { } } + private void makePasswordComplexityBindings(Element tenantBindings) { + PasswordComplexityData passwordComplexityData = spec.getPasswordComplexityData(); + if (passwordComplexityData != null && passwordComplexityData.isEnabled()) { + final var root = tenantBindings.addElement(new QName("passwordRequirementConfig", nstenant)); + + // passwordComplexity/enabled + root.addElement(new QName("enabled", nstenant)) + .addText(String.valueOf(passwordComplexityData.isEnabled())); + + // passwordComplexity/minLength + passwordComplexityData.getMinLength().ifPresent(minLength -> + root.addElement(new QName("minLength", nstenant)) + .addText(String.valueOf(minLength)) + ); + + // passwordComplexity/requireLowerCase + root.addElement(new QName("requireLowerCase", nstenant)) + .addText(String.valueOf(passwordComplexityData.requireLowerCase())); + + // passwordComplexity/requireUpperCase + root.addElement(new QName("requireUpperCase", nstenant)) + .addText(String.valueOf(passwordComplexityData.requireUpperCase())); + + // passwordComplexity/requireDigit + root.addElement(new QName("requireDigit", nstenant)) + .addText(String.valueOf(passwordComplexityData.requireDigit())); + + // passwordComplexity/requireSpecial + root.addElement(new QName("requireSpecial", nstenant)) + .addText(String.valueOf(passwordComplexityData.requireSpecial())); + } + } + private void makeUiBindings(Element tenantBindingElement) { UiData uiData = spec.getUiData(); String baseUrl = (uiData != null) ? uiData.getBaseURL() : null; diff --git a/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/PasswordComplexityData.java b/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/PasswordComplexityData.java new file mode 100644 index 000000000..123344d9c --- /dev/null +++ b/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/PasswordComplexityData.java @@ -0,0 +1,55 @@ +package org.collectionspace.chain.csp.schema; + +import java.util.Optional; + +import org.collectionspace.chain.csp.config.ReadOnlySection; + +public class PasswordComplexityData { + final boolean enabled; + + final Integer minLength; + final boolean requireLowerCase; + final boolean requireUpperCase; + final boolean requireDigit; + final boolean requireSpecial; + + public PasswordComplexityData(ReadOnlySection section) { + enabled = Boolean.parseBoolean((String) section.getValue("/enabled")); + + minLength = parseIntFromSection(section, "/min-length"); + requireLowerCase = Boolean.parseBoolean((String) section.getValue("/require-lower-case")); + requireUpperCase = Boolean.parseBoolean((String) section.getValue("/require-upper-case")); + requireDigit = Boolean.parseBoolean((String) section.getValue("/require-digit")); + requireSpecial = Boolean.parseBoolean((String) section.getValue("/require-special")); + } + + private Integer parseIntFromSection(ReadOnlySection section, String path) { + final var asString = (String) section.getValue(path); + return asString == null ? null : Integer.parseInt(asString); + } + + public boolean isEnabled() { + return enabled; + } + + public boolean requireLowerCase() { + return requireLowerCase; + } + + public boolean requireUpperCase() { + return requireUpperCase; + } + + public boolean requireDigit() { + return requireDigit; + } + + public boolean requireSpecial() { + return requireSpecial; + } + + public Optional getMinLength() { + return Optional.ofNullable(minLength); + } + +} diff --git a/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/Spec.java b/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/Spec.java index e12a18aa5..863a40128 100644 --- a/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/Spec.java +++ b/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/Spec.java @@ -62,6 +62,7 @@ public class Spec implements CSP, Configurable { private EmailData ed; private AdminData adminData; private UiData uiData; + private PasswordComplexityData passwordComplexityData; @Override public String getName() { return "schema"; } @@ -114,6 +115,16 @@ public Object populate(Object parent, ReadOnlySection section) { } }); + rules.addRule(SECTIONED, new String[] {"password-complexity"}, SECTION_PREFIX + "password-complexity", null, + new RuleTarget() { + @Override + public Object populate(Object parent, ReadOnlySection section) { + passwordComplexityData = new PasswordComplexityData(section); + return this; + } + }); + + rules.addRule(SECTIONED,new String[]{"ui"},SECTION_PREFIX+"ui",null,new RuleTarget(){ @Override public Object populate(Object parent, ReadOnlySection section) { @@ -445,6 +456,10 @@ public Object populate(Object parent, ReadOnlySection section) { } + public PasswordComplexityData getPasswordComplexityData() { + return passwordComplexityData; + } + public EmailData getEmailData() { return ed.getEmailData(); } public UiData getUiData() { return uiData != null ? uiData.getUiData() : null; } public AdminData getAdminData() { return adminData.getAdminData(); } diff --git a/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/ServicesStorageGenerator.java b/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/ServicesStorageGenerator.java index a2ccae55c..fe7f61320 100644 --- a/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/ServicesStorageGenerator.java +++ b/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/ServicesStorageGenerator.java @@ -155,7 +155,7 @@ public Object populate(Object parent, ReadOnlySection milestone) throws Exceptio String tenantId = (String)milestone.getValue("/tenantId"); String tenantName = (String)milestone.getValue("/tenantName"); - RemoteClient remoteClient = tenantSpec.new RemoteClient(name, url, username, password, ssl, auth, tenantId, tenantName); + RemoteClient remoteClient = new TenantSpec.RemoteClient(name, url, username, password, ssl, auth, tenantId, tenantName); tenantSpec.addRemoteClient(remoteClient); return this; diff --git a/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/TenantSpec.java b/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/TenantSpec.java index 45d70b0db..55ec998d9 100644 --- a/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/TenantSpec.java +++ b/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/TenantSpec.java @@ -51,7 +51,7 @@ public class TenantSpec { private Set defaultlanguages = new LinkedHashSet(); private Set defaultdateformats = new LinkedHashSet(); - public class RemoteClient { + public static class RemoteClient { private String name; private String url; private String user; diff --git a/pom.xml b/pom.xml index a7fde8d82..3a0452da9 100644 --- a/pom.xml +++ b/pom.xml @@ -283,33 +283,6 @@ - - maven-antrun-plugin - 1.8 - - - check-environment-vars - validate - - run - - - - - - - - - - - - - - - - - org.apache.maven.plugins diff --git a/tomcat-main/src/main/resources/defaults/settings.xml b/tomcat-main/src/main/resources/defaults/settings.xml index aa810625d..64b0013c4 100644 --- a/tomcat-main/src/main/resources/defaults/settings.xml +++ b/tomcat-main/src/main/resources/defaults/settings.xml @@ -4,23 +4,23 @@ Administrator 1 core - 60 - + 60 + 2592000 2592000 2592000 - + 2592000 2592000 2592000 2592000 - 2592000 - - 2592000 - + 2592000 + + 2592000 + 2592000 @@ -43,14 +43,22 @@ CollectionSpace Password reset request Hello {{greeting}},\n\r\n\rYou've started the process to reset your CollectionSpace account password. To finish resetting your password, go to the Reset Password page {{link}} on CollectionSpace.\n\r\n\rIf clicking the link doesn't work, copy and paste the following link into your browser address bar and click Go.\n\r\n\r{{link}}\n\r Thanks,\n\r\n\r CollectionSpace Administrator\n\r\n\rPlease do not reply to this email. This mailbox is not monitored and you will not receive a response. For assistance, contact your CollectionSpace Administrator directly. - + + + false + 6 + true + true + true + true + http://localhost:@JEE_PORT@/cspace-services - - - /collectionspace/tenant/core/ + + + /collectionspace/tenant/core/ From e200b4954162d2ffde618b13e783138fae57abbf Mon Sep 17 00:00:00 2001 From: Spiros Dimopulos Date: Tue, 21 Jul 2026 07:23:35 +0300 Subject: [PATCH 09/12] DRYD-2127: Procedure > Acquisition > Add Alternate Identifier/Note combination (#359) --- CHANGELOG.md | 4 ++++ .../main/resources/defaults/base-procedure-acquisition.xml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 804e5e611..cae6659e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ * Add password complexity requirements to tenant settings.xml +### Acquisition + +* Add alternative identifier group `alternativeIdentifierGroupList/alternativeIdentifierGroup` + ### CollectionObject * Add home location group `homeLocationGroupList/homeLocationGroup` diff --git a/tomcat-main/src/main/resources/defaults/base-procedure-acquisition.xml b/tomcat-main/src/main/resources/defaults/base-procedure-acquisition.xml index bc9f5c763..2cdfeb145 100644 --- a/tomcat-main/src/main/resources/defaults/base-procedure-acquisition.xml +++ b/tomcat-main/src/main/resources/defaults/base-procedure-acquisition.xml @@ -14,6 +14,10 @@
+ + + + From f87c9548a0a84bbf3f6139c925280b2a180bc974 Mon Sep 17 00:00:00 2001 From: mglyrasis <129785358+mglyrasis@users.noreply.github.com> Date: Wed, 22 Jul 2026 12:17:39 -0600 Subject: [PATCH 10/12] NOJIRA: Remove unused import after JDK25 changes (#360) --- .../chain/csp/webui/userdetails/UserDetailsReset.java | 1 - 1 file changed, 1 deletion(-) diff --git a/cspi-webui/src/main/java/org/collectionspace/chain/csp/webui/userdetails/UserDetailsReset.java b/cspi-webui/src/main/java/org/collectionspace/chain/csp/webui/userdetails/UserDetailsReset.java index dadae9aaa..1681fc8ae 100644 --- a/cspi-webui/src/main/java/org/collectionspace/chain/csp/webui/userdetails/UserDetailsReset.java +++ b/cspi-webui/src/main/java/org/collectionspace/chain/csp/webui/userdetails/UserDetailsReset.java @@ -8,7 +8,6 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.Security; import java.util.Date; import java.util.Properties; From 0ad0ef25c8019d8473369c95d371a1b53b335e0a Mon Sep 17 00:00:00 2001 From: Michael Ritter Date: Mon, 27 Jul 2026 16:26:55 -0600 Subject: [PATCH 11/12] Release 9.0.0 RC.1 (#361) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3a0452da9..bedd2e661 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ Root - 9.0.0-SNAPSHOT + 9.0.0-RC.1 ${revision} 21 ${basedir}/tmp From a4526b61fb477704798284a7bd71bf4afcff1d80 Mon Sep 17 00:00:00 2001 From: Michael Ritter Date: Fri, 14 Aug 2026 11:00:40 -0600 Subject: [PATCH 12/12] Prepare 9.0.0-RC.2 (#362) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bedd2e661..5ffa3a81f 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ Root - 9.0.0-RC.1 + 9.0.0-RC.2 ${revision} 21 ${basedir}/tmp