#
# A place to modify the Nuxeo database with SQL statements.
# See https://doc.nuxeo.com/display/ADMINDOC/VCS+Configuration#VCSConfiguration-DatabaseCreationOption
+# or https://doc.nuxeo.com/nxdoc/repository-configuration/#page-title
#
#CATEGORY: afterTableCreation
#IF: emptyResult
ALTER TABLE reports_common add CONSTRAINT reportname_unique UNIQUE (name);
+
+#
+# Add a unique constraint to the batch job 'name' column of the batch_common table.
+#
+LOG.INFO Adding a unique constraint to the batch 'name' column of the batch_common table
+
+#TEST:
+SELECT constraint_name FROM information_schema.constraint_column_usage WHERE table_name = 'batch_common' AND constraint_name = 'batchname_unique';
+
+#IF: emptyResult
+ALTER TABLE batch_common add CONSTRAINT batchname_unique UNIQUE (name);
<artifactId>org.collectionspace.services.collectionobject.jaxb</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.batch.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.collectionspace.services</groupId>
<artifactId>org.collectionspace.services.collectionobject.client</artifactId>
* $LastChangedDate: $
*/
public class ServiceResult {
+ public boolean autoDelete = true;
public String testID = "";
public String testGroupID = "";
public String fullURL = "";
int deleteFailures = 0;
for (ServiceResult pr : serviceResultsMap.values()) {
try {
- if (Tools.notEmpty(pr.deleteURL)){
+ if (pr.autoDelete == true && Tools.notEmpty(pr.deleteURL)){
ServiceResult deleteResult = XmlReplayTransport.doDELETE(pr.deleteURL, pr.auth, pr.testID, "[autodelete:"+logName+"]");
if (deleteResult.gotExpectedResult() == false || deleteResult.responseCode != 200) {
reattemptList.put(REATTEMPT_KEY + deleteFailures++, pr); // We need to try again after our dependents have been deleted. cow()
try {
testElementIndex++;
String testID = testNode.valueOf("@ID");
+ //
+ // Figure out if we will auto delete resources
+ boolean autoDelete = param_autoDeletePOSTS;
+ String autoDeleteValue = testNode.valueOf("@autoDeletePOSTS");
+ if (autoDeleteValue != null && !autoDeleteValue.trim().isEmpty()) {
+ autoDelete = Boolean.valueOf(autoDeleteValue).booleanValue();
+ }
+
String testIDLabel = Tools.notEmpty(testID) ? (testGroupID+'.'+testID) : (testGroupID+'.'+testElementIndex);
String method = testNode.valueOf("method");
String contentType = testNode.valueOf("contentType");
vars = parts.varsList.get(0);
}
serviceResult = XmlReplayTransport.doPOST_PUTFromXML(parts.responseFilename, vars, protoHostPort, uri, method, contentType, evalStruct, authForTest, testIDLabel);
+ serviceResult.autoDelete = autoDelete;
if (vars!=null) {
serviceResult.addVars(vars);
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ns:batch_common xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:ns="http://collectionspace.org/services/batch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://collectionspace.org/services/batch file:batch_common.xsd">
+ <name>name0</name>
+ <notes>notes0</notes>
+ <forDocTypes>
+ <forDocType>CollectionObject</forDocType>
+ <forDocType>Intake</forDocType>
+ </forDocTypes>
+ <forRoles>
+ <roleDisplayName>TENANT_READER</roleDisplayName>
+ <roleDisplayName>TENANT_ADMINISTRATOR</roleDisplayName>
+ </forRoles>
+ <resourceActionGroupList>
+ <resourceActionGroup>
+ <resourceName>blobs</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>media</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>concepts</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>collectionobjects</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ </resourceActionGroupList>
+ <supportsNoContext>false</supportsNoContext>
+ <supportsSingleDoc>false</supportsSingleDoc>
+ <supportsDocList>false</supportsDocList>
+ <supportsGroup>false</supportsGroup>
+ <createsNewFocus>false</createsNewFocus>
+ <className>className0</className>
+</ns:batch_common>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<document name="batch">
+ <ns2:batch_common xmlns:ns2="http://collectionspace.org/services/batch" xmlns:ns3="http://collectionspace.org/services/jaxb">
+ <name>batch-create-permissions</name>
+ <notes>A batch resource for testing the Batch service's permission enforcement before invoking batch jobs.</notes>
+ <resourceActionGroupList>
+ <resourceActionGroup>
+ <resourceName>blobs</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>media</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>concepts</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>collectionobjects</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ </resourceActionGroupList>
+ <supportsNoContext>true</supportsNoContext>
+ <className>org.collectionspace.services.batch.nuxeo.TestBatchJob</className>
+ </ns2:batch_common>
+</document>
<document name="batch">
<ns2:batch_common
xmlns:ns2="http://collectionspace.org/services/batch"
- xmlns:ns3="http://collectionspace.org/services/jaxb">
+ xmlns:ns3="http://collectionspace.org/services/jaxb"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://collectionspace.org/services/batch file:batch_common.xsd">
<name>TestUpdateObjectLocationBatchJob</name>
<forDocTypes>
<forDocType>CollectionObject</forDocType>
</forDocTypes>
+ <forRoles>
+ <roleDisplayName>TENANT_READER</roleDisplayName>
+ <roleDisplayName>TENANT_ADMINISTRATOR</roleDisplayName>
+ </forRoles>
+ <resourceActionGroupList>
+ <resourceActionGroup>
+ <resourceName>blobs</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>media</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>concepts</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>collectionobjects</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ </resourceActionGroupList>
<supportsSingleDoc>true</supportsSingleDoc>
<supportsDocList>true</supportsDocList>
<supportsGroup>true</supportsGroup>
<supportsNoContext>true</supportsNoContext>
<createsNewFocus>false</createsNewFocus>
- <className>org.collectionspace.services.batch.nuxeo.UpdateObjectLocationBatchJob</className>
+ <className>org.collectionspace.services.batch.nuxeo.TestBatchJob</className>
</ns2:batch_common>
</document>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ Valid modes - {"single", "list", "group", "nocontext"}
+-->
+<ns2:invocationContext xmlns:ns2="http://collectionspace.org/services/common/invocable" xmlns:ns3="http://collectionspace.org/services/jaxb">
+ <mode>mode0</mode>
+ <updateCoreValues>updateCoreValues0</updateCoreValues>
+ <docType>docType0</docType>
+ <singleCSID>singleCSID0</singleCSID>
+ <groupCSID>groupCSID0</groupCSID>
+ <listCSIDs>
+ <csid>csid0</csid>
+ <csid>csid1</csid>
+ <csid>csid2</csid>
+ </listCSIDs>
+ <params>
+ <param>
+ </param>
+ <param>
+ </param>
+ <param>
+ </param>
+ </params>
+</ns2:invocationContext>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ Valid modes - {"single", "list", "group", "nocontext"}
+-->
+<ns2:invocationContext xmlns:ns2="http://collectionspace.org/services/common/invocable" xmlns:ns3="http://collectionspace.org/services/jaxb">
+ <mode>nocontexty</mode>
+</ns2:invocationContext>
<auths>
<!-- IMPORTANT: THESE ARE STICKY :: THEY STICK AROUND UNTIL RESET, IN EXEC ORDER OF THIS FILE. -->
<auth ID="admin@core.collectionspace.org">YWRtaW5AY29yZS5jb2xsZWN0aW9uc3BhY2Uub3JnOkFkbWluaXN0cmF0b3I=</auth>
+ <auth ID="reader@core.collectionspace.org">cmVhZGVyQGNvcmUuY29sbGVjdGlvbnNwYWNlLm9yZzpyZWFkZXI=</auth>
+ <auth ID="testAdministator">YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y</auth>
</auths>
+
+ <testGroup ID="testPermissionsAndRoles" autoDeletePOSTS="true">
+ <test ID="createBatchPermissions" auth="test">
+ <method>POST</method>
+ <uri>/cspace-services/batch/</uri>
+ <filename>batch/batch-create-permissions.xml</filename>
+ </test>
+ <test ID="testInvokeNoContext" auth="test" autoDeletePOSTS="false">
+ <method>POST</method>
+ <uri>/cspace-services/batch/${createBatchPermissions.CSID}</uri>
+ <filename>batch/batch-invoke-nocontext.xml</filename>
+ </test>
+ </testGroup>
+
<testGroup ID="testSingle" autoDeletePOSTS="true">
<test ID="createBatch1" auth="test">
<method>POST</method>
<test ID="createBatch2" auth="test">
<method>POST</method>
<uri>/cspace-services/batch/</uri>
- <filename>batch/batch1.xml</filename>
+ <filename>batch/batch2.xml</filename>
</test>
<test ID="createBatch" auth="test">
<method>POST</method>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<document name="batch">
+ <ns2:batch_common xmlns:ns2="http://collectionspace.org/services/batch"
+ xmlns:ns3="http://collectionspace.org/services/jaxb">
+ <name>TestBatchJob</name>
+ <notes>A benign batch job for testing the Batch service.</notes>
+ <forRoles>
+ <roleDisplayName>TENANT_READER</roleDisplayName>
+ <roleDisplayName>TENANT_ADMINISTRATOR</roleDisplayName>
+ </forRoles>
+ <resourceActionGroupList>
+ <resourceActionGroup>
+ <resourceName>blobs</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>media</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>concepts</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>collectionobjects</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ </resourceActionGroupList>
+ <supportsNoContext>false</supportsNoContext>
+ <supportsSingleDoc>false</supportsSingleDoc>
+ <supportsDocList>false</supportsDocList>
+ <supportsGroup>false</supportsGroup>
+ <createsNewFocus>false</createsNewFocus>
+ <className>org.collectionspace.services.batch.nuxeo.TestBatchJob</className>
+ </ns2:batch_common>
+</document>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<document name="batch">
+ <ns2:batch_common xmlns:ns2="http://collectionspace.org/services/batch"
+ xmlns:ns3="http://collectionspace.org/services/jaxb">
+ <name>TestBatchJob</name>
+ <notes>A benign batch job for testing the Batch service.</notes>
+ <forRoles>
+ <roleDisplayName>TENANT_READER</roleDisplayName>
+ <roleDisplayName>TENANT_ADMINISTRATOR</roleDisplayName>
+ </forRoles>
+ <resourceActionGroupList>
+ <resourceActionGroup>
+ <resourceName>blobs</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>media</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>concepts</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>collectionobjects</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ </resourceActionGroupList>
+ <supportsNoContext>false</supportsNoContext>
+ <supportsSingleDoc>false</supportsSingleDoc>
+ <supportsDocList>false</supportsDocList>
+ <supportsGroup>false</supportsGroup>
+ <createsNewFocus>false</createsNewFocus>
+ <className>org.collectionspace.services.batch.nuxeo.TestBatchJob</className>
+ </ns2:batch_common>
+</document>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<document name="batch">
+ <ns2:batch_common xmlns:ns2="http://collectionspace.org/services/batch"
+ xmlns:ns3="http://collectionspace.org/services/jaxb">
+ <name>TestBatchJob</name>
+ <notes>A benign batch job for testing the Batch service.</notes>
+ <forRoles>
+ <roleDisplayName>TENANT_READER</roleDisplayName>
+ <roleDisplayName>TENANT_ADMINISTRATOR</roleDisplayName>
+ </forRoles>
+ <resourceActionGroupList>
+ <resourceActionGroup>
+ <resourceName>blobs</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>media</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>concepts</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>collectionobjects</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ </resourceActionGroupList>
+ <supportsNoContext>false</supportsNoContext>
+ <supportsSingleDoc>false</supportsSingleDoc>
+ <supportsDocList>false</supportsDocList>
+ <supportsGroup>false</supportsGroup>
+ <createsNewFocus>false</createsNewFocus>
+ <className>org.collectionspace.services.batch.nuxeo.TestBatchJob</className>
+ </ns2:batch_common>
+</document>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<document name="batch">
+ <ns2:batch_common xmlns:ns2="http://collectionspace.org/services/batch"
+ xmlns:ns3="http://collectionspace.org/services/jaxb">
+ <name>TestBatchJob</name>
+ <notes>A benign batch job for testing the Batch service.</notes>
+ <forRoles>
+ <roleDisplayName>TENANT_READER</roleDisplayName>
+ <roleDisplayName>TENANT_ADMINISTRATOR</roleDisplayName>
+ </forRoles>
+ <resourceActionGroupList>
+ <resourceActionGroup>
+ <resourceName>blobs</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>media</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>concepts</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>collectionobjects</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ </resourceActionGroupList>
+ <supportsNoContext>false</supportsNoContext>
+ <supportsSingleDoc>false</supportsSingleDoc>
+ <supportsDocList>false</supportsDocList>
+ <supportsGroup>false</supportsGroup>
+ <createsNewFocus>false</createsNewFocus>
+ <className>org.collectionspace.services.batch.nuxeo.TestBatchJob</className>
+ </ns2:batch_common>
+</document>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<document name="batch">
- <ns2:batch_common
- xmlns:ns2="http://collectionspace.org/services/batch"
- xmlns:ns3="http://collectionspace.org/services/jaxb">
- <name>TestCreateAndLinkLoanOutBatchJob</name>
- <notes>This should be interesting</notes>
- <forDocTypes>
- <forDocType>CollectionObject</forDocType>
- </forDocTypes>
- <supportsSingleDoc>true</supportsSingleDoc>
- <supportsDocList>true</supportsDocList>
- <createsNewFocus>true</createsNewFocus>
- <className>org.collectionspace.services.batch.nuxeo.CreateAndLinkLoanOutBatchJob</className>
- </ns2:batch_common>
-</document>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<document name="batch">
+ <ns2:batch_common xmlns:ns2="http://collectionspace.org/services/batch"
+ xmlns:ns3="http://collectionspace.org/services/jaxb">
+ <name>TestBatchJob</name>
+ <notes>A second benign batch job for testing the Batch service.</notes>
+ <supportsNoContext>false</supportsNoContext>
+ <supportsSingleDoc>false</supportsSingleDoc>
+ <supportsDocList>false</supportsDocList>
+ <supportsGroup>false</supportsGroup>
+ <createsNewFocus>false</createsNewFocus>
+ <className>org.collectionspace.services.batch.nuxeo.TestBatchJob</className>
+ </ns2:batch_common>
+</document>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<ns2:invocationContext
-xmlns:ns2="http://collectionspace.org/services/common/invocable"
-xmlns:ns3="http://collectionspace.org/services/jaxb">
- <mode>single</mode>
- <docType>CollectionObject</docType>
- <singleCSID>${CollObj1}</singleCSID>
-</ns2:invocationContext>
-
-
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> empty = new HashSet<Class<?>>();
- private ResourceMap<PoxPayloadIn, PoxPayloadOut> resourceMap = new ResourceMapImpl();
+ private ResourceMap resourceMap = new ResourceMapImpl();
private ServletContext servletContext = null;
public CollectionSpaceJaxRsApplication() {
</xs:annotation>
<xs:sequence>
<xs:element name="screenName" type="xs:string" minOccurs="1"/>
+ <xs:element name="userid" type="xs:string" minOccurs="1" />
<xs:element name="personRefName" type="xs:string" minOccurs="1" />
<xs:element name="email" type="xs:string" minOccurs="1" />
<xs:element name="status" type="status" minOccurs="1" />
import org.collectionspace.services.authorization.AccountPermission;
import org.collectionspace.services.authorization.AccountRole;
import org.collectionspace.services.authorization.AccountRoleRel;
+import org.collectionspace.services.authorization.RoleValue;
import org.collectionspace.services.authorization.SubjectType;
import org.collectionspace.services.client.AccountClient;
import org.collectionspace.services.client.PayloadOutputPart;
+import org.collectionspace.services.client.RoleClient;
import org.collectionspace.services.common.SecurityResourceBase;
import org.collectionspace.services.common.ServiceMessages;
+import org.collectionspace.services.common.UriInfoWrapper;
import org.collectionspace.services.common.context.RemoteServiceContextFactory;
import org.collectionspace.services.common.context.ServiceContext;
import org.collectionspace.services.common.context.ServiceContextFactory;
+import org.collectionspace.services.common.query.UriInfoImpl;
import org.collectionspace.services.common.storage.StorageClient;
import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
import org.jboss.resteasy.util.HttpResponseCodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.PathSegment;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@GET
@Produces("application/xml")
public AccountsCommonList getAccountList(@Context UriInfo ui) {
- AccountsCommonList result = (AccountsCommonList)getList(ui, AccountsCommon.class);
+ UriInfoWrapper uriInfoWrapper = new UriInfoWrapper(ui);
+ AccountsCommonList result = (AccountsCommonList)getList(uriInfoWrapper, AccountsCommon.class);
if(logger.isTraceEnabled()) {
PayloadOutputPart ppo = new PayloadOutputPart(AccountsCommonList.class.getSimpleName(),
result);
}
return result;
}
+
+ protected UriInfo createUriInfo() throws URISyntaxException {
+ return createUriInfo("");
+ }
+
+ private UriInfo createUriInfo(String queryString) throws URISyntaxException {
+ URI absolutePath = new URI("");
+ URI baseUri = new URI("");
+ return new UriInfoImpl(absolutePath, baseUri, "", queryString, Collections.<PathSegment>emptyList());
+ }
+
+ /**
+ * Perform a search off the accounts for using a user ID
+ * @param userId
+ * @return
+ */
+ private String getAccountCsid(String userId) {
+ String result = null;
+
+ try {
+ UriInfo uriInfo = createUriInfo(String.format("uid=%s", userId));
+ AccountsCommonList accountsCommonList = getAccountList(uriInfo);
+ if (accountsCommonList != null && accountsCommonList.getAccountListItem() != null) {
+ for (AccountListItem accountListItem: accountsCommonList.getAccountListItem()) {
+ if (accountListItem.getUserid().equalsIgnoreCase(userId)) {
+ result = accountListItem.getCsid();
+ break;
+ }
+ }
+ }
+ } catch (URISyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return result;
+ }
+
+ /**
+ * Return the list of roles (display name) for a user id.
+ *
+ * @param userId
+ * @return
+ */
+ public List<String> getAccountRoles(String userId, String tenantId) {
+ List<String> result = null;
+
+ String accountCsid = getAccountCsid(userId);
+ if (accountCsid != null) {
+ AccountRole accountRole = getAccountRole(accountCsid);
+ if (accountRole != null && accountRole.getRole() != null) {
+ List<RoleValue> roleValueList = accountRole.getRole();
+ if (roleValueList.isEmpty() == false) {
+ result = new ArrayList<String>();
+ for (RoleValue roleValue: roleValueList) {
+ String displayName = roleValue.getDisplayName();
+ if (displayName == null) {
+ displayName = RoleClient.inferDisplayName(roleValue.getRoleName(), tenantId);
+ }
+ result.add(displayName);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
@PUT
@Path("{csid}")
logger.debug("getAccountPerm with accCsid=" + accCsid);
ensureCSID(accCsid, ServiceMessages.GET_FAILED+ "getAccountPerm account ");
AccountPermission result = null;
- String userId = "undefined";
try {
result = JpaStorageUtils.getAccountPermissions(accCsid);
} catch (Exception e) {
AccountsCommon account = (AccountsCommon) obj;
AccountListItem accListItem = new AccountListItem();
accListItem.setScreenName(account.getScreenName());
+ accListItem.setUserid(account.getUserId());
accListItem.setEmail(account.getEmail());
accListItem.setStatus(account.getStatus());
String id = account.getCsid();
import javax.ws.rs.core.Response;
-
-
-
-
-
-
-
-
import org.apache.http.HttpStatus;
-import org.collectionspace.services.authorization.AccountRole;
import org.collectionspace.services.authorization.Role;
import org.collectionspace.services.authorization.RolesList;
import org.collectionspace.services.description.ServiceDescription;
public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT;
public static final String SERVICE_PATH_PROXY = SERVICE_PATH + "/";
public final static String IMMUTABLE = "immutable";
+ private final static String BACKEND_ROLE_PREFIX = "ROLE_";
public RoleClient() throws Exception {
super();
public RoleClient(String clientPropertiesFilename) throws Exception {
super(clientPropertiesFilename);
}
-
+
+ /**
+ * Creates a backend (Spring Security as of v4.5) role name.
+ * @param roleDisplayName
+ * @param tenantId
+ * @return
+ */
+ static public String getBackendRoleName(String roleDisplayName, String tenantId) {
+ String roleName = roleDisplayName.toUpperCase();
+ String rolePrefix = BACKEND_ROLE_PREFIX + tenantId + "_";
+ if (!roleName.startsWith(rolePrefix)) {
+ roleName = rolePrefix + roleName;
+ }
+ return roleName;
+ }
+
+ /*
+ * Only call this method with a valid backend role name (not the display name).
+ */
+ static public String inferDisplayName(String backendRoleName, String tenantId) {
+ String rolePrefix = BACKEND_ROLE_PREFIX + tenantId + "_";
+ String inferredRoleName = backendRoleName.replace(rolePrefix, "");
+
+ if (logger.isWarnEnabled()) {
+ String msg = String.format("Role display name '%s' is being inferred from backend role name '%s'.",
+ inferredRoleName, backendRoleName);
+ logger.warn(msg);
+ }
+
+ return inferredRoleName;
+ }
+
@Override
public String getServiceName() {
throw new UnsupportedOperationException(); //FIXME: REM - http://issues.collectionspace.org/browse/CSPACE-3498 }
return SERVICE_PATH_COMPONENT;
}
- public Response readList() {
+ @Override
+ public Response readList() {
return getProxy().readList();
}
}
- public Response read(String csid) {
+ @Override
+ public Response read(String csid) {
return getProxy().read(csid);
}
* @param role the role
* @return the client response
*/
- public Response create(Role role) {
+ @Override
+ public Response create(Role role) {
return getProxy().create(role);
}
* @param role
* @return
*/
- public Response update(String csid, Role role) {
+ @Override
+ public Response update(String csid, Role role) {
return getProxy().update(csid, role);
}
final Logger logger = LoggerFactory.getLogger(PermissionRoleSubResource.class);
/** The storage client. */
final StorageClient storageClient = new JpaRelationshipStorageClient<PermissionRole>();
- //
- private String permissionRoleCsid = null;
-
/**
* Instantiates a new permission role sub resource.
*
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
-import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
}
setTenant(role);
- role.setRoleName(fixRoleName(role.getRoleName(),
- role.getTenantId()));
+ role.setRoleName(RoleClient.getBackendRoleName(role.getRoleName(), role.getTenantId()));
role.setCsid(id);
// We do not allow creation of locked roles through the services.
role.setMetadataProtection(null);
Role roleReceived = getCommonPart();
// If marked as metadata immutable, do not do update
if(!RoleClient.IMMUTABLE.equals(roleFound.getMetadataProtection())) {
- roleReceived.setRoleName(fixRoleName(roleReceived.getRoleName(),
+ roleReceived.setRoleName(RoleClient.getBackendRoleName(roleReceived.getRoleName(),
roleFound.getTenantId()));
merge(roleReceived, roleFound);
}
}
}
- private String fixRoleName(String role, String tenantId) {
- String roleName = role.toUpperCase();
- String rolePrefix = "ROLE_" + tenantId + "_";
- if (!roleName.startsWith(rolePrefix)) {
- roleName = rolePrefix + roleName;
- }
- return roleName;
- }
-
private void setTenant(Role role) {
//set tenant only if not available from input
if (role.getTenantId() == null || role.getTenantId().isEmpty()) {
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.collectionspace.services.authorization.perms.ActionType;
import org.collectionspace.services.authorization.spi.CSpaceAuthorizationProvider;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
return self;
}
+ public static String getMethod(ActionType actionType) {
+ String result = null;
+
+ switch (actionType) {
+ case CREATE:
+ result = "POST";
+ break;
+ case READ:
+ result = "GET";
+ break;
+ case UPDATE:
+ result = "PUT";
+ break;
+ case DELETE:
+ result = "DELETE";
+ break;
+ case RUN:
+ result = "RUN";
+ break;
+ case SEARCH:
+ result = "READ";
+ break;
+ default:
+ throw new RuntimeException(String.format("Encountered unexpected action type '%s'.",
+ actionType.value()));
+ }
+
+ return result;
+ }
+
private void setupProvider() {
String beanConfig = "applicationContext-authorization.xml";
//system property is only set in test environment
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ns:batch_common xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:ns="http://collectionspace.org/services/batch"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://collectionspace.org/services/batch file:batch_common.xsd">
+ <name>name0</name>
+ <notes>notes0</notes>
+ <forDocTypes>
+ <forDocType>CollectionObject</forDocType>
+ <forDocType>Intake</forDocType>
+ </forDocTypes>
+ <forRoles>
+ <roleDisplayName>TENANT_READER</roleDisplayName>
+ <roleDisplayName>TENANT_ADMINISTRATOR</roleDisplayName>
+ </forRoles>
+ <resourceActionGroupList>
+ <resourceActionGroup>
+ <resourceName>blobs</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>media</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>concepts</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>collectionobjects</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ </resourceActionGroupList>
+ <supportsNoContext>false</supportsNoContext>
+ <supportsSingleDoc>false</supportsSingleDoc>
+ <supportsDocList>false</supportsDocList>
+ <supportsGroup>false</supportsGroup>
+ <createsNewFocus>false</createsNewFocus>
+ <className>className0</className>
+</ns:batch_common>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
- Loan Out schema (XSD)
+ Batch common schema (XSD)
Entity : Batch
Part : Common
Used for: Nuxeo EP core document type
- $LastChangedRevision: 2316 $
- $LastChangedDate: 2010-06-02 16:03:51 -0700 (Wed, 02 Jun 2010) $
-->
<xs:schema
<!-- See http://wiki.collectionspace.org/display/collectionspace/Loans+Out+Schema -->
- <!-- Batch Information Group -->
-
- <xs:element name="name" type="xs:string"/>
- <xs:element name="notes" type="xs:string"/>
+ <!-- Batch Information Group -->
+ <xs:element name="name" type="xs:string" />
+ <xs:element name="notes" type="xs:string" />
<xs:element name="forDocTypes">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="forDocType" type="xs:string" minOccurs="1" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="forRoles">
<xs:complexType>
<xs:sequence>
- <xs:element name="forDocType" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
+ <xs:element name="roleDisplayName" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
- <xs:element name="supportsNoContext" type="xs:boolean"/>
- <xs:element name="supportsSingleDoc" type="xs:boolean"/>
- <xs:element name="supportsDocList" type="xs:boolean"/>
- <xs:element name="supportsGroup" type="xs:boolean"/>
- <!-- NYI <xs:element name="supportsQuery" type="xs:boolean"/> -->
- <xs:element name="createsNewFocus" type="xs:boolean"/>
- <xs:element name="className" type="xs:string"/>
+ <xs:element name="resourceActionGroupList" type="resourceActionGroupList"/>
+ <xs:element name="supportsNoContext" type="xs:boolean" />
+ <xs:element name="supportsSingleDoc" type="xs:boolean" />
+ <xs:element name="supportsDocList" type="xs:boolean" />
+ <xs:element name="supportsGroup" type="xs:boolean" />
+ <!-- Batch specific fields -->
+ <xs:element name="createsNewFocus" type="xs:boolean" />
+ <xs:element name="className" type="xs:string" />
+
+ <xs:complexType name="resourceActionGroupList">
+ <xs:sequence>
+ <xs:element name="resourceActionGroup" type="resourceActionGroup" minOccurs="3" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="resourceActionGroup">
+ <xs:sequence>
+ <xs:element name="resourceName" type="xs:string"/>
+ <xs:element name="actionGroup" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+
</xs:schema>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ns:className xmlns:ns="http://collectionspace.org/batch/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://collectionspace.org/batch/ file:/C:/dev/src/cspace/services/services/batch/3rdparty/nuxeo-platform-cs-batch/src/main/resources/schemas/batch_common.xsd">className0</ns:className>
public static final String SERVICE_NAME = "batch";
public static final String SERVICE_PATH_COMPONENT = SERVICE_NAME;
public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT;
- public static final String SERVICE_PAYLOAD_NAME = SERVICE_NAME;
+ public static final String SERVICE_PAYLOAD_NAME = SERVICE_NAME;
+ public static final String SERVICE_COMMON_PART_NAME = SERVICE_NAME + PART_LABEL_SEPARATOR + PART_COMMON_LABEL;
public BatchClient() throws Exception {
super();
</parent>
<modelVersion>4.0.0</modelVersion>
- <groupId>org.collectionspace.services</groupId>
<artifactId>org.collectionspace.services.batch.jaxb</artifactId>
<name>services.batch.jaxb</name>
<artifactId>org.collectionspace.services.jaxb</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.hyperjaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
<build>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ns:batch_common xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:ns="http://collectionspace.org/services/batch"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://collectionspace.org/services/batch file:batch_common.xsd">
+ <name>name0</name>
+ <notes>notes0</notes>
+ <forDocTypes>
+ <forDocType>CollectionObject</forDocType>
+ <forDocType>Intake</forDocType>
+ </forDocTypes>
+ <forRoles>
+ <roleDisplayName>TENANT_READER</roleDisplayName>
+ <roleDisplayName>TENANT_ADMINISTRATOR</roleDisplayName>
+ </forRoles>
+ <resourceActionGroupList>
+ <resourceActionGroup>
+ <resourceName>blobs</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>media</resourceName>
+ <actionGroup>CRUL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>concepts</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ <resourceActionGroup>
+ <resourceName>collectionobjects</resourceName>
+ <actionGroup>RL</actionGroup>
+ </resourceActionGroup>
+ </resourceActionGroupList>
+ <supportsNoContext>false</supportsNoContext>
+ <supportsSingleDoc>false</supportsSingleDoc>
+ <supportsDocList>false</supportsDocList>
+ <supportsGroup>false</supportsGroup>
+ <createsNewFocus>false</createsNewFocus>
+ <className>className0</className>
+</ns:batch_common>
<xs:complexType>
<xs:sequence>
<!-- Batch Information Group -->
- <xs:element name="name" type="xs:string" />
+ <xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="notes" type="xs:string" />
- <xs:element name="forDocTypes">
+ <xs:element name="forDocTypes" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
- <xs:element name="forDocType" type="xs:string"
- minOccurs="1" maxOccurs="unbounded" />
+ <xs:element name="forDocType" type="xs:string" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
- <xs:element name="supportsNoContext" type="xs:boolean" />
- <xs:element name="supportsSingleDoc" type="xs:boolean" />
- <xs:element name="supportsDocList" type="xs:boolean" />
- <xs:element name="supportsGroup" type="xs:boolean" />
+ <xs:element name="forRoles" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="roleDisplayName" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="resourceActionGroupList" type="resourceActionGroupList" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="supportsNoContext" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="supportsSingleDoc" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="supportsDocList" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="supportsGroup" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
<!-- Batch specific fields -->
- <xs:element name="createsNewFocus" type="xs:boolean" />
- <xs:element name="className" type="xs:string" />
+ <xs:element name="createsNewFocus" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="className" type="xs:string" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
+ <xs:complexType name="resourceActionGroupList">
+ <xs:sequence>
+ <xs:element name="resourceActionGroup" type="resourceActionGroup" minOccurs="1" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="resourceActionGroup">
+ <xs:sequence>
+ <xs:element name="resourceName" type="xs:string" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="actionGroup" type="xs:string" minOccurs="1" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:complexType>
</xs:schema>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ jaxb:version="1.0" elementFormDefault="unqualified"
+ xmlns:ns="http://collectionspace.org/services/batch"
+ xmlns="http://collectionspace.org/services/batch" targetNamespace="http://collectionspace.org/services/batch" version="0.1">
+
+ <!--
+ An XSD for a CollectionSpace "document" payload that contains a batch_common "part". This is based on the
+ batch_common.xsd file.
+ -->
+ <!-- batch -->
+ <xs:element name="document">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="batch_common" minOccurs="1" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- Batch Information Group -->
+ <xs:element name="name" type="xs:string"></xs:element>
+ <xs:element name="notes" type="xs:string"></xs:element>
+ <xs:element name="forDocTypes" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="forDocType" type="xs:string" minOccurs="1" maxOccurs="unbounded"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="forRoles" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="roleDisplayName" type="xs:string" minOccurs="1" maxOccurs="unbounded"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="resourceActionGroupList" type="resourceActionGroupList" minOccurs="0" maxOccurs="1"></xs:element>
+ <xs:element name="supportsNoContext" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="supportsSingleDoc" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="supportsDocList" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="supportsGroup" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+ <!-- Batch specific fields -->
+ <xs:element name="createsNewFocus" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="className" type="xs:string" minOccurs="1" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="resourceActionGroupList">
+ <xs:sequence>
+ <xs:element name="resourceActionGroup" type="resourceActionGroup" minOccurs="1" maxOccurs="unbounded"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="resourceActionGroup">
+ <xs:sequence>
+ <xs:element name="resourceName" type="xs:string" minOccurs="1" maxOccurs="1"></xs:element>
+ <xs:element name="actionGroup" type="xs:string" minOccurs="1" maxOccurs="1"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ns:document xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:ns="http://collectionspace.org/services/batch"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://collectionspace.org/services/batch file:/C:/dev/src/cspace/services/services/batch/jaxb/src/main/resources/batch_common_document.xsd">
+ <ns:batch_common>
+ <ns:name>name0</ns:name>
+ <ns:notes>notes0</ns:notes>
+ <ns:forDocTypes>
+ <ns:forDocType>forDocType0</ns:forDocType>
+ <ns:forDocType>forDocType1</ns:forDocType>
+ </ns:forDocTypes>
+ <ns:forRoles>
+ <ns:roleDisplayName>roleDisplayName0</ns:roleDisplayName>
+ <ns:roleDisplayName>roleDisplayName1</ns:roleDisplayName>
+ </ns:forRoles>
+ <ns:resourceActionGroupList>
+ <ns:resourceActionGroup>
+ <ns:resourceName>resourceName0</ns:resourceName>
+ <ns:actionGroup>actionGroup0</ns:actionGroup>
+ </ns:resourceActionGroup>
+ <ns:resourceActionGroup>
+ <ns:resourceName>resourceName1</ns:resourceName>
+ <ns:actionGroup>actionGroup1</ns:actionGroup>
+ </ns:resourceActionGroup>
+ </ns:resourceActionGroupList>
+ <ns:supportsNoContext>false</ns:supportsNoContext>
+ <ns:supportsSingleDoc>false</ns:supportsSingleDoc>
+ <ns:supportsDocList>false</ns:supportsDocList>
+ <ns:supportsGroup>false</ns:supportsGroup>
+ <ns:createsNewFocus>false</ns:createsNewFocus>
+ <ns:className>className0</ns:className>
+ </ns:batch_common>
+</ns:document>
<groupId>org.collectionspace.services</groupId>
<artifactId>org.collectionspace.services.common</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.authentication.service</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.account.service</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.authorization.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.authorization.service</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.collectionspace.services</groupId>
<artifactId>org.collectionspace.services.jaxb</artifactId>
import java.util.Collections;
import java.util.List;
import javax.ws.rs.core.Response;
+
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.common.ResourceMap;
import org.collectionspace.services.common.context.ServiceContext;
import org.collectionspace.services.common.invocable.InvocationContext;
* - ADR 2013-01-04
*/
public abstract class AbstractBatchInvocable implements BatchInvocable {
+ final Logger logger = LoggerFactory.getLogger(AbstractBatchInvocable.class);
public final int OK_STATUS = Response.Status.OK.getStatusCode();
public final int CREATED_STATUS = Response.Status.CREATED.getStatusCode();
public final int INT_ERROR_STATUS = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
protected final String CSID_VALUES_NOT_PROVIDED_IN_INVOCATION_CONTEXT =
"Could not find required CSID values in the invocation context for this batch job.";
+
+ private ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx;
private List<String> invocationModes;
private ResourceMap resourceMap;
- private InvocationContext invocationCtx;
- private ServiceContext ctx;
- private int completionStatus;
- private InvocationResults results;
- private InvocationError errorInfo;
- final Logger logger = LoggerFactory.getLogger(AbstractBatchInvocable.class);
+ protected InvocationContext invocationCtx;
+ protected int completionStatus;
+ protected InvocationResults results;
+ protected InvocationError errorInfo;
public AbstractBatchInvocable() {
init();
}
@Override
- public void setServiceContext(ServiceContext context) {
+ public void setServiceContext(ServiceContext<PoxPayloadIn, PoxPayloadOut> context) {
this.ctx = context;
}
@Override
- public ServiceContext getServiceContext() {
+ public ServiceContext<PoxPayloadIn, PoxPayloadOut> getServiceContext() {
return ctx;
}
import org.collectionspace.services.batch.nuxeo.BatchDocumentModelHandler;
import org.collectionspace.services.client.BatchClient;
import org.collectionspace.services.client.IQueryManager;
+import org.collectionspace.services.client.PayloadPart;
import org.collectionspace.services.client.PoxPayloadIn;
import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.common.NuxeoBasedResource;
@Override
//public Class<BatchCommon> getCommonPartClass() {
public Class getCommonPartClass() {
- try {
- return Class.forName("org.collectionspace.services.batch.BatchCommon");//.class;
- } catch (ClassNotFoundException e){
- return null;
- }
+ return BatchCommon.class;
}
/**
return list;
}
- private AbstractCommonList batchSearch(UriInfo ui,
- String docType, String mode) {
+ private AbstractCommonList batchSearch(UriInfo ui, String docType, String mode) {
try {
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(ui);
DocumentHandler handler = createDocumentHandler(ctx);
}
return ptClause;
}
-
-
-
+ private BatchCommon getBatchCommon(String csid) throws Exception {
+ BatchCommon result = null;
+
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
+ PoxPayloadOut ppo = get(csid, ctx);
+ PayloadPart batchCommonPart = ppo.getPart(BatchClient.SERVICE_COMMON_PART_NAME);
+ result = (BatchCommon)batchCommonPart.getBody();
+
+ return result;
+ }
+
@POST
@Path("{csid}")
public InvocationResults invokeBatchJob(
@Context UriInfo ui,
@PathParam("csid") String csid,
InvocationContext invContext) {
+
try {
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(ui);
BatchDocumentModelHandler handler = (BatchDocumentModelHandler)createDocumentHandler(ctx);
-
- return handler.invokeBatchJob(ctx, csid, resourceMap, invContext);
+ return handler.invokeBatchJob(ctx, csid, resourceMap, invContext, getBatchCommon(csid));
} catch (Exception e) {
- throw bigReThrow(e, ServiceMessages.POST_FAILED);
+ String msg = String.format("%s Could not invoke batch job with CSID='%s'.",
+ ServiceMessages.POST_FAILED, csid);
+ throw bigReThrow(e, msg);
}
}
}
*/
package org.collectionspace.services.batch.nuxeo;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import javax.ws.rs.core.Response;
-import org.collectionspace.services.BatchJAXBSchema;
-import org.collectionspace.services.jaxb.InvocableJAXBSchema;
+import org.collectionspace.authentication.AuthN;
+import org.collectionspace.services.account.AccountResource;
+import org.collectionspace.services.authorization.AuthZ;
+import org.collectionspace.services.authorization.CSpaceResource;
+import org.collectionspace.services.authorization.PermissionException;
+import org.collectionspace.services.authorization.URIResourceImpl;
+import org.collectionspace.services.authorization.perms.ActionType;
import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler;
import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
import org.collectionspace.services.nuxeo.client.java.RepositoryClientImpl;
-import org.collectionspace.services.nuxeo.util.NuxeoUtils;
import org.collectionspace.services.batch.BatchCommon;
+import org.collectionspace.services.batch.BatchCommon.ForDocTypes;
+import org.collectionspace.services.batch.BatchCommon.ForRoles;
import org.collectionspace.services.batch.BatchInvocable;
+import org.collectionspace.services.batch.ResourceActionGroup;
+import org.collectionspace.services.batch.ResourceActionGroupList;
import org.collectionspace.services.client.PoxPayloadIn;
import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.common.ResourceMap;
+import org.collectionspace.services.common.authorization_mgt.ActionGroup;
import org.collectionspace.services.common.context.ServiceContext;
import org.collectionspace.services.common.document.BadRequestException;
import org.collectionspace.services.common.document.DocumentException;
-import org.collectionspace.services.common.document.DocumentWrapper;
import org.collectionspace.services.common.invocable.Invocable;
import org.collectionspace.services.common.invocable.InvocationContext;
import org.collectionspace.services.common.invocable.InvocationResults;
import org.collectionspace.services.common.invocable.Invocable.InvocationError;
+
import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.nuxeo.ecm.core.api.DocumentModel;
-import org.nuxeo.ecm.core.api.model.PropertyException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final Logger logger = LoggerFactory.getLogger(BatchDocumentModelHandler.class);
protected final int BAD_REQUEST_STATUS = Response.Status.BAD_REQUEST.getStatusCode();
-
- public InvocationResults invokeBatchJob(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String csid,
- ResourceMap resourceMap, InvocationContext invocationCtx) throws Exception {
-
- CoreSessionInterface repoSession = null;
- boolean releaseRepoSession = false;
-
- String invocationMode = invocationCtx.getMode();
- String modeProperty = null;
- boolean checkDocType = true;
+
+ /**
+ * Return true if the batch job supports the requested mode.
+ * @param invocationCtx
+ * @param batchCommon
+ * @return
+ * @throws BadRequestException
+ */
+ protected boolean supportsInvokationMode(InvocationContext invocationCtx, BatchCommon batchCommon) throws BadRequestException {
+ boolean result = false;
+
+ String invocationMode = invocationCtx.getMode().toLowerCase();
if (BatchInvocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) {
- modeProperty = BatchJAXBSchema.SUPPORTS_SINGLE_DOC;
+ result = batchCommon.isSupportsSingleDoc(); //BatchJAXBSchema.SUPPORTS_SINGLE_DOC;
} else if (BatchInvocable.INVOCATION_MODE_LIST.equalsIgnoreCase(invocationMode)) {
- modeProperty = BatchJAXBSchema.SUPPORTS_DOC_LIST;
+ result = batchCommon.isSupportsDocList(); //BatchJAXBSchema.SUPPORTS_DOC_LIST;
} else if (BatchInvocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) {
- modeProperty = BatchJAXBSchema.SUPPORTS_GROUP;
+ result = batchCommon.isSupportsGroup(); //BatchJAXBSchema.SUPPORTS_GROUP;
} else if (Invocable.INVOCATION_MODE_NO_CONTEXT.equalsIgnoreCase(invocationMode)) {
- modeProperty = InvocableJAXBSchema.SUPPORTS_NO_CONTEXT;
- checkDocType = false;
+ result = batchCommon.isSupportsNoContext(); //InvocableJAXBSchema.SUPPORTS_NO_CONTEXT;
} else {
- throw new BadRequestException("BatchResource: unknown Invocation Mode: " + invocationMode);
+ String msg = String.format("BatchResource: Unknown invocation mode '%s' requested trying to invoke batch job '%s'.",
+ invocationMode, batchCommon.getName());
+ throw new BadRequestException(msg);
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns true if we found any required permissions.
+ *
+ * @param batchCommon
+ * @return
+ */
+ private boolean hasRequiredPermissions(BatchCommon batchCommon) {
+ boolean result = false;
+
+ try {
+ result = batchCommon.getResourceActionGroupList().getResourceActionGroup().size() > 0;
+ } catch (NullPointerException e) {
+ // ignore exception, we're just testing to see if we have any list elements
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns true if we found any required roles.
+ *
+ * @param batchCommon
+ * @return
+ */
+ private boolean hasRequiredRoles(BatchCommon batchCommon) {
+ boolean result = false;
+
+ try {
+ result = batchCommon.getForRoles().getRoleDisplayName().size() > 0;
+ } catch (NullPointerException e) {
+ // ignore exception, we're just testing to see if we have any list elements
+ }
+
+ return result;
+ }
+
+ /**
+ * The current user is authorized to run the batch job if:
+ * 1. No permissions or roles are specified in the batch job
+ * 2. No roles are specified, but permissions are specified and the current user has those permissions
+ * 3. Roles are specified and the current user is a member of at least one of the roles.
+ *
+ * @param batchCommon
+ * @return
+ */
+ protected boolean isAuthoritzed(BatchCommon batchCommon) {
+ boolean result = true;
+
+ if (hasRequiredRoles(batchCommon)) {
+ result = isAuthorizedWithRoles(batchCommon);
+ } else if (hasRequiredPermissions(batchCommon)) {
+ result = isAuthoritzedWithPermissions(batchCommon);
+ }
+
+ return result;
+ }
+
+ protected boolean isAuthorizedWithRoles(BatchCommon batchCommon) {
+ boolean result = false;
+
+ ForRoles forRolesList = batchCommon.getForRoles();
+ if (forRolesList != null) {
+ AccountResource accountResource = new AccountResource();
+ List<String> roleDisplayNameList = accountResource.getAccountRoles(AuthN.get().getUserId(), AuthN.get().getCurrentTenantId());
+ for (String target : forRolesList.getRoleDisplayName()) {
+ if (roleDisplayNameList.contains(target)) {
+ result = true;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Check to see if the current user is authorized to run/invoke this batch job. If the batch job
+ * did not specify any permissions, we assume that the current user is authorized to run the job.
+ * @param batchCommon
+ * @return
+ */
+ protected boolean isAuthoritzedWithPermissions(BatchCommon batchCommon) {
+ boolean result = true;
+
+ ResourceActionGroupList resourceActionGroupList = batchCommon.getResourceActionGroupList();
+ if (resourceActionGroupList != null) {
+ String tenantId = AuthN.get().getCurrentTenantId();
+ for (ResourceActionGroup resourceActionGroup: resourceActionGroupList.getResourceActionGroup()) {
+ String resourceName = resourceActionGroup.getResourceName();
+ ActionGroup actionGroup = ActionGroup.creatActionGroup(resourceActionGroup.getActionGroup());
+ for (ActionType actionType: actionGroup.getActions()) {
+ CSpaceResource res = new URIResourceImpl(tenantId, resourceName, AuthZ.getMethod(actionType));
+ if (AuthZ.get().isAccessAllowed(res) == false) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns a copy of the incoming list of strings all lower-cased. Also removes any duplicates.
+ *
+ * @param listOfStrings
+ * @return
+ */
+ private List<String> toLowerCase(List<String> listOfStrings) {
+ List<String> result = null;
+
+ if (listOfStrings != null) {
+ Set<String> stringSet = new HashSet<String>();
+ for (String s : listOfStrings) {
+ stringSet.add(s.toLowerCase());
+ }
+ result = new ArrayList<String>(stringSet);
}
+
+ return result;
+ }
+
+ public InvocationResults invokeBatchJob(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String csid,
+ ResourceMap resourceMap, InvocationContext invocationCtx, BatchCommon batchCommon) throws Exception {
+ CoreSessionInterface repoSession = null;
+ boolean releaseRepoSession = false;
RepositoryClientImpl repoClient = (RepositoryClientImpl) this.getRepositoryClient(ctx);
repoSession = this.getRepositorySession();
releaseRepoSession = true;
}
- String className = null;
// Get properties from the batch docModel, and release the session
try {
- DocumentWrapper<DocumentModel> wrapper = repoClient.getDoc(repoSession, ctx, csid);
- DocumentModel docModel = wrapper.getWrappedObject();
- Boolean supports = (Boolean) NuxeoUtils.getProperyValue(docModel, modeProperty);
- if (!supports) {
- throw new BadRequestException("BatchResource: This Batch Job does not support Invocation Mode: "
- + invocationMode);
+ //
+ // Ensure the current user has permission to run this batch job
+ if (isAuthoritzed(batchCommon) == false) {
+ String msg = String.format("BatchResource: The user '%s' does not have permission to run the batch job '%s' CSID='%s'",
+ AuthN.get().getUserId(), batchCommon.getName(), csid);
+ throw new PermissionException(msg);
}
- if (checkDocType) {
- List<String> forDocTypeList = (List<String>) NuxeoUtils.getProperyValue(docModel, BatchJAXBSchema.FOR_DOC_TYPES); //docModel.getPropertyValue(BatchJAXBSchema.FOR_DOC_TYPES);
- if (forDocTypeList == null || !forDocTypeList.contains(invocationCtx.getDocType())) {
- throw new BadRequestException("BatchResource: Invoked with unsupported document type: "
- + invocationCtx.getDocType());
+
+ //
+ // Ensure the batch job supports the requested invocation context's mode type
+ if (supportsInvokationMode(invocationCtx, batchCommon) == false) {
+ String msg = String.format("BatchResource: The batch job '%s' CSID='%s' does not support the invocation mode '%s'.",
+ batchCommon.getName(), csid, invocationCtx.getMode());
+ throw new BadRequestException(msg);
+ }
+
+ //
+ // Ensure the batch job supports the requested invocation context's document type
+ if (!Invocable.INVOCATION_MODE_NO_CONTEXT.equalsIgnoreCase(invocationCtx.getMode())) {
+ ForDocTypes forDocTypes = batchCommon.getForDocTypes();
+ if (forDocTypes != null) {
+ List<String> forDocTypeList = toLowerCase(forDocTypes.getForDocType()); // convert all strings to lowercase.
+ if (forDocTypeList == null || !forDocTypeList.contains(invocationCtx.getDocType().toLowerCase())) {
+ String msg = String.format("BatchResource: The batch job '%s' CSID='%s' does not support the invocation document type '%s'.",
+ batchCommon.getName(), csid, invocationCtx.getDocType());
+ throw new BadRequestException(msg);
+ }
}
}
- className = (String) NuxeoUtils.getProperyValue(docModel, BatchJAXBSchema.BATCH_CLASS_NAME); //docModel.getPropertyValue(BatchJAXBSchema.BATCH_CLASS_NAME);
- } catch (PropertyException pe) {
- if (logger.isDebugEnabled()) {
- logger.debug("Property exception getting batch values: ", pe);
+
+ //
+ // Now that we've ensure all the prerequisites have been met, let's try to
+ // instantiate and run the batch job.
+ //
+
+ String className = batchCommon.getClassName().trim();
+ ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+ Class<?> c = tccl.loadClass(className);
+ tccl.setClassAssertionStatus(className, true);
+ if (!BatchInvocable.class.isAssignableFrom(c)) {
+ throw new RuntimeException("BatchResource: Class: " + className + " does not implement BatchInvocable!");
+ }
+
+ BatchInvocable batchInstance = (BatchInvocable) c.newInstance();
+ List<String> modes = batchInstance.getSupportedInvocationModes();
+ if (!modes.contains(invocationCtx.getMode().toLowerCase())) {
+ String msg = String.format("BatchResource: Invoked with unsupported mode '%s'. Batch class '%s' supports these modes: %s.",
+ invocationCtx.getMode().toLowerCase(), className, modes.toString());
+ throw new BadRequestException(msg);
+ }
+
+ batchInstance.setInvocationContext(invocationCtx);
+ batchInstance.setServiceContext(ctx);
+
+ if (resourceMap != null) {
+ batchInstance.setResourceMap(resourceMap);
+ } else {
+ resourceMap = ResteasyProviderFactory.getContextData(ResourceMap.class);
+ if (resourceMap != null) {
+ batchInstance.setResourceMap(resourceMap);
+ } else {
+ logger.warn("BatchResource.invoke did not get a resourceMapHolder in context!");
+ }
+ }
+
+ batchInstance.run();
+ int status = batchInstance.getCompletionStatus();
+ if (status == Invocable.STATUS_ERROR) {
+ InvocationError error = batchInstance.getErrorInfo();
+ if (error.getResponseCode() == BAD_REQUEST_STATUS) {
+ throw new BadRequestException("BatchResouce: batchProcess encountered error: "
+ + batchInstance.getErrorInfo());
+ } else {
+ throw new RuntimeException("BatchResouce: batchProcess encountered error: "
+ + batchInstance.getErrorInfo());
+
+ }
}
- throw pe;
- } catch (DocumentException de) {
+
+ InvocationResults results = batchInstance.getResults();
+ return results;
+ } catch (PermissionException e) {
if (logger.isDebugEnabled()) {
- logger.debug("Problem getting batch doc: ", de);
+ logger.debug("BatchResource: Caught exception ", e);
}
- throw de;
+ throw e;
} catch (Exception e) {
if (logger.isDebugEnabled()) {
- logger.debug("Caught exception ", e);
+ logger.debug("BatchResource: Caught exception ", e);
}
throw new DocumentException(e);
} finally {
repoClient.releaseRepositorySession(ctx, repoSession);
}
}
-
- className = className.trim();
- ClassLoader tccl = Thread.currentThread().getContextClassLoader();
- Class<?> c = tccl.loadClass(className);
- // enable validation assertions
- tccl.setClassAssertionStatus(className, true);
- if (!BatchInvocable.class.isAssignableFrom(c)) {
- throw new RuntimeException("BatchResource: Class: " + className + " does not implement BatchInvocable!");
- }
-
- BatchInvocable batchInstance = (BatchInvocable) c.newInstance();
- List<String> modes = batchInstance.getSupportedInvocationModes();
- if (!modes.contains(invocationMode)) {
- throw new BadRequestException("BatchResource: Invoked with unsupported context mode: " + invocationMode);
- }
-
- batchInstance.setInvocationContext(invocationCtx);
- batchInstance.setServiceContext(ctx);
-
- if (resourceMap != null) {
- batchInstance.setResourceMap(resourceMap);
- } else {
- resourceMap = ResteasyProviderFactory.getContextData(ResourceMap.class);
- if (resourceMap != null) {
- batchInstance.setResourceMap(resourceMap);
- } else {
- logger.warn("BatchResource.invoke did not get a resourceMapHolder in Context!");
- }
- }
-
- batchInstance.run();
- int status = batchInstance.getCompletionStatus();
- if (status == Invocable.STATUS_ERROR) {
- InvocationError error = batchInstance.getErrorInfo();
- if (error.getResponseCode() == BAD_REQUEST_STATUS) {
- throw new BadRequestException("BatchResouce: batchProcess encountered error: "
- + batchInstance.getErrorInfo());
- } else {
- throw new RuntimeException("BatchResouce: batchProcess encountered error: "
- + batchInstance.getErrorInfo());
-
- }
- }
-
- InvocationResults results = batchInstance.getResults();
- return results;
}
}
package org.collectionspace.services.batch.nuxeo;
-import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.batch.BatchCommon;
+import org.collectionspace.services.batch.BatchInvocable;
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.common.document.InvalidDocumentException;
-import org.collectionspace.services.common.document.ValidatorHandler;
-import org.collectionspace.services.common.document.DocumentHandler.Action;
+import org.collectionspace.services.common.document.ValidatorHandlerImpl;
-public class BatchValidatorHandler implements ValidatorHandler {
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BatchValidatorHandler extends ValidatorHandlerImpl<PoxPayloadIn, PoxPayloadOut> {
+
+ final Logger logger = LoggerFactory.getLogger(BatchValidatorHandler.class);
+
+ //
+ // Error Strings
+ //
+ private static final String VALIDATION_ERROR = "The batch record payload was invalid. See log file for more details.";
+ private static final String NAME_NULL_ERROR = "The batch record field \"name\" cannot be empty or missing.";
+ private static final String MISSING_CLASS_ERROR = "The Java class '%s' (fully qualified with package name) for the batch job named '%s' cannot be found.";
+
+ @Override
+ protected Class<?> getCommonPartClass() {
+ return BatchCommon.class;
+ }
+
+ @Override
+ protected void handleCreate() throws InvalidDocumentException {
+ try {
+ BatchCommon batchCommon = (BatchCommon) getCommonPart();
+ validateBatchCommon(batchCommon);
+ } catch (AssertionError e) {
+ if (logger.isErrorEnabled() == true) {
+ logger.error(e.getMessage(), e);
+ }
+ throw new InvalidDocumentException(VALIDATION_ERROR, e);
+ }
+ }
+
+ @Override
+ protected void handleGet() throws InvalidDocumentException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void handleGetAll() throws InvalidDocumentException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void handleUpdate() throws InvalidDocumentException {
+ try {
+ BatchCommon batchCommon = (BatchCommon) getCommonPart();
+ validateBatchCommon(batchCommon);
+ } catch (AssertionError e) {
+ if (logger.isErrorEnabled() == true) {
+ logger.error(e.getMessage(), e);
+ }
+ throw new InvalidDocumentException(VALIDATION_ERROR, e);
+ }
+ }
@Override
- public void validate(Action action, ServiceContext ctx)
- throws InvalidDocumentException {
+ protected void handleDelete() throws InvalidDocumentException {
// TODO Auto-generated method stub
- //System.out.println("BatchValidatorHandler executed.");
+
}
+ //
+ // Private Methods
+ //
+ private boolean canFindClass(String className) {
+ boolean result = false;
+
+ try {
+ ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+ Class<?> c = tccl.loadClass(className);
+ tccl.setClassAssertionStatus(className, true);
+ if (!BatchInvocable.class.isAssignableFrom(c)) {
+ throw new RuntimeException("BatchResource: Class: " + className + " does not implement BatchInvocable!");
+ }
+ result = true;
+ } catch (Exception e) {
+ String msg = String.format("Could not find load batch class named '%s'",
+ className);
+ logger.debug(msg, e);
+ }
+
+ return result;
+ }
+
+ private void validateBatchCommon(BatchCommon batchCommon) {
+ CS_ASSERT(batchCommon != null);
+
+ //
+ // Ensure a batch name
+ String batchName = batchCommon.getName();
+ CS_ASSERT(batchName != null, NAME_NULL_ERROR);
+ CS_ASSERT(batchName.isEmpty() == false, NAME_NULL_ERROR);
+
+ //
+ // Ensure a batch class
+ String batchClassName = batchCommon.getClassName();
+ CS_ASSERT(batchName != null, NAME_NULL_ERROR);
+ CS_ASSERT(batchName.isEmpty() == false, NAME_NULL_ERROR);
+
+ //
+ // Ensure we can find and load the batch Java class
+ if (canFindClass(batchClassName) == false) {
+ String msg = String.format(MISSING_CLASS_ERROR, batchClassName, batchCommon.getName());
+ CS_ASSERT(false, batchClassName);
+ }
+ }
+
}
package org.collectionspace.services.batch.nuxeo;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import javax.ws.rs.core.Response;
-import org.collectionspace.services.batch.BatchInvocable;
+import org.collectionspace.services.batch.AbstractBatchInvocable;
import org.collectionspace.services.client.CollectionSpaceClientUtils;
import org.collectionspace.services.common.NuxeoBasedResource;
-import org.collectionspace.services.common.ResourceMap;
import org.collectionspace.services.common.api.GregorianCalendarDateTimeUtils;
-import org.collectionspace.services.common.context.ServiceContext;
import org.collectionspace.services.common.invocable.InvocationContext;
-import org.collectionspace.services.common.invocable.InvocationResults;
import org.collectionspace.services.client.LoanoutClient;
import org.collectionspace.services.client.RelationClient;
-public class CreateAndLinkLoanOutBatchJob implements BatchInvocable {
+public class CreateAndLinkLoanOutBatchJob extends AbstractBatchInvocable {
- private static ArrayList<String> invocationModes = null;
- private InvocationContext invocationCtx;
- private ServiceContext ctx;
- private int completionStatus;
- private ResourceMap resourceMap;
- private InvocationResults results;
- private InvocationError errorInfo;
private final String RELATION_TYPE = "affects";
private final String LOAN_DOCTYPE = "LoanOut";
private final String RELATION_PREDICATE_DISP = "affects";
- protected final int CREATED_STATUS = Response.Status.CREATED.getStatusCode();
- protected final int BAD_REQUEST_STATUS = Response.Status.BAD_REQUEST.getStatusCode();
- protected final int INT_ERROR_STATUS = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
public CreateAndLinkLoanOutBatchJob() {
- CreateAndLinkLoanOutBatchJob.setupClassStatics();
- invocationCtx = null;
- completionStatus = STATUS_UNSTARTED;
- resourceMap = null;
- results = new InvocationResults();
- errorInfo = null;
+ setSupportedInvocationModes(Arrays.asList(INVOCATION_MODE_SINGLE, INVOCATION_MODE_LIST));
}
-
- private static void setupClassStatics() {
- if(invocationModes == null ) {
- invocationModes = new ArrayList<String>(1);
- invocationModes.add(INVOCATION_MODE_SINGLE);
- invocationModes.add(INVOCATION_MODE_LIST);
- }
- }
-
- /**
- * @return a set of modes that this plugin can support on invocation. Must be non-empty.
- */
- public List<String> getSupportedInvocationModes() {
- return CreateAndLinkLoanOutBatchJob.invocationModes;
- }
-
- @Override
- public void setServiceContext(ServiceContext context) {
- this.ctx = context;
- }
-
- @Override
- public ServiceContext getServiceContext() {
- return ctx;
- }
-
- @Override
- public InvocationContext getInvocationContext() {
- return invocationCtx;
- }
- /**
- * Sets the invocation context for the batch job. Called before run().
- * @param context an instance of InvocationContext.
- */
- @Override
- public void setInvocationContext(InvocationContext context) {
- this.invocationCtx = context;
- }
-
- /**
- * Sets the invocation context for the batch job. Called before run().
- * @param invocationCtx an instance of InvocationContext.
- */
- public void setResourceMap(ResourceMap resourceMap) {
- this.resourceMap = resourceMap;
- }
-
/**
* The main work logic of the batch job. Will be called after setContext.
*/
+ @Override
public void run() {
completionStatus = STATUS_MIN_PROGRESS;
try {
// First, create the Loanout
- if(createLoan() != STATUS_ERROR) {
+ if (createLoan() != STATUS_ERROR) {
if(INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationCtx.getMode())) {
if(createRelation(results.getPrimaryURICreated(),
invocationCtx.getSingleCSID()) != STATUS_ERROR) {
// First, create the Loanout
// We fetch the resource class by service name
- NuxeoBasedResource resource = (NuxeoBasedResource) resourceMap.get( LoanoutClient.SERVICE_NAME);
- Response response = resource.create(resourceMap, null, loanoutPayload);
+ NuxeoBasedResource resource = (NuxeoBasedResource) getResourceMap().get( LoanoutClient.SERVICE_NAME);
+ Response response = resource.create(getResourceMap(), null, loanoutPayload);
if(response.getStatus() != CREATED_STATUS) {
completionStatus = STATUS_ERROR;
errorInfo = new InvocationError(INT_ERROR_STATUS,
+ "<relationshipType>"+RELATION_TYPE+"</relationshipType>"
+ "<predicateDisplayName>"+RELATION_PREDICATE_DISP+"</predicateDisplayName>"
+ "</ns2:relations_common></document>";
- NuxeoBasedResource resource = (NuxeoBasedResource) resourceMap.get(RelationClient.SERVICE_NAME);
- Response response = resource.create(resourceMap, null, relationPayload);
+ NuxeoBasedResource resource = (NuxeoBasedResource) getResourceMap().get(RelationClient.SERVICE_NAME);
+ Response response = resource.create(getResourceMap(), null, relationPayload);
if(response.getStatus() != CREATED_STATUS) {
completionStatus = STATUS_ERROR;
errorInfo = new InvocationError(INT_ERROR_STATUS,
}
return completionStatus;
}
-
- /**
- * @return one of the STATUS_* constants, or a value from 1-99 to indicate progress.
- * Implementations need not support partial completion (progress) values, and can transition
- * from STATUS_MIN_PROGRESS to STATUS_COMPLETE.
- */
- public int getCompletionStatus() {
- return completionStatus;
- }
-
- /**
- * @return information about the batch job actions and results
- */
- public InvocationResults getResults() {
- if(completionStatus != STATUS_COMPLETE)
- return null;
- return results;
- }
-
- /**
- * @return a user-presentable note when an error occurs in batch processing. Will only
- * be called if getCompletionStatus() returns STATUS_ERROR.
- */
- public InvocationError getErrorInfo() {
- return errorInfo;
- }
-
-
}
--- /dev/null
+package org.collectionspace.services.batch.nuxeo;
+
+import java.util.Arrays;
+
+import org.collectionspace.services.batch.AbstractBatchInvocable;
+
+public class TestBatchJob extends AbstractBatchInvocable {
+
+ public TestBatchJob() {
+ super();
+ setSupportedInvocationModes(Arrays.asList(INVOCATION_MODE_SINGLE, INVOCATION_MODE_LIST,
+ INVOCATION_MODE_GROUP, INVOCATION_MODE_NO_CONTEXT));
+ }
+
+ @Override
+ public void run() {
+ // An empty batch job used just for testing.
+ }
+
+}
import javax.ws.rs.core.UriInfo;
import org.collectionspace.services.batch.AbstractBatchInvocable;
-import org.collectionspace.services.batch.UriInfoImpl;
import org.collectionspace.services.client.AbstractCommonListUtils;
import org.collectionspace.services.client.CollectionObjectClient;
import org.collectionspace.services.client.IClientQueryParams;
import org.collectionspace.services.common.api.RefNameUtils;
import org.collectionspace.services.common.api.Tools;
import org.collectionspace.services.common.invocable.InvocationResults;
+import org.collectionspace.services.common.query.UriInfoImpl;
import org.collectionspace.services.jaxb.AbstractCommonList;
import org.dom4j.DocumentException;
//import org.jboss.resteasy.specimpl.UriInfoImpl;
ResourceMap resourcemap = getResourceMap();
NuxeoBasedResource collectionObjectResource = (NuxeoBasedResource) resourcemap.get(CollectionObjectClient.SERVICE_NAME);
NuxeoBasedResource movementResource = (NuxeoBasedResource) resourcemap.get(MovementClient.SERVICE_NAME);
- String computedCurrentLocation;
long numUpdated = 0;
long processed = 0;
}
UriInfo uriInfo = this.setupQueryParamForUpdateRecords(); // Determines if we'll updated the updateAt and updatedBy core values
- byte[] response = collectionObjectResource.update(resourcemap, uriInfo, collectionObjectCsid,
- collectionObjectUpdatePayload);
+ if (logger.isDebugEnabled()) {
+ byte[] responseBytes = collectionObjectResource.update(resourcemap, uriInfo, collectionObjectCsid,
+ collectionObjectUpdatePayload);
+ logger.debug(String.format("Batch resource: Resonse from collectionobject (cataloging record) update: %s", new String(responseBytes)));
+ }
numUpdated++;
if (logger.isTraceEnabled()) {
}
}
-
private List<String> getMemberCsidsFromGroup(String serviceName, String groupCsid) throws URISyntaxException, DocumentException {
ResourceMap resourcemap = getResourceMap();
NuxeoBasedResource resource = (NuxeoBasedResource) resourcemap.get(serviceName);
boolean morePages = true;
long currentPage = 0;
- long totalItems = 0;
long pageSize = DEFAULT_PAGE_SIZE;
List<String> noContextCsids = new ArrayList<String>();
private void setDomDocument(Document dom) throws DocumentException {
this.domDocument = dom;
String label = domDocument.getRootElement().getName();
- if (label != null) {
+ if (label != null && label.equalsIgnoreCase("document")) {
this.payloadName = label;
- } else if (logger.isWarnEnabled() == true) {
- logger.warn("Incoming message payload is missing a name/label.");
- logger.warn(this.xmlPayload);
+ } else {
+ String msg = "The following incoming request payload is missing the root <document> element or is otherwise malformed. For example valid payloads, see https://wiki.collectionspace.org/display/DOC/Common+Services+REST+API+documentation";
+ throw new DocumentException(msg + '\n' + this.xmlPayload);
}
parseParts();
}
}
/**
- * Attempts to marshal a DOM4j element (for a part) into an instance of a JAXB object
+ * Attempts to unmarshal a DOM4j element (for a part) into an instance of a JAXB object
*
* @param elementInput the element input
* @return the object
result = um.unmarshal(
new StreamSource(new StringReader(elementInput.asXML())));
} catch (Exception e) {
- if (logger.isTraceEnabled() == true) {
- logger.trace(e.getMessage());
- }
+ String msg = String.format("Could not unmarshal XML payload '%s' into a JAXB object.",
+ elementInput.getName());
+ logger.warn(msg);
}
return result;
Document doc = DocumentHelper.parseText(text);
result = doc.getRootElement(); //FIXME: REM - call .detach() to free the element
} catch (Exception e) {
- e.printStackTrace(); //FIXME: REM - Please use proper logger.isWarning() statement
+ String msg = String.format("Could not marshal JAXB object '%s' to an XML element.",
+ jaxbObject.toString());
+ logger.error(msg);
}
return result;
* presentation of error messages to clients.
* @param includeLines if zero, return all lines of stack trace, otherwise return number of lines from top.
*/
- public static String errorToString(Throwable e, boolean stackTraceOnException, int includeLines){
- if (e==null){
- return "";
- }
- String s = e.toString() + "\r\n -- message: " + e.getMessage();
-
- StringBuffer causeBuffer = new StringBuffer();
- Throwable cause = e.getCause();
- while (cause != null){
- causeBuffer.append(cause.getClass().getName()+"::"+cause.getMessage()+"\r\n");
- cause = cause.getCause();
- }
- if (causeBuffer.length()>0) s = s + "\r\n -- Causes: "+causeBuffer.toString();
+ public static String errorToString(Throwable e, boolean stackTraceOnException, int includeLines) {
+ if (e == null) {
+ return "";
+ }
+ String s = "\r\n -- Exception: " + e.getClass().getCanonicalName() + "\r\n -- Message: " + e.getMessage();
+ StringBuffer causeBuffer = new StringBuffer();
+ Throwable cause = e.getCause();
+ while (cause != null) {
+ causeBuffer.append(cause.getClass().getName() + "::" + cause.getMessage() + "\r\n");
+ cause = cause.getCause();
+ }
+ if (causeBuffer.length() > 0) {
+ s = s + "\r\n -- Causes: " + causeBuffer.toString();
+ }
- s = s + "\r\n -- Stack Trace: \r\n -- " + getStackTrace(e, includeLines);
- return s;
- }
+ s = s + "\r\n -- Stack Trace: \r\n -- " + getStackTrace(e, includeLines);
+ return s;
+ }
/**
* Return a set of properties from a properties file.
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
+import org.collectionspace.services.authorization.PermissionException;
import org.collectionspace.services.client.CollectionSpaceClient;
-import org.collectionspace.services.client.PoxPayloadIn;
-import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.common.CSWebApplicationException;
import org.collectionspace.services.common.api.Tools;
import org.collectionspace.services.common.config.ServiceConfigUtils;
response = Response.status(Response.Status.UNAUTHORIZED).entity(serviceMsg + e.getMessage()).type("text/plain").build();
result = new CSWebApplicationException(e, response);
+ } else if (e instanceof PermissionException) {
+ response = Response.status(Response.Status.FORBIDDEN).entity(serviceMsg + e.getMessage()).type("text/plain").build();
+ result = new CSWebApplicationException(e, response);
+
} else if (e instanceof DocumentNotFoundException) {
//
// Don't log this error unless we're in 'trace' mode
// return new WebApplicationException(e, code);
result = new CSWebApplicationException(e, response);
+ } else if (e instanceof org.dom4j.DocumentException) {
+ int code = Response.Status.BAD_REQUEST.getStatusCode();
+ response = Response.status(code).entity(serviceMsg + e.getMessage()).type("text/plain").build();
+ result = new CSWebApplicationException(e, response);
} else if (e instanceof CSWebApplicationException) {
// subresource may have already thrown this exception
// so just pass it on
* @param ctx the ctx
* @return the repository client
*/
- public RepositoryClient getRepositoryClient(ServiceContext<IT, OT> ctx);
+ public RepositoryClient<IT, OT> getRepositoryClient(ServiceContext<IT, OT> ctx);
/**
* Gets the storage client.
@Context UriInfo uriInfo,
String xmlPayload) {
uriInfo = new UriInfoWrapper(uriInfo);
- return this.create(null, resourceMap, uriInfo, xmlPayload);
+ return this.create(null, resourceMap, uriInfo, xmlPayload);
}
public Response create(ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx, // REM: 8/13/2012 - Some sub-classes will override this method -e.g., MediaResource does.
/*
* Maps service names to Resource instances. Use the Service Client Class to get the service name.
*/
-public interface ResourceMap<IT, OT> extends Map<String, CollectionSpaceResource<IT, OT>> {
+public interface ResourceMap extends Map<String, CollectionSpaceResource<?, ?>> {
}
import java.util.HashMap;
-import org.collectionspace.services.client.PoxPayloadIn;
-import org.collectionspace.services.client.PoxPayloadOut;
-
-public class ResourceMapImpl extends HashMap<String, CollectionSpaceResource<PoxPayloadIn, PoxPayloadOut>> implements ResourceMap<PoxPayloadIn, PoxPayloadOut> {
+public class ResourceMapImpl extends HashMap<String, CollectionSpaceResource<?, ?>> implements ResourceMap {
/**
*
*/
private synchronized void populateUriTemplateRegistry() {
if (uriTemplateRegistry.isEmpty()) {
- CollectionSpaceResource resource = null;
+ CollectionSpaceResource<?, ?> resource = null;
ResourceMap resourceMap = getJaxRSResourceMap();
- Set<Map.Entry<String, CollectionSpaceResource>> entrySet = resourceMap.entrySet();
- for (Map.Entry<String, CollectionSpaceResource> entry : entrySet) {
+ Set<Map.Entry<String, CollectionSpaceResource<?, ?>>> entrySet = resourceMap.entrySet();
+ for (Map.Entry<String, CollectionSpaceResource<?, ?>> entry : entrySet) {
resource = entry.getValue();
Map<UriTemplateRegistryKey, StoredValuesUriTemplate> entries =
resource.getUriRegistryEntries();
--- /dev/null
+package org.collectionspace.services.common.authorization_mgt;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.collectionspace.services.authorization.perms.ActionType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ActionGroup {
+ final static Logger logger = LoggerFactory.getLogger(ActionGroup.class);
+
+ String name;
+ ActionType[] actions = {};
+
+ static private String toString(ActionType[] actionTypes) {
+ String result = null;
+
+ if (actionTypes.length > 0) {
+ result = new String();
+ for (ActionType actionType: actionTypes) {
+ result = result + actionType.value() + ':';
+ }
+ }
+
+ return result;
+ }
+
+ static private String toString(List<Character> charList) {
+ String result = null;
+
+ if (charList.isEmpty() == false) {
+ result = new String();
+ for (Character c: charList) {
+ result = result + c;
+ }
+ }
+
+ return result;
+ }
+
+ static int valueOf(Character c) {
+ int result = 0;
+
+ switch (c) {
+ case 'C':
+ result = 1;
+ break;
+ case 'R':
+ result = 2;
+ break;
+ case 'U':
+ result = 3;
+ break;
+ case 'D':
+ result = 4;
+ break;
+ case 'I':
+ result = 5;
+ break;
+ case 'L':
+ result = 6;
+ break;
+ default:
+ result = 0;
+ }
+
+ return result;
+ }
+
+ static int valueOf(ActionType actionType) {
+ int result = 0;
+
+ switch (actionType) {
+ case CREATE:
+ result = 1;
+ break;
+ case READ:
+ result = 2;
+ break;
+ case UPDATE:
+ result = 3;
+ break;
+ case DELETE:
+ result = 4;
+ break;
+ case RUN:
+ result = 5;
+ break;
+ case SEARCH:
+ result = 6;
+ break;
+ default:
+ result = 0;
+ }
+
+ return result;
+ }
+
+ /**
+ * Factory method to create an ActionGroup from an action string -i.e., "CRUDL", "RL", "CRUL", etc.
+ * @param actionString
+ * @return
+ */
+ static public ActionGroup creatActionGroup(String actionString) {
+ ActionGroup result = null;
+
+ Set<Character> actionCharSet = new HashSet<Character>();
+ Set<ActionType> actionTypeSet = new HashSet<ActionType>();
+ for (char c : actionString.toCharArray()) {
+ switch (c) {
+ case 'C':
+ actionTypeSet.add(ActionType.CREATE);
+ actionCharSet.add(c);
+ break;
+
+ case 'R':
+ actionTypeSet.add(ActionType.READ);
+ actionCharSet.add(c);
+ break;
+
+ case 'U':
+ actionTypeSet.add(ActionType.UPDATE);
+ actionCharSet.add(c);
+ break;
+
+ case 'D':
+ actionTypeSet.add(ActionType.DELETE);
+ actionCharSet.add(c);
+ break;
+
+ case 'I':
+ actionTypeSet.add(ActionType.RUN);
+ actionCharSet.add(c);
+ break;
+
+ case 'L':
+ actionTypeSet.add(ActionType.SEARCH);
+ actionCharSet.add(c);
+ break;
+
+ default:
+ System.out.println(String.format("Unknown action character '%c'.", c));
+ }
+ }
+
+ if (actionTypeSet.size() > 0) {
+ // sort for readability
+ ArrayList<Character> actionCharList = new ArrayList<Character>(actionCharSet);
+ Collections.sort(actionCharList, new Comparator<Character>() {
+ @Override
+ public int compare(Character c1, Character c2) {
+ if (valueOf(c1) > valueOf(c2)) {
+ return 1;
+ } else if (valueOf(c1) < valueOf(c2)) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ });
+
+ // sort for readability
+ ArrayList<ActionType> actionTypeList = new ArrayList<ActionType>(actionTypeSet);
+ Collections.sort(actionTypeList, new Comparator<ActionType>() {
+ @Override
+ public int compare(ActionType a1, ActionType a2) {
+ if (valueOf(a1) > valueOf(a2)) {
+ return 1;
+ } else if (valueOf(a1) < valueOf(a2)) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ });
+
+ result = new ActionGroup();
+ result.name = toString(actionCharList);
+ result.actions = actionTypeList.toArray(result.actions);
+ }
+
+ logger.trace(String.format("Create new action group containing these actions name:'%s' actions:'%s'",
+ result.name, toString(result.actions)));
+
+ return result;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public ActionType[] getActions() {
+ return this.actions;
+ }
+}
// for READ-ONLY
final public static String ACTIONGROUP_RL_NAME = "RL";
final public static ActionType[] ACTIONSET_RL = {ActionType.READ, ActionType.SEARCH};
-
-
- /*
- * Inner class to deal with predefined ADMIN and READER action groupds
- */
- public class ActionGroup {
- String name;
- ActionType[] actions;
-
- public String getName() {
- return name;
- }
- }
static ActionGroup ACTIONGROUP_CRUDL;
static ActionGroup ACTIONGROUP_RL;
// A static block to initialize the predefined action groups
static {
- AuthorizationCommon ac = new AuthorizationCommon();
// For admin
- ACTIONGROUP_CRUDL = ac.new ActionGroup();
+ ACTIONGROUP_CRUDL = new ActionGroup();
ACTIONGROUP_CRUDL.name = ACTIONGROUP_CRUDL_NAME;
ACTIONGROUP_CRUDL.actions = ACTIONSET_CRUDL;
// For reader
- ACTIONGROUP_RL = ac.new ActionGroup();
+ ACTIONGROUP_RL = new ActionGroup();
ACTIONGROUP_RL.name = ACTIONGROUP_RL_NAME;
ACTIONGROUP_RL.actions = ACTIONSET_RL;
/*
* Returns the name of the service's acting repository. Gets this from the tenant and service bindings files
*/
- public String getRepositoryName() throws Exception {
+ @Override
+ public String getRepositoryName() throws Exception {
String result = null;
TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
* @return
* @throws Exception
*/
- public CollectionSpaceResource<IT, OT> getResource(ServiceContext ctx) throws Exception {
+ public CollectionSpaceResource<IT, OT> getResource(ServiceContext<?, ?> ctx) throws Exception {
CollectionSpaceResource<IT, OT> result = null;
- ResourceMap<IT, OT> resourceMap = ctx.getResourceMap();
+ ResourceMap resourceMap = ctx.getResourceMap();
String resourceName = ctx.getClient().getServiceName();
result = (CollectionSpaceResource<IT, OT>) resourceMap.get(resourceName);
/**
* @param map the map of service names to resource instances.
*/
- public void setResourceMap(ResourceMap map) {
+ @Override
+ public void setResourceMap(ResourceMap map) {
this.resourceMap = map;
}
* @see org.collectionspace.services.common.context.RemoteServiceContext#getLocalContext(java.lang.String)
*/
@Override
- public ServiceContext getLocalContext(String localContextClassName) throws Exception {
+ public ServiceContext<IT, OT> getLocalContext(String localContextClassName) throws Exception {
ClassLoader cloader = Thread.currentThread().getContextClassLoader();
Class<?> ctxClass = cloader.loadClass(localContextClassName);
if (!ServiceContext.class.isAssignableFrom(ctxClass)) {
+ " implementation of " + ServiceContext.class.getName());
}
- Constructor ctor = ctxClass.getConstructor(java.lang.String.class);
- ServiceContext ctx = (ServiceContext) ctor.newInstance(getServiceName());
+ Constructor<?> ctor = ctxClass.getConstructor(java.lang.String.class);
+ ServiceContext<IT, OT> ctx = (ServiceContext<IT, OT>) ctor.newInstance(getServiceName());
return ctx;
}
import org.collectionspace.services.common.invocable.InvocationContext;
import java.util.List;
+
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.common.api.Tools;
import org.collectionspace.services.common.context.ServiceContext;
return (Tools.notBlank(message)) ? message : "No error message provided";
}
}
+
public String INVOCATION_MODE_SINGLE = "single";
public String INVOCATION_MODE_LIST = "list";
public String INVOCATION_MODE_GROUP = "group";
public String INVOCATION_MODE_NO_CONTEXT = "nocontext";
//public String INVOCATION_MODE_QUERY = "query"; NYI
+
public final int STATUS_ERROR = -1;
public final int STATUS_UNSTARTED = 0;
public final int STATUS_MIN_PROGRESS = 1;
/*
* Save a handle to the JAX-RS related service context
*/
- void setServiceContext(ServiceContext context);
+ void setServiceContext(ServiceContext<PoxPayloadIn, PoxPayloadOut> context);
- ServiceContext getServiceContext();
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> getServiceContext();
InvocationContext getInvocationContext();
}
-package org.collectionspace.services.batch;
+package org.collectionspace.services.common.query;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import org.jboss.resteasy.specimpl.PathSegmentImpl;
checkActive();
//
- // All active users are allowed to the *their* (we enforce this) current list of permissions. If this is not
+ // All active users are allowed to see the *their* (we enforce this) current list of permissions. If this is not
// the request, then we'll do a full AuthZ check.
//
if (resName.equalsIgnoreCase(ACCOUNT_PERMISSIONS) != true) { //see comment immediately above
*/
public class UnauthorizedException extends ServiceException {
- final public static int HTTP_CODE = 401;
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ final public static int HTTP_CODE = 401;
/**
* Creates a new instance of <code>UnauthorizedException</code> without detail message.
* @return the tL
* @throws Exception the exception
*/
- public TL extractPagingInfo(TL theCommonList, DocumentWrapper<WLT> wrapDoc)
+ @Override
+ public TL extractPagingInfo(TL theCommonList, DocumentWrapper<WLT> wrapDoc)
throws Exception {
AbstractCommonList commonList = (AbstractCommonList) theCommonList;
return (TL) commonList;
}
- public Lifecycle getLifecycle(String docTypeName) {
+ @Override
+ public Lifecycle getLifecycle(String docTypeName) {
Lifecycle result = new Lifecycle();
result.setName("Life cycles are not supported by the JPA-based services.");
return result; // NOTE: As of 3/2012, none of the JPA-based services support a life cycle type.
Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
//iterate over parts received and fill those parts
+ boolean werePartsFilled = false;
List<PayloadInputPart> inputParts = input.getParts();
for (PayloadInputPart part : inputParts) {
continue;
}
fillPart(part, docModel, partMeta, action, ctx);
+ werePartsFilled = true;
+ }
+
+ if (werePartsFilled == false) {
+ String msg = String.format("%s request failed because there were no XML payload parts in the request.",
+ action.toString());
+ logger.error(msg);
+ throw new BadRequestException(msg);
}
}
$LastChangedRevision: 2316 $
$LastChangedDate: 2010-06-02 16:03:51 -0700 (Wed, 02 Jun 2010) $
-->
-<xs:schema
- xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- jaxb:version="1.0" elementFormDefault="unqualified"
- xmlns:ns="http://collectionspace.org/services/common/invocable"
- xmlns="http://collectionspace.org/services/common/invocable"
- targetNamespace="http://collectionspace.org/services/common/invocable" version="0.1">
-
- <xs:element name="invocationContext">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="mode" type="xs:string"/>
- <xs:element name="updateCoreValues" type="xs:string"/>
- <xs:element name="docType" type="xs:string"/>
- <xs:element name="singleCSID" type="xs:string"/>
- <xs:element name="groupCSID" type="xs:string"/>
- <xs:element name="listCSIDs">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="csid" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="params">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="param" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="key" type="xs:string" minOccurs="0" maxOccurs="1"/>
- <xs:element name="value" type="xs:string" minOccurs="0" maxOccurs="1"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-</xs:schema>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="1.0" elementFormDefault="unqualified" xmlns:ns="http://collectionspace.org/services/common/invocable" xmlns="http://collectionspace.org/services/common/invocable" targetNamespace="http://collectionspace.org/services/common/invocable" version="0.1">
+ <xs:element name="invocationContext">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="mode" type="xs:string"></xs:element>
+ <xs:element name="updateCoreValues" type="xs:string"></xs:element>
+ <xs:element name="docType" type="xs:string"></xs:element>
+ <xs:element name="singleCSID" type="xs:string"></xs:element>
+ <xs:element name="groupCSID" type="xs:string"></xs:element>
+ <xs:element name="listCSIDs">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="csid" type="xs:string" minOccurs="0" maxOccurs="unbounded"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="params">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="param" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="key" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
+ <xs:element name="value" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>