1 package org.collectionspace.services.jaxrs;
3 import javax.servlet.ServletContextEvent;
4 import javax.ws.rs.core.Response;
6 import org.jboss.resteasy.core.Dispatcher;
7 import org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap;
9 import org.collectionspace.authentication.CSpaceTenant;
10 import org.collectionspace.services.account.Tenant;
11 import org.collectionspace.services.account.TenantResource;
12 import org.collectionspace.services.authorization.AuthZ;
13 import org.collectionspace.services.client.AuthorityClient;
14 import org.collectionspace.services.common.CSWebApplicationException;
15 import org.collectionspace.services.common.ResourceMap;
16 import org.collectionspace.services.common.ServiceMain;
17 import org.collectionspace.services.common.api.RefName;
18 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
19 import org.collectionspace.services.common.vocabulary.AuthorityResource;
20 import org.collectionspace.services.config.service.AuthorityInstanceType;
21 import org.collectionspace.services.config.service.ServiceBindingType;
22 import org.collectionspace.services.config.service.ServiceBindingType.AuthorityInstanceList;
23 import org.collectionspace.services.config.service.Term;
24 import org.collectionspace.services.config.service.TermList;
25 import org.collectionspace.services.config.tenant.TenantBindingType;
27 import java.lang.reflect.Constructor;
28 import java.util.Date;
29 import java.util.Hashtable;
30 import java.util.List;
31 import java.util.logging.Level;
33 public class CSpaceResteasyBootstrap extends ResteasyBootstrap {
35 java.util.logging.Logger logger = java.util.logging.Logger.getAnonymousLogger();
36 static final String RESET_AUTHORITIES_PROPERTY = "org.collectionspace.services.authorities.reset";
39 public void contextInitialized(ServletContextEvent event) {
42 // This call to super instantiates and initializes our JAX-RS application class.
43 // The application class is org.collectionspace.services.jaxrs.CollectionSpaceJaxRsApplication.
45 logger.log(Level.INFO, String.format("%tc [INFO] Starting up the CollectionSpace Services' JAX-RS application.", new Date()));
46 super.contextInitialized(event);
47 CollectionSpaceJaxRsApplication app = (CollectionSpaceJaxRsApplication)deployment.getApplication();
48 Dispatcher disp = deployment.getDispatcher();
49 disp.getDefaultContextObjects().put(ResourceMap.class, app.getResourceMap());
51 String resetAuthsString = System.getProperty(RESET_AUTHORITIES_PROPERTY, Boolean.FALSE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file
52 initializeAuthorities(app.getResourceMap(), Boolean.valueOf(resetAuthsString));
54 logger.log(Level.INFO, String.format("%tc [INFO] CollectionSpace Services' JAX-RS application started.", new Date()));
55 } catch (Exception e) {
57 throw new RuntimeException(e);
63 public void contextDestroyed(ServletContextEvent event) {
64 logger.log(Level.INFO, "[INFO] Shutting down the CollectionSpace Services' JAX-RS application.");
65 //Do something if needed.
66 logger.log(Level.INFO, "[INFO] CollectionSpace Services' JAX-RS application stopped.");
70 * Initialize all authorities and vocabularies defined in the service bindings.
74 public void initializeAuthorities(ResourceMap resourceMap, boolean reset) throws Exception {
75 TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
76 Hashtable<String, TenantBindingType> tenantBindingsTable = tenantBindingConfigReader.getTenantBindings(false);
77 for (TenantBindingType tenantBindings : tenantBindingsTable.values()) {
78 CSpaceTenant tenant = new CSpaceTenant(tenantBindings.getId(), tenantBindings.getName());
79 if (shouldInitializeAuthorities(tenant, reset) == true) {
80 for (ServiceBindingType serviceBinding : tenantBindings.getServiceBindings()) {
81 AuthorityInstanceList element = serviceBinding.getAuthorityInstanceList();
82 if (element != null && element.getAuthorityInstance() != null) {
83 List<AuthorityInstanceType> authorityInstanceList = element.getAuthorityInstance();
84 for (AuthorityInstanceType authorityInstance : authorityInstanceList) {
86 initializeAuthorityInstance(resourceMap, authorityInstance, serviceBinding, tenant, reset);
87 } catch (Exception e) {
88 logger.log(Level.SEVERE, "Could not initialize authorities and authority terms: " + e.getMessage());
95 // If we made it this far, we've either created the tenant's authorities and terms or we've reset them. Either way,
96 // we should mark the isAuthoritiesInitialized field of the tenant to 'true'.
98 setAuthoritiesInitialized(tenant, true);
103 @SuppressWarnings("rawtypes")
104 private AuthorityClient getAuthorityClient(String classname) throws Exception {
105 Class clazz = Class.forName(classname.trim());
106 Constructor co = clazz.getConstructor(null);
107 Object classInstance = co.newInstance(null);
108 return (AuthorityClient) classInstance;
111 private boolean shouldInitializeAuthorities(CSpaceTenant cspaceTenant, boolean reset) {
112 AuthZ.get().login(); // login as super admin
113 TenantResource tenantResource = new TenantResource();
114 Tenant tenantState = tenantResource.getTenant(cspaceTenant.getId());
117 // If the tenant's authorities have been initialized and
118 // we're not being asked to reset them, we'll return 'false'
119 // making any changes
121 return tenantState.isAuthoritiesInitialized() == false || reset == true;
124 private void setAuthoritiesInitialized(CSpaceTenant cspaceTenant, boolean initState) {
125 AuthZ.get().login(); // login as super admin
126 TenantResource tenantResource = new TenantResource();
127 Tenant tenantState = tenantResource.getTenant(cspaceTenant.getId());
129 tenantState.setAuthoritiesInitialized(initState);
130 tenantResource.updateTenant(cspaceTenant.getId(), tenantState);
135 * Check to see if an an authority instance and its corresponding terms exist. If not, try to create them.
137 private void initializeAuthorityInstance(ResourceMap resourceMap,
138 AuthorityInstanceType authorityInstance,
139 ServiceBindingType serviceBinding,
140 CSpaceTenant cspaceTenant,
141 boolean reset) throws Exception {
143 Response response = null;
144 String serviceName = serviceBinding.getName();
146 AuthZ.get().login(cspaceTenant);
147 String clientClassName = serviceBinding.getClientHandler();
148 AuthorityClient client = getAuthorityClient(clientClassName);
149 String authoritySpecifier = RefName.shortIdToPath(authorityInstance.getTitleRef()); // e.g., urn:cspace:name(ulan)
152 // Test to see if the authority instance exists already.
154 AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(serviceName.toLowerCase());
156 response = authorityResource.get(null, null, authoritySpecifier);
157 } catch (CSWebApplicationException e) {
158 response = e.getResponse(); // If the authority doesn't exist, we expect a 404 error
162 // If it doesn't exist (status is not 200), then try to create the authority instance
164 status = response.getStatus();
165 if (status != Response.Status.OK.getStatusCode()) {
166 String xmlPayload = client.createAuthorityInstance(authorityInstance.getTitleRef(), authorityInstance.getTitle());
167 response = authorityResource.createAuthority(xmlPayload);
168 status = response.getStatus();
169 if (status != Response.Status.CREATED.getStatusCode()) {
170 throw new CSWebApplicationException(response);
174 if (status == Response.Status.OK.getStatusCode()) {
175 logger.log(Level.FINE, String.format("Authority of type '%s' with the short ID of '%s' existed already.",
176 serviceName, authorityInstance.getTitleRef()));
177 } else if (status == Response.Status.CREATED.getStatusCode()) {
178 logger.log(Level.INFO, String.format("Created a new authority of type '%s' with the short ID of '%s'.",
179 serviceName, authorityInstance.getTitleRef()));
181 logger.log(Level.WARNING, String.format("Unknown status '%d' encountered when creating or fetching authority of type '%s' with the short ID of '%s'.",
182 serviceName, authorityInstance.getTitleRef()));
186 // Next, try to create or verify the authority terms.
188 initializeAuthorityInstanceTerms(authorityResource, client, authoritySpecifier, resourceMap, authorityInstance, serviceName, cspaceTenant);
191 private void initializeAuthorityInstanceTerms(
192 AuthorityResource authorityResource,
193 AuthorityClient client,
194 String authoritySpecifier,
195 ResourceMap resourceMap,
196 AuthorityInstanceType authorityInstance,
198 CSpaceTenant tenant) throws Exception {
201 Response response = null;
203 TermList termListElement = authorityInstance.getTermList();
204 if (termListElement == null) {
208 for (Term term : termListElement.getTerm()) {
210 // Check to see if the term already exists
213 String termSpecifier = RefName.shortIdToPath(term.getId());
214 authorityResource.getAuthorityItem(null, null, resourceMap, authoritySpecifier, termSpecifier);
215 status = Response.Status.OK.getStatusCode();
216 } catch (CSWebApplicationException e) {
217 response = e.getResponse(); // If the authority doesn't exist, we expect a 404 error
218 status = response.getStatus();
222 // If the term doesn't exist, create it.
224 if (status != Response.Status.OK.getStatusCode()) {
225 String termShortId = term.getId();
226 String termDisplayName = term.getContent().trim();
227 String xmlPayload = client.createAuthorityItemInstance(termShortId, termDisplayName);
229 authorityResource.createAuthorityItem(resourceMap, null, authoritySpecifier, xmlPayload);
230 logger.log(Level.INFO, String.format("Created a new term '%s:%s' in the authority of type '%s' with the short ID of '%s'.",
231 termDisplayName, termShortId, serviceName, authorityInstance.getTitleRef()));
232 } catch (CSWebApplicationException e) {
233 response = e.getResponse();
234 status = response.getStatus();
235 if (status != Response.Status.CREATED.getStatusCode()) {
236 throw new CSWebApplicationException(response);