]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
DRYD-1268: UCB Misc/QoL Contribs (#384)
authorMichael Ritter <mikejritter@users.noreply.github.com>
Fri, 5 Jan 2024 05:33:25 +0000 (22:33 -0700)
committerGitHub <noreply@github.com>
Fri, 5 Jan 2024 05:33:25 +0000 (00:33 -0500)
Co-authored-by: Richard Millet <richard.millet@berkeley.edu>
15 files changed:
.gitignore
services/JaxRsServiceProvider/src/main/webapp/META-INF/context.xml
services/authentication/service/src/main/java/org/collectionspace/authentication/spring/CSpaceUserDetailsService.java
services/authentication/service/src/main/java/org/collectionspace/authentication/spring/SpringAuthNContext.java
services/authorization-mgt/import/build.xml
services/common/src/main/java/org/collectionspace/services/common/EmailUtil.java
services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java
services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java
services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContextImpl.java
services/common/src/main/java/org/collectionspace/services/common/context/ServiceBindingUtils.java
services/common/src/main/java/org/collectionspace/services/common/relation/RelationResource.java
services/common/src/main/java/org/collectionspace/services/common/relation/nuxeo/RelationConstants.java
services/common/src/main/java/org/collectionspace/services/common/storage/JDBCTools.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoConnectorEmbedded.java
services/config/src/main/java/org/collectionspace/services/common/config/PropertyItemUtils.java

index c2a6a58d8a5f3bcb16404d98a6e08fbd61888b4d..db5b3c75a2017baac0fd37918a9c9c65f595c574 100644 (file)
@@ -20,3 +20,7 @@ m2-settings.xml
 *.log.*
 cspace-app-perflog.csv
 .flattened-pom.xml
+bin
+*.diff
+logged_schemas
+logs
index 92518bba5c80dd92e4de9a4bbab0ac12d1a89271..e17f8175994c52fabad672feeaecf3eb0c782d9f 100644 (file)
@@ -8,7 +8,7 @@
   the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
   OF ANY KIND, either express or implied. See the License for the specific language
   governing permissions and limitations under the License. -->
-<Context antiResourceLocking="false" privileged="true" path="/cspace-services"
+<Context antiResourceLocking="false" privileged="true" failCtxIfServletStartFails="true" path="/cspace-services"
     docBase="cspace-services">
 
     <!-- Disable HTTP Session persistence between restart since webengine session objects are not serializable -->
index 754c588f8842d0f6bd1a8b632acdc6c223a4c74a..a0974dc7719bce8b54607ee9a2ccd6177ed8e93d 100644 (file)
 
  *  https://source.collectionspace.org/collection-space/LICENSE.txt
 
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *//**
- *  This document is a part of the source code and related artifacts
- *  for CollectionSpace, an open source collections management system
- *  for museums and related institutions:
-
- *  http://www.collectionspace.org
- *  http://wiki.collectionspace.org
-
- *  Copyright 2009 University of California at Berkeley
-
- *  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
-
  *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -84,6 +62,11 @@ public class CSpaceUserDetailsService implements UserDetailsService {
             salt = realm.getSalt(username);
             requireSSO = realm.isRequireSSO(username);
             tenants = getTenants(username);
+            if (tenants == null || tenants.isEmpty()) {
+                String msg = String.format("The account '%s' is not associated with any tenants.  " +
+                                           "Please contact your administrator.", username);
+                throw new AccountException(msg);
+            }
             grantedAuthorities = getAuthorities(username);
         }
         catch (AccountNotFoundException e) {
index 309f856baf8bfc895da23f4f4efba075d3c54e9f..5550dc70c2b702358f873cb87185780d45595d78 100644 (file)
@@ -83,7 +83,9 @@ public class SpringAuthNContext implements AuthNContext {
 
        CSpaceUser cspaceUser = getUser();
        if (cspaceUser != null) {
-            result = getCurrentTenant().getId();
+            if (getCurrentTenant() != null) {
+                result = getCurrentTenant().getId();
+            }
        } else {
                String username = getUserId();
                if (username.equals(AuthN.ANONYMOUS_USER)) {
index b0b53a92e3787bb89418050e35e583634358947f..3210975769815e1f10f85c02cee2b91514715144 100644 (file)
     <target name="import" depends="import-unix,import-windows"
             description="import authorization" />
     <target name="import-unix" if="osfamily-unix" depends="setup_hibernate.cfg">
-        <exec executable="mvn" failonerror="true">
+        <exec executable="mvn" failonerror="true"> <!-- To debug, change command here mvn to 'mvnDebug' -->
             <arg value="exec:java" />
             <arg value="-f" />
             <arg value="${basedir}/pom.xml" />
index 7ad5de4ae508338489212a5c124a53d9c774202f..f4e5cf02735d5f26f612133bde02e4ae2f52573b 100644 (file)
@@ -28,7 +28,7 @@ public class EmailUtil {
 
        public static void main(String [] args) {
                String username = "collectionspace.lyrasis@gmail.com";
-           String password = "CSpace11-GG";
+           String password = "bogus_password";
            String recipient = "remillet@gmail.com";
 
            Properties props = new Properties();
index 0ce3d507c9ceeaeb9185156464e2891d80c1e1ce..2b96040642cac7392f76edca85da52d8910584f8 100644 (file)
@@ -163,6 +163,7 @@ public class ServiceMain {
                        //celebrate success
                         initFailed = false;
                     } catch (Exception e) {
+                        newInstance.release(); // attempt to release resources acquired during initialization attempt
                         instance = null;
                         if (e instanceof RuntimeException) {
                             throw (RuntimeException) e;
index 09545a4dd8cf0edeb30ac69e341f53c1e4a70319..91c920708ea22fff5b3c1bd6c3f54070ca37b3ad 100644 (file)
@@ -1304,7 +1304,7 @@ public class AuthorizationCommon {
                        }
 
                        if (result.contains("{{link}}") == false) {
-                               logger.warn("The tenant's password reset message does not contain a required '{{link}}' marker.");
+                               logger.error("The tenant's password reset message does not contain a required '{{link}}' marker.");
                                result = null;
                        }
 
index 25caaab683e6049ca304753149632e25b7155ac2..7921a8e5d3e85283c92288d8d434aec1ae738f75 100644 (file)
@@ -626,7 +626,7 @@ public abstract class AbstractServiceContextImpl<IT, OT>
                // to specify sort ordering, pagination, etc.
                //
                MultivaluedMap<String, String> queryParameters = this.getQueryParams();
-               if (queryParameters != null) {
+               if (queryParameters != null && !queryParameters.isEmpty()) {
                  docFilter.setSortOrder(queryParameters);
                  docFilter.setPagination(queryParameters);
                  String workflowWhereClause = buildWorkflowWhereClause(queryParameters);
index 219a1880f65838a94af889c2e564d813993ac0e3..9404590b1937c7d2a18cc3a1f0843f5fde59a315 100644 (file)
@@ -116,12 +116,14 @@ public class ServiceBindingUtils {
                String propName, boolean qualify) {
        List<String> values = new ArrayList<String>();
         ServiceObjectType objectType = serviceBinding.getObject();
-        List<ObjectPartType> objectPartTypes = objectType.getPart();
-        for (ObjectPartType objectPartType : objectPartTypes) {
-               List<PropertyType> propNodeList = objectPartType.getProperties();
-               PropertyItemUtils.getPropertyValuesByNameInNodeList(propNodeList, 
-                               propName, (qualify?(objectPartType.getLabel()+":"):null), values);
-        }
+               if (objectType != null) {
+                       List<ObjectPartType> objectPartTypes = objectType.getPart();
+                       for (ObjectPartType objectPartType : objectPartTypes) {
+                               List<PropertyType> propNodeList = objectPartType.getProperties();
+                               PropertyItemUtils.getPropertyValuesByNameInNodeList(propNodeList, propName,
+                                       (qualify ? objectPartType.getLabel() + ":" : null), values);
+                       }
+               }
        return values;
     }
 
index 46bf5587bde4777d82fe054a0c3f2624505bf17b..503b0826ed923c9619c8eda423b5c3513ca94c80 100644 (file)
@@ -92,6 +92,7 @@ public class RelationResource extends NuxeoBasedResource {
                return this.getList(parentCtx, parentCtx.getUriInfo());
        }
        
+       @Override
        public RelationsCommonList getList(ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx, UriInfo uriInfo) {
                MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
                
index 798da03d2c6b16c8930f465beb9fde8fef974212..3f5d5a809566984114673e8bc26220bb643b8a82 100644 (file)
@@ -54,6 +54,6 @@ public class RelationConstants {
     public final static String TYPE_SCHEMA_NAME = COMMON_SCHEMA_NAME;
     public final static String TYPE_FIELD_NAME = IRelationsManager.RELATIONSHIP_TYPE;
     
-    public final static String AFFECTS_TYPE = RelationshipType.AFFECTS.toString();
-    public final static String BROADER_TYPE = RelationshipType.HAS_BROADER.toString();
+    public final static String AFFECTS_TYPE = RelationshipType.AFFECTS.value();
+    public final static String BROADER_TYPE = RelationshipType.HAS_BROADER.value();
 }
index 311bf37cba47c3d6fcf2747b23fa1201e2d03c86..0c3e0adceee432e6f88af4c7dd2e4e30c80e6956 100644 (file)
@@ -594,47 +594,32 @@ public class JDBCTools {
     /**
      * Create a database user, if that user doesn't already exist.
      *
-     * @param conn a database connection.
+     * @param dataSourceName the datasource for the connection
+     * @param repositoryName the repository name for the connection
+     * @param cspaceInstanceId the cspace instance id for the connection
      * @param dbType a database product type.
      * @param username the name of the database user to create.
      * @param userPW the initial password for that database user.
      */
     public static void createNewDatabaseUser(String dataSourceName, String repositoryName,
              String cspaceInstanceId, DatabaseProductType dbType, String username, String userPW) throws Exception {
-        Statement stmt = null;
-        Connection conn = null;
         if (dbType != DatabaseProductType.POSTGRESQL) {
             throw new UnsupportedOperationException("createNewDatabaseUser only supports PostgreSQL");
         }
-        try {
+
+        String sql = null;
+        try (Connection conn = getConnection(dataSourceName, repositoryName, cspaceInstanceId);
+             Statement stmt = conn.createStatement()) {
             if (hasDatabaseUser(dataSourceName, repositoryName, cspaceInstanceId, dbType, username)) {
-                if (logger.isDebugEnabled()) {
-                    logger.debug("User: " + username + " already exists.");
-                }
+                logger.debug("User: {} already exists.", username);
             } else {
-                conn = getConnection(dataSourceName, repositoryName, cspaceInstanceId);
-                stmt = conn.createStatement();
-                String sql = "CREATE ROLE " + username + " WITH PASSWORD '" + userPW + "' LOGIN";
+                sql = "CREATE ROLE " + username + " WITH PASSWORD '" + userPW + "' LOGIN";
                 stmt.executeUpdate(sql);
-                if (logger.isDebugEnabled()) {
-                    logger.debug("Created User: " + username);
-                }
+                logger.debug("Created User: {}", username);
             }
         } catch (Exception e) {
-            logger.error("createNewDatabaseUser failed on exception: " + e.getLocalizedMessage());
+            logger.error("createNewDatabaseUser failed with exception:", e);
             throw e;
-        } finally {
-            try {
-                if (stmt != null) {
-                    stmt.close();
-                }
-                if (conn != null) {
-                    conn.close();
-                }
-            } catch (SQLException sqle) {
-                // nothing we can do here except log
-                logger.warn("SQL Exception when closing statement/connection: " + sqle.getLocalizedMessage());
-            }
         }
     }
 
index 9f15b782b8e101dff10ee83e406ca6ea79cfa41c..0fca95e1c8107d7338e965822bbf5ebacc88a217 100644 (file)
@@ -5,6 +5,12 @@ import java.io.IOException;
 import java.util.Hashtable;
 import java.util.Iterator;
 
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Enumeration;
+
+import javax.management.JMException;
 import javax.servlet.ServletContext;
 
 import org.apache.catalina.util.ServerInfo;
@@ -43,6 +49,7 @@ public class NuxeoConnectorEmbedded {
        private volatile boolean initialized = false; // use volatile for lazy
                                                                                                        // initialization in
                                                                                                        // singleton
+       private ClassLoader classLoader;
        public NuxeoFrameworkBootstrap fb;
        private ServletContext servletContext;
        private RepositoryClientConfigType repositoryClientConfig;
@@ -112,14 +119,14 @@ public class NuxeoConnectorEmbedded {
                                        + nuxeoHomeDir.getCanonicalPath());
                }
 
-               ClassLoader cl = NuxeoConnectorEmbedded.class.getClassLoader();
+               classLoader = NuxeoConnectorEmbedded.class.getClassLoader();
 
-               fb = new NuxeoFrameworkBootstrap(cl, nuxeoHomeDir);
+               fb = new NuxeoFrameworkBootstrap(classLoader, nuxeoHomeDir);
                fb.setHostName("Tomcat");
                fb.setHostVersion(ServerInfo.getServerNumber());
 
                fb.initialize();
-               fb.start(new MutableClassLoaderDelegate(cl));
+               fb.start(new MutableClassLoaderDelegate(classLoader));
 
                // Test to see if we can connect to the default repository
                boolean transactionStarted = false;
@@ -133,7 +140,7 @@ public class NuxeoConnectorEmbedded {
                try {
                        Repository defaultRepo = Framework.getService(RepositoryManager.class).getDefaultRepository();
                        coreSession = CoreInstance.openCoreSession(defaultRepo.getName(), new SystemPrincipal(null));
-               } catch (Throwable t) {
+        } catch (Throwable t) {
                        logger.error(t.getMessage());
                        throw new RuntimeException("Could not start the Nuxeo EP Framework", t);
                } finally {
@@ -147,6 +154,25 @@ public class NuxeoConnectorEmbedded {
                }
        }
 
+       private void stopNuxeoEP() {
+               try {
+                       fb.stop(new MutableClassLoaderDelegate(classLoader));
+                       Enumeration<Driver> drivers = DriverManager.getDrivers();
+                       while (drivers.hasMoreElements()) {
+                               Driver driver = drivers.nextElement();
+                               try {
+                                       DriverManager.deregisterDriver(driver);
+                                       logger.info("Deregister JDBC driver: {}", driver);
+                               } catch (SQLException e) {
+                                       logger.error("Error deregistering JDBC driver {}", driver, e);
+                               }
+                       }
+               } catch (IllegalArgumentException | ReflectiveOperationException | JMException e) {
+                       logger.error("CollectionSpace was unable to shutdown Nuxeo cleanly.", e);
+               }
+       }
+
+
        /**
         * release releases resources occupied by Nuxeo remoting client runtime
         *
@@ -156,6 +182,7 @@ public class NuxeoConnectorEmbedded {
                if (initialized == true) {
                        try {
                                client.tryDisconnect();
+                               stopNuxeoEP();
                        } catch (Exception e) {
                                logger.error("Failed to disconnect Nuxeo connection.", e);
                                throw e;
index cf93b2db59390655d73c10b58313acddb83823b2..e9567abe81d8b4ae00e31c506c1ebaacd629b503 100644 (file)
@@ -96,37 +96,36 @@ public class PropertyItemUtils {
        return getPropertyValuesByName(propItems, propName, qualPrefix, null);
     }
 
-               /**
-                * @param propNodeList the Item list to search for the named property
-                * @param propName the name of the property of interest
-                * @param qualPrefix a namespace qualifier prefix (with ':') to prepend, or null
-                * @param values and existing list to append values to. If null, a new one will be created.
-                * @return values, or that is null, a new List of string values found for the named property
-                */
-               public static List<String> getPropertyValuesByName(
-                               List<PropertyItemType> propItems, String propName, String qualPrefix,
-                               List<String> values ) {
-
-                       if (values == null) {
-                               values = new ArrayList<String>();
-                       }
+       /**
+        * @param propName the name of the property of interest
+        * @param qualPrefix a namespace qualifier prefix (with ':') to prepend, or null
+        * @param values and existing list to append values to. If null, a new one will be created.
+        * @return values, or that is null, a new List of string values found for the named property
+        */
+       public static List<String> getPropertyValuesByName(
+                       List<PropertyItemType> propItems, String propName, String qualPrefix,
+                       List<String> values ) {
+
+               if (values == null) {
+                       values = new ArrayList<String>();
+               }
 
-                       if (propItems != null) {
-                               for (PropertyItemType propItem : propItems) {
-                                       if (propName.equals(propItem.getKey())) {
-                                               // TODO - the trim() belongs here, not down a few lines.
-                                               String value = propItem.getValue();
+               if (propItems != null) {
+                       for (PropertyItemType propItem : propItems) {
+                               if (propName.equals(propItem.getKey())) {
+                                       // TODO - the trim() belongs here, not down a few lines.
+                                       String value = propItem.getValue();
 
-                                               if (value != null) {
-                                                       values.add((qualPrefix != null) ? (qualPrefix + value) : value.trim());
-                                               }
+                                       if (value != null) {
+                                               values.add((qualPrefix != null) ? (qualPrefix + value) : value.trim());
                                        }
                                }
                        }
-
-                       return values;
                }
 
+               return values;
+       }
+
     /**
      * @param propNodeList the wrapping list node from JAXB
      * @param propName the property to set