#url of the collectionspace server\r
-cspace.url=http://localhost:8180/cspace-services/\r
+#cspace.url=http://localhost:8180/cspace-services/\r
#cspace.url=http://localhost:8200/cspace-services/\r
+#for sockspy: \r
+cspace.url=http://localhost:8280/cspace-services/\r
+\r
cspace.ssl=false\r
cspace.auth=true\r
# default user\r
<service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
org.collectionspace.services.loanin.nuxeo.LoaninDocumentModelHandler
</service:documentHandler>
+ <service:DocHandlerParams xmlns:service='http://collectionspace.org/services/common/service'>
+ <service:classname>org.collectionspace.services.loanin.nuxeo.LoaninDocumentModelHandler</service:classname>
+ <service:params>
+ <service:NuxeoSchemaName>loansin</service:NuxeoSchemaName>
+ <service:DublinCoreTitle>loansin</service:DublinCoreTitle>
+ <service:SummaryFields>loanInNumber|lenderList|loanReturnDate|uri|csid</service:SummaryFields>
+ <service:NuxeoSchemaName>loansin</service:NuxeoSchemaName>
+ <service:AbstractCommonListClassname>org.collectionspace.services.loanin.LoansinCommonList</service:AbstractCommonListClassname>
+ <service:CommonListItemClassname>org.collectionspace.services.loanin.LoansinCommonList$LoaninListItem</service:CommonListItemClassname>
+ <service:ListItemMethodName>getLoaninListItem</service:ListItemMethodName>
+ <service:ListItemsArrays>
+ <service:ListItemsArray>
+ <service:setter>setLoanInNumber</service:setter>
+ <service:element>loanInNumber</service:element>
+ <service:container></service:container>
+ <service:subelement></service:subelement>
+ </service:ListItemsArray>
+
+ <service:ListItemsArray>
+ <service:setter>setLender</service:setter>
+ <service:element>lenderList</service:element>
+ <service:container>lenderGroupList</service:container>
+ <service:subelement>lender</service:subelement>
+ </service:ListItemsArray>
+
+ <service:ListItemsArray>
+ <service:setter>setLoanReturnDate</service:setter>
+ <service:element>loanReturnDate</service:element>
+ <service:container></service:container>
+ <service:subelement></service:subelement>
+ </service:ListItemsArray>
+ </service:ListItemsArrays>
+ </service:params>
+ </service:DocHandlerParams>
<service:validatorHandler xmlns:service='http://collectionspace.org/services/common/service'>
org.collectionspace.services.loanin.nuxeo.LoaninValidatorHandler
</service:validatorHandler>
+ <service:initHandler xmlns:service='http://collectionspace.org/services/common/service'>
+ <service:classname>org.collectionspace.services.common.InitHandler</service:classname>
+ <service:fields>
+ <service:field>ID</service:field>
+ <service:field>Foo</service:field>
+ </service:fields>
+ </service:initHandler>
<service:properties xmlns:service='http://collectionspace.org/services/common/service'>
<!-- What to use for name???
<types:item><types:key>objectNameProperty</types:key><types:value>objectName</types:value></types:item> -->
<service:part id="1" control_group="Managed"
versionable="true" auditable="false"
label="media_common" updated="" order="1">
+ <service:properties>
+ <types:item><types:key>authRef</types:key><types:value>contributor</types:value></types:item>
+ <types:item><types:key>authRef</types:key><types:value>coverage</types:value></types:item>
+ <types:item><types:key>authRef</types:key><types:value>creator</types:value></types:item>
+ <types:item><types:key>authRef</types:key><types:value>publisher</types:value></types:item>
+ <types:item><types:key>authRef</types:key><types:value>rightsHolder</types:value></types:item>
+ <types:item><types:key>authRef</types:key><types:value>subjects|subject</types:value></types:item>
+ </service:properties>
<service:content contentType="application/xml">
<service:xmlContent
namespaceURI="http://collectionspace.org/services/media"
<service:part id="1" control_group="Managed"
versionable="true" auditable="false"
label="media_common" updated="" order="1">
+
+ <service:properties>
+ <types:item><types:key>authRef</types:key><types:value>contributor</types:value></types:item>
+ <types:item><types:key>authRef</types:key><types:value>coverage</types:value></types:item>
+ <types:item><types:key>authRef</types:key><types:value>creator</types:value></types:item>
+ <types:item><types:key>authRef</types:key><types:value>publisher</types:value></types:item>
+ <types:item><types:key>authRef</types:key><types:value>rightsHolder</types:value></types:item>
+ <types:item><types:key>authRef</types:key><types:value>subjects|subject</types:value></types:item>
+ </service:properties>
+
<service:content contentType="application/xml">
<service:xmlContent
namespaceURI="http://collectionspace.org/services/media"
--- /dev/null
+package org.collectionspace.services.common;\r
+\r
+import com.sun.media.jai.util.DataBufferUtils;\r
+import org.collectionspace.services.common.context.ServiceContext;\r
+import org.collectionspace.services.common.document.DocumentHandler;\r
+import org.collectionspace.services.common.document.IInitHandler;\r
+import org.collectionspace.services.common.document.InvalidDocumentException;\r
+import org.collectionspace.services.common.service.ServiceBindingType;\r
+\r
+import java.sql.*;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+/**\r
+ * User: laramie\r
+ * $LastChangedRevision: $\r
+ * $LastChangedDate: $\r
+ */\r
+public class InitHandler implements IInitHandler {\r
+\r
+ public void onRepositoryInitialized(ServiceBindingType sbt, List<String> fields) throws Exception {\r
+ //todo: all post-init tasks for services, or delegate to services that override.\r
+ System.out.println("\r\n\r\n~~~~~~~~~~~~~ in onRepositoryInitialized with ServiceBindingType: "+sbt);\r
+\r
+ //call something like this: services.common.storage.DBUtils.addIndex(String tablename, String fields[]);\r
+ //for every field that has an authRef, do ...\r
+ // --> Connection conn = getConnection();\r
+ //see parameter that you need for adding indices to SQL.\r
+\r
+ }\r
+ /*\r
+ private void doJDBC(){\r
+ Connection conn = null;\r
+ PreparedStatement pstmt = null;\r
+ Statement stmt = null;\r
+ // First find or create the tenants\r
+ try {\r
+ String queryTenantSQL = "UPDATE TABLE ADD KEY `tablename`.`id`...";\r
+ conn = getConnection();\r
+ // First find or create the tenants\r
+ stmt = conn.createStatement();\r
+ ResultSet rs = stmt.executeQuery(queryTenantSQL);\r
+ ArrayList<String> existingTenants = new ArrayList<String>();\r
+ while (rs.next()) {\r
+ String tId = rs.getString("id");\r
+ String tName = rs.getString("name");\r
+ if(tenantInfo.containsKey(tId)) {\r
+ existingTenants.add(tId);\r
+ if(!tenantInfo.get(tId).equalsIgnoreCase(tName)) {\r
+ logger.warn("Configured name for tenant: "\r
+ +tId+" in repository: "+tName\r
+ +" does not match config'd name: "+ tenantInfo.get(tId));\r
+ }\r
+ }\r
+ }\r
+ rs.close();\r
+ pstmt.close();\r
+ stmt.close();\r
+ } catch (RuntimeException rte) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("Exception in createDefaultAccounts: "+\r
+ rte.getLocalizedMessage());\r
+ logger.debug(rte.getStackTrace().toString());\r
+ }\r
+ throw rte;\r
+ } catch (SQLException sqle) {\r
+ // SQLExceptions can be chained. We have at least one exception, so\r
+ // set up a loop to make sure we let the user know about all of them\r
+ // if there happens to be more than one.\r
+ if (logger.isDebugEnabled()) {\r
+ SQLException tempException = sqle;\r
+ while (null != tempException) {\r
+ logger.debug("SQL Exception: " + sqle.getLocalizedMessage());\r
+ tempException = tempException.getNextException();\r
+ }\r
+ logger.debug(sqle.getStackTrace().toString());\r
+ }\r
+ throw new RuntimeException("SQL problem in createDefaultAccounts: ", sqle);\r
+ } catch (Exception e) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("Exception in createDefaultAccounts: "+\r
+ e.getLocalizedMessage());\r
+ }\r
+ } finally {\r
+ try {\r
+ if(conn!=null)\r
+ conn.close();\r
+ if(pstmt!=null)\r
+ pstmt.close();\r
+ if(stmt!=null)\r
+ stmt.close();\r
+ } catch (SQLException sqle) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("SQL Exception closing statement/connection: "\r
+ + sqle.getLocalizedMessage());\r
+ }\r
+ }\r
+ }\r
+ }\r
+ */\r
+\r
+}\r
import javax.naming.NamingException;\r
import javax.security.auth.login.LoginException;\r
import javax.sql.DataSource;\r
-import javax.ws.rs.WebApplicationException;\r
-import javax.ws.rs.core.Response;\r
\r
import org.collectionspace.services.common.config.ServicesConfigReaderImpl;\r
import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;\r
+import org.collectionspace.services.common.document.IInitHandler;\r
import org.collectionspace.services.common.security.SecurityUtils;\r
+import org.collectionspace.services.common.service.*;\r
import org.collectionspace.services.common.tenant.TenantBindingType;\r
import org.collectionspace.services.common.types.PropertyItemType;\r
import org.collectionspace.services.common.types.PropertyType;\r
+import org.collectionspace.services.nuxeo.client.java.DocHandlerBase;\r
import org.collectionspace.services.nuxeo.client.java.NuxeoConnector;\r
import org.collectionspace.services.nuxeo.client.java.TenantRepository;\r
import org.slf4j.Logger;\r
return instance;\r
}\r
\r
- private void initialize() throws Exception {\r
- setServerRootDir();\r
+ private void initialize() throws Exception { setServerRootDir();\r
readConfig();\r
propagateConfiguredProperties();\r
try {\r
} catch(Exception e) {\r
logger.error("Default Account setup failed on exception: "+e.getLocalizedMessage());\r
}\r
+ try {\r
+ //loadDocHandlers();\r
+ firePostInitHandlers();\r
+ } catch(Exception e) {\r
+ logger.error("ServiceMain.initialize firePostInitHandlers failed on exception: "+e.getLocalizedMessage());\r
+ }\r
+\r
if (getClientType().equals(ClientType.JAVA)) {\r
nuxeoConnector = NuxeoConnector.getInstance();\r
- nuxeoConnector.initialize(\r
- getServicesConfigReader().getConfiguration().getRepositoryClient());\r
+ nuxeoConnector.initialize(getServicesConfigReader().getConfiguration().getRepositoryClient());\r
}\r
+\r
}\r
\r
/**\r
private String getDefaultReaderUserID(String tenantName) {\r
return TENANT_READER_ACCT_PREFIX+tenantName;\r
}\r
- \r
+\r
+ private void firePostInitHandlers() throws Exception {\r
+ Hashtable<String, TenantBindingType> tenantBindingTypeMap = tenantBindingConfigReader.getTenantBindings();\r
+ //Loop through all tenants in tenant-bindings.xml\r
+ for (TenantBindingType tbt: tenantBindingTypeMap.values()){\r
+ //String name = tbt.getName();\r
+ //String id = tbt.getId();\r
+ //Loop through all the services in this tenant\r
+ List<ServiceBindingType> sbtList = tbt.getServiceBindings();\r
+ for (ServiceBindingType sbt: sbtList){\r
+ //Get the list of InitHandler elements, extract the first one (only one supported right now) and fire it using reflection.\r
+ List<org.collectionspace.services.common.service.InitHandler> list = sbt.getInitHandler();\r
+ if (list!=null && list.size()>0){\r
+ org.collectionspace.services.common.service.InitHandler handlerType = list.get(0);\r
+ String initHandlerClassname = handlerType.getClassname();\r
+ org.collectionspace.services.common.service.InitHandler.Fields ft = handlerType.getFields();\r
+ List<String> fields = ft.getField();\r
+ Object o = instantiate(initHandlerClassname, IInitHandler.class);\r
+ if (o != null && o instanceof IInitHandler){\r
+ IInitHandler handler = (IInitHandler)o;\r
+ handler.onRepositoryInitialized(sbt, fields);\r
+ //The InitHandler may be the default one,\r
+ // or specialized classes which still implement this interface and are registered in tenant-bindings.xml.\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ public Object instantiate(String clazz, Class castTo) throws Exception {\r
+ ClassLoader tccl = Thread.currentThread().getContextClassLoader();\r
+ clazz = clazz.trim();\r
+ Class<?> c = tccl.loadClass(clazz);\r
+ if (castTo.isAssignableFrom(c)) {\r
+ return c.newInstance();\r
+ }\r
+ return null;\r
+ }\r
+\r
+ private void loadDocHandlers() throws Exception {\r
+ Hashtable<String, TenantBindingType> tenantBindingTypeMap = tenantBindingConfigReader.getTenantBindings();\r
+ for (TenantBindingType tbt: tenantBindingTypeMap.values()){\r
+ String name = tbt.getName();\r
+ String id = tbt.getId();\r
+\r
+ List<ServiceBindingType> sbtList = tbt.getServiceBindings();\r
+ for (ServiceBindingType sbt: sbtList){\r
+ DocHandlerParams params = sbt.getDocHandlerParams();\r
+ if (params!=null){\r
+ params.getClassname();\r
+ DocHandlerParams.Params p = params.getParams();\r
+ DocHandlerBase.CommonListReflection clr = new DocHandlerBase.CommonListReflection();\r
+ //List<ListItemsArray> items = p.getListItemsArrays(); //todo: this thing only returns one row. xsd is wrong. tenant-bindings.xml has an example of multiple elements in loansin.\r
+ List<ListItemsArray> items = /*DocHandlerParams.Params.ListItemsArrays items =*/\r
+ p.getListItemsArrays().getListItemsArray(); //todo: this thing only returns one row. xsd is wrong. tenant-bindings.xml has an example of multiple elements in loansin.\r
+ int size = items.size();\r
+ String[][] rows = new String[size][4];\r
+ int r = 0;\r
+ for (ListItemsArray item: items){\r
+ String[] row = rows[r];\r
+ row[0] = item.getSetter();\r
+ row[1] = item.getElement();\r
+ row[2] = item.getContainer();\r
+ row[3] = item.getSubelement();\r
+ r++;\r
+ }\r
+ clr.ListItemsArray = rows;\r
+ clr.AbstractCommonListClassname = p.getAbstractCommonListClassname();\r
+ clr.CommonListItemClassname = p.getCommonListItemClassname();\r
+ clr.DublinCoreTitle = p.getDublinCoreTitle();\r
+ clr.ListItemMethodName = p.getListItemMethodName();\r
+ clr.NuxeoSchemaName = p.getNuxeoSchemaName();\r
+ clr.SummaryFields = p.getSummaryFields();\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+\r
private Connection getConnection() throws LoginException, SQLException {\r
InitialContext ctx = null;\r
Connection conn = null;\r
--- /dev/null
+package org.collectionspace.services.common.document;\r
+\r
+import org.collectionspace.services.common.context.ServiceContext;\r
+import org.collectionspace.services.common.service.ServiceBindingType;\r
+\r
+import java.util.List;\r
+\r
+/**\r
+ * User: laramie\r
+ * $LastChangedRevision: $\r
+ * $LastChangedDate: $\r
+ */\r
+public interface IInitHandler {\r
+ public void onRepositoryInitialized(ServiceBindingType sbt, List<String> fields) throws Exception;\r
+}\r
throws DocumentNotFoundException, DocumentException {
DocumentFilter filter = handler.getDocumentFilter();
- //filter.setOrderByClause("collectionspace_core:updatedAt DESC"); //per http://issues.collectionspace.org/browse/CSPACE-705
-
+ String oldOrderBy = filter.getOrderByClause();
+ if (oldOrderBy!=null && oldOrderBy.isEmpty()){
+ filter.setOrderByClause("collectionspace_core:updatedAt DESC"); //per http://issues.collectionspace.org/browse/CSPACE-705
+ }
QueryContext queryContext = new QueryContext(ctx, handler);
RepositoryInstance repoSession = null;
try {
<xs:element name="object" type="ServiceObjectType" minOccurs="1" maxOccurs="1"/>
<!-- document handler to be used to process the content (need to be in classpath) -->
<xs:element name="documentHandler" type="xs:string" minOccurs="1" maxOccurs="1"/>
+
+ <xs:element name="DocHandlerParams" type="DocHandlerParams" minOccurs="0" maxOccurs="1"/>
+
<!-- validator handler(s) to be used to validate the content (need to be in classpath) -->
<!-- validator handler is called for create (POST) and update (PUT) requests only -->
<xs:element name="validatorHandler" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <!-- initHandler is a post-init task after the Nuxeo repository is available. -->
+ <!-- worked: <xs:element name="initHandler" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>-->
+ <xs:element name="initHandler" type="initHandler" minOccurs="0" maxOccurs="unbounded"/>
<!-- name of the repository domain -->
<xs:element name="repositoryDomain" type="xs:string" minOccurs="0" maxOccurs="1"/>
<!-- repositoryWorkspaceId could be workspace id -->
</xs:attribute>
</xs:complexType>
+ <xs:complexType name="FieldsType">
+ <xs:sequence>
+ <xs:element name="field" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="initHandler">
+ <xs:sequence>
+ <xs:element name="classname" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <!--<xs:element name="fields" type="FieldsType" minOccurs="0" maxOccurs="1"/>-->
+ <xs:element name="fields">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="field" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="DocHandlerParams">
+ <xs:sequence>
+ <xs:element name="classname" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="params">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="NuxeoSchemaName" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="DublinCoreTitle" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="SummaryFields" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="AbstractCommonListClassname" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="CommonListItemClassname" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="ListItemMethodName" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="ListItemsArrays" minOccurs="1" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ListItemsArray" type="ListItemsArray" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="ListItemsArray">
+ <xs:sequence>
+ <xs:element name="setter" type="xs:string" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="element" type="xs:string" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="container" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ <xs:element name="subelement" type="xs:string" minOccurs="0" maxOccurs="1"/>
+ </xs:sequence>
+ </xs:complexType>
+
+
+
+
+
</xs:schema>