import org.collectionspace.services.common.ResourceMap;
import org.collectionspace.services.common.ServiceMain;
import org.collectionspace.services.common.api.RefName;
+import org.collectionspace.services.common.config.ConfigUtils;
import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
import org.collectionspace.services.common.vocabulary.AuthorityResource;
import org.collectionspace.services.config.service.Term;
import org.collectionspace.services.config.service.TermList;
import org.collectionspace.services.config.tenant.TenantBindingType;
+import org.collectionspace.services.nuxeo.util.NuxeoUtils;
+
+import org.nuxeo.elasticsearch.ElasticSearchComponent;
+import org.nuxeo.elasticsearch.api.ElasticSearchService;
+import org.nuxeo.runtime.api.Framework;
import java.lang.reflect.Constructor;
import java.util.Date;
import java.util.logging.Level;
public class CSpaceResteasyBootstrap extends ResteasyBootstrap {
-
+
java.util.logging.Logger logger = java.util.logging.Logger.getAnonymousLogger();
static final String RESET_AUTHORITIES_PROPERTY = "org.collectionspace.services.authorities.reset";
+ private static final String RESET_ELASTICSEARCH_INDEX_PROPERTY = "org.collectionspace.services.elasticsearch.reset";
private static final String QUICK_BOOT_PROPERTY = "org.collectionspace.services.quickboot";
-
+
@Override
public void contextInitialized(ServletContextEvent event) {
try {
CollectionSpaceJaxRsApplication app = (CollectionSpaceJaxRsApplication)deployment.getApplication();
Dispatcher disp = deployment.getDispatcher();
disp.getDefaultContextObjects().put(ResourceMap.class, app.getResourceMap());
-
+
String quickBoot = System.getProperty(QUICK_BOOT_PROPERTY, Boolean.FALSE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file
if (Boolean.valueOf(quickBoot) == false) {
String resetAuthsString = System.getProperty(RESET_AUTHORITIES_PROPERTY, Boolean.FALSE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file
initializeAuthorities(app.getResourceMap(), Boolean.valueOf(resetAuthsString));
+
+ String resetElasticsearchIndexString = System.getProperty(RESET_ELASTICSEARCH_INDEX_PROPERTY, Boolean.FALSE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file
+
+ if (Boolean.valueOf(resetElasticsearchIndexString) == true) {
+ resetElasticSearchIndex();
+ }
}
-
+
logger.log(Level.INFO, String.format("%tc [INFO] CollectionSpace Services' JAX-RS application started.", new Date()));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
-
-
- @Override
- public void contextDestroyed(ServletContextEvent event) {
- logger.log(Level.INFO, "[INFO] Shutting down the CollectionSpace Services' JAX-RS application.");
- //Do something if needed.
- logger.log(Level.INFO, "[INFO] CollectionSpace Services' JAX-RS application stopped.");
- }
+
+
+ @Override
+ public void contextDestroyed(ServletContextEvent event) {
+ logger.log(Level.INFO, "[INFO] Shutting down the CollectionSpace Services' JAX-RS application.");
+ //Do something if needed.
+ logger.log(Level.INFO, "[INFO] CollectionSpace Services' JAX-RS application stopped.");
+ }
+
+ public void resetElasticSearchIndex() throws Exception {
+ ElasticSearchComponent es = (ElasticSearchComponent) Framework.getService(ElasticSearchService.class);
+
+ for (String repositoryName : es.getRepositoryNames()) {
+ logger.log(Level.INFO, String.format("%tc [INFO] Rebuilding Elasticsearch index for repository %s", new Date(), repositoryName));
+
+ es.dropAndInitRepositoryIndex(repositoryName);
+ }
+
+ TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
+ Hashtable<String, TenantBindingType> tenantBindingsTable = tenantBindingConfigReader.getTenantBindings(false);
+
+ for (TenantBindingType tenantBinding : tenantBindingsTable.values()) {
+ CSpaceTenant tenant = new CSpaceTenant(tenantBinding.getId(), tenantBinding.getName());
+
+ AuthZ.get().login(tenant);
+
+ for (ServiceBindingType serviceBinding : tenantBinding.getServiceBindings()) {
+ Boolean isElasticsearchIndexed = serviceBinding.isElasticsearchIndexed();
+ String servicesRepoDomainName = serviceBinding.getRepositoryDomain();
+
+ if (isElasticsearchIndexed && servicesRepoDomainName != null && servicesRepoDomainName.trim().isEmpty() == false) {
+ String repositoryName = ConfigUtils.getRepositoryName(tenantBinding, servicesRepoDomainName);
+ String docType = serviceBinding.getObject().getName();
+ String tenantQualifiedDocType = NuxeoUtils.getTenantQualifiedDocType(tenantBinding.getId(), docType);
+
+ logger.log(Level.INFO, String.format("%tc [INFO] Starting Elasticsearch reindexing for docType %s in repository %s", new Date(), tenantQualifiedDocType, repositoryName));
+
+ es.runReindexingWorker(repositoryName, String.format("SELECT ecm:uuid FROM %s", tenantQualifiedDocType));
+ }
+ }
+ }
+ }
/**
* Initialize all authorities and vocabularies defined in the service bindings.
* @throws Exception
*/
public void initializeAuthorities(ResourceMap resourceMap, boolean reset) throws Exception {
- TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
+ TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
Hashtable<String, TenantBindingType> tenantBindingsTable = tenantBindingConfigReader.getTenantBindings(false);
for (TenantBindingType tenantBindings : tenantBindingsTable.values()) {
CSpaceTenant tenant = new CSpaceTenant(tenantBindings.getId(), tenantBindings.getName());
}
}
}
-
+
@SuppressWarnings("rawtypes")
private AuthorityClient getAuthorityClient(String classname) throws Exception {
Class clazz = Class.forName(classname.trim());
Object classInstance = co.newInstance(null);
return (AuthorityClient) classInstance;
}
-
+
private boolean shouldInitializeAuthorities(CSpaceTenant cspaceTenant, boolean reset) {
AuthZ.get().login(); // login as super admin
TenantResource tenantResource = new TenantResource();
//
return tenantState.isAuthoritiesInitialized() == false || reset == true;
}
-
+
private void setAuthoritiesInitialized(CSpaceTenant cspaceTenant, boolean initState) {
AuthZ.get().login(); // login as super admin
TenantResource tenantResource = new TenantResource();
/*
* Check to see if an an authority instance and its corresponding terms exist. If not, try to create them.
*/
- private void initializeAuthorityInstance(ResourceMap resourceMap,
- AuthorityInstanceType authorityInstance,
- ServiceBindingType serviceBinding,
+ private void initializeAuthorityInstance(ResourceMap resourceMap,
+ AuthorityInstanceType authorityInstance,
+ ServiceBindingType serviceBinding,
CSpaceTenant cspaceTenant,
boolean reset) throws Exception {
int status = -1;
Response response = null;
String serviceName = serviceBinding.getName();
-
+
AuthZ.get().login(cspaceTenant);
String clientClassName = serviceBinding.getClientHandler();
AuthorityClient client = getAuthorityClient(clientClassName);
} catch (CSWebApplicationException e) {
response = e.getResponse(); // If the authority doesn't exist, we expect a 404 error
}
-
+
//
// If it doesn't exist (status is not 200), then try to create the authority instance
//
response = authorityResource.createAuthority(xmlPayload);
status = response.getStatus();
if (status != Response.Status.CREATED.getStatusCode()) {
- throw new CSWebApplicationException(response);
+ throw new CSWebApplicationException(response);
}
}
-
+
if (status == Response.Status.OK.getStatusCode()) {
logger.log(Level.FINE, String.format("Authority of type '%s' with the short ID of '%s' existed already.",
serviceName, authorityInstance.getTitleRef()));
} else {
logger.log(Level.WARNING, String.format("Unknown status '%d' encountered when creating or fetching authority of type '%s' with the short ID of '%s'.",
serviceName, authorityInstance.getTitleRef()));
- }
-
+ }
+
//
// Next, try to create or verify the authority terms.
//
- initializeAuthorityInstanceTerms(authorityResource, client, authoritySpecifier, resourceMap, authorityInstance, serviceName, cspaceTenant);
+ initializeAuthorityInstanceTerms(authorityResource, client, authoritySpecifier, resourceMap, authorityInstance, serviceName, cspaceTenant);
}
-
+
private void initializeAuthorityInstanceTerms(
AuthorityResource authorityResource,
- AuthorityClient client,
- String authoritySpecifier,
- ResourceMap resourceMap,
- AuthorityInstanceType authorityInstance,
+ AuthorityClient client,
+ String authoritySpecifier,
+ ResourceMap resourceMap,
+ AuthorityInstanceType authorityInstance,
String serviceName,
CSpaceTenant tenant) throws Exception {
-
+
int status = -1;
Response response = null;
if (termListElement == null) {
return;
}
-
+
for (Term term : termListElement.getTerm()) {
//
// Check to see if the term already exists
//
try {
- String termSpecifier = RefName.shortIdToPath(term.getId());
+ String termSpecifier = RefName.shortIdToPath(term.getId());
authorityResource.getAuthorityItem(null, null, resourceMap, authoritySpecifier, termSpecifier);
status = Response.Status.OK.getStatusCode();
} catch (CSWebApplicationException e) {
response = e.getResponse(); // If the authority doesn't exist, we expect a 404 error
status = response.getStatus();
}
-
+
//
// If the term doesn't exist, create it.
//
response = e.getResponse();
status = response.getStatus();
if (status != Response.Status.CREATED.getStatusCode()) {
- throw new CSWebApplicationException(response);
+ throw new CSWebApplicationException(response);
}
}
}
>
<xs:import namespace="http://collectionspace.org/services/config/types" schemaLocation="types.xsd" />
-
-
+
+
<xs:element name="root" type="ServiceBindingType"></xs:element>
-
+
<xs:complexType name="ServiceBindingType">
<xs:sequence>
<!-- other URI paths using which this service binding could be accessed -->
<xs:element name="uriPath" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
-
+
<!-- object representation served by the service -->
<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"/>
-
+
<!-- optional instances definitions -->
<xs:element name="AuthorityInstanceList">
<xs:complexType>
<xs:element name="repositoryWorkspaceId" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="properties" type="types:PropertyType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
-
+
<!-- name of the service, this is also the default URI path to access this service binding -->
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="version" type="types:VersionType" use="required"/>
+ <xs:attribute name="elasticsearchIndexed" type="xs:boolean" default="false"/>
<xs:attribute name="requiresDocumentHandler" type="xs:boolean" default="true"/>
<xs:attribute name="supportsReplicating" type="xs:boolean" default="false"/>
<xs:attribute name="remoteClientConfigName" type="xs:string"/>
<xs:element ref="termList"/>
</xs:sequence>
</xs:complexType>
-
+
<xs:element name="termList">
<xs:complexType>
<xs:sequence>
<xs:attribute name="id" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
-
+
<!--
ServiceObjectType defines the manifest for a collectionspace
object. includes properties of the object as well as manifests
<xs:element name="public" type="xs:boolean" minOccurs="0" maxOccurs="1" default="true"/> <!-- any entity in the chain can cache this -->
<xs:element name="noCache" type="xs:boolean" minOccurs="0" maxOccurs="1" default="false"/> <!-- should not be cached in any way/method -->
<xs:element name="mustRevalidate" type="xs:boolean" minOccurs="0" maxOccurs="1" default="false"/> <!-- See http://bit.ly/2mnCwIi -->
- <xs:element name="proxyRevalidate" type="xs:boolean" minOccurs="0" maxOccurs="1" default="false"/>
+ <xs:element name="proxyRevalidate" type="xs:boolean" minOccurs="0" maxOccurs="1" default="false"/>
<xs:element name="noStore" type="xs:boolean" minOccurs="0" maxOccurs="1" default="false"/> <!-- can be cached but should not be stored on disk (most browsers will hold the resources in memory until they will be quit) -->
<xs:element name="noTransform" type="xs:boolean" minOccurs="0" maxOccurs="1" default="false"/> <!-- the resource should not be modified (for example shrink image by proxy) -->
<xs:element name="maxAge" type="xs:integer" minOccurs="0" maxOccurs="1" default="86400"/> <!-- how long the resource is valid (measured in seconds) -->