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;
15 import org.collectionspace.services.common.CSWebApplicationException;
16 import org.collectionspace.services.common.ResourceMap;
17 import org.collectionspace.services.common.ServiceMain;
18 import org.collectionspace.services.common.api.RefName;
19 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
20 import org.collectionspace.services.common.vocabulary.AuthorityResource;
22 import org.collectionspace.services.config.service.AuthorityInstanceType;
23 import org.collectionspace.services.config.service.ServiceBindingType;
24 import org.collectionspace.services.config.service.ServiceBindingType.AuthorityInstanceList;
25 import org.collectionspace.services.config.service.Term;
26 import org.collectionspace.services.config.service.TermList;
27 import org.collectionspace.services.config.tenant.TenantBindingType;
29 import java.lang.reflect.Constructor;
30 import java.util.Date;
31 import java.util.Hashtable;
32 import java.util.List;
33 import java.util.logging.Level;
35 public class CSpaceResteasyBootstrap extends ResteasyBootstrap {
37 java.util.logging.Logger logger = java.util.logging.Logger.getAnonymousLogger();
38 static final String RESET_AUTHORITIES_PROPERTY = "org.collectionspace.services.authorities.reset";
39 private static final String QUICK_BOOT_PROPERTY = "org.collectionspace.services.quickboot";
42 public void contextInitialized(ServletContextEvent event) {
45 // This call to super instantiates and initializes our JAX-RS application class.
46 // The application class is org.collectionspace.services.jaxrs.CollectionSpaceJaxRsApplication.
48 logger.log(Level.INFO, String.format("%tc [INFO] Starting up the CollectionSpace Services' JAX-RS application.", new Date()));
49 super.contextInitialized(event);
50 CollectionSpaceJaxRsApplication app = (CollectionSpaceJaxRsApplication)deployment.getApplication();
51 Dispatcher disp = deployment.getDispatcher();
52 disp.getDefaultContextObjects().put(ResourceMap.class, app.getResourceMap());
54 String quickBoot = System.getProperty(QUICK_BOOT_PROPERTY, Boolean.FALSE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file
55 if (Boolean.valueOf(quickBoot) == false) {
56 String resetAuthsString = System.getProperty(RESET_AUTHORITIES_PROPERTY, Boolean.FALSE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file
57 initializeAuthorities(app.getResourceMap(), Boolean.valueOf(resetAuthsString));
60 logger.log(Level.INFO, String.format("%tc [INFO] CollectionSpace Services' JAX-RS application started.", new Date()));
61 } catch (Exception e) {
63 throw new RuntimeException(e);
69 public void contextDestroyed(ServletContextEvent event) {
70 logger.log(Level.INFO, "[INFO] Shutting down the CollectionSpace Services' JAX-RS application.");
71 //Do something if needed.
72 logger.log(Level.INFO, "[INFO] CollectionSpace Services' JAX-RS application stopped.");
76 * Initialize all authorities and vocabularies defined in the service bindings.
80 public void initializeAuthorities(ResourceMap resourceMap, boolean reset) throws Exception {
81 TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader();
82 Hashtable<String, TenantBindingType> tenantBindingsTable = tenantBindingConfigReader.getTenantBindings(false);
83 for (TenantBindingType tenantBindings : tenantBindingsTable.values()) {
84 CSpaceTenant tenant = new CSpaceTenant(tenantBindings.getId(), tenantBindings.getName());
85 if (shouldInitializeAuthorities(tenant, reset) == true) {
86 for (ServiceBindingType serviceBinding : tenantBindings.getServiceBindings()) {
87 AuthorityInstanceList element = serviceBinding.getAuthorityInstanceList();
88 if (element != null && element.getAuthorityInstance() != null) {
89 List<AuthorityInstanceType> authorityInstanceList = element.getAuthorityInstance();
90 for (AuthorityInstanceType authorityInstance : authorityInstanceList) {
92 initializeAuthorityInstance(resourceMap, authorityInstance, serviceBinding, tenant, reset);
93 } catch (Exception e) {
94 logger.log(Level.SEVERE, "Could not initialize authorities and authority terms: " + e.getMessage());
101 // If we made it this far, we've either created the tenant's authorities and terms or we've reset them. Either way,
102 // we should mark the isAuthoritiesInitialized field of the tenant to 'true'.
104 setAuthoritiesInitialized(tenant, true);
109 @SuppressWarnings("rawtypes")
110 private AuthorityClient getAuthorityClient(String classname) throws Exception {
111 Class clazz = Class.forName(classname.trim());
112 Constructor co = clazz.getConstructor(null);
113 Object classInstance = co.newInstance(null);
114 return (AuthorityClient) classInstance;
117 private boolean shouldInitializeAuthorities(CSpaceTenant cspaceTenant, boolean reset) {
118 AuthZ.get().login(); // login as super admin
119 TenantResource tenantResource = new TenantResource();
120 Tenant tenantState = tenantResource.getTenant(cspaceTenant.getId());
123 // If the tenant's authorities have been initialized and
124 // we're not being asked to reset them, we'll return 'false'
125 // making any changes
127 return tenantState.isAuthoritiesInitialized() == false || reset == true;
130 private void setAuthoritiesInitialized(CSpaceTenant cspaceTenant, boolean initState) {
131 AuthZ.get().login(); // login as super admin
132 TenantResource tenantResource = new TenantResource();
133 Tenant tenantState = tenantResource.getTenant(cspaceTenant.getId());
135 tenantState.setAuthoritiesInitialized(initState);
136 tenantResource.updateTenant(cspaceTenant.getId(), tenantState);
141 * Check to see if an an authority instance and its corresponding terms exist. If not, try to create them.
143 private void initializeAuthorityInstance(ResourceMap resourceMap,
144 AuthorityInstanceType authorityInstance,
145 ServiceBindingType serviceBinding,
146 CSpaceTenant cspaceTenant,
147 boolean reset) throws Exception {
149 Response response = null;
150 String serviceName = serviceBinding.getName();
152 AuthZ.get().login(cspaceTenant);
153 String clientClassName = serviceBinding.getClientHandler();
154 AuthorityClient client = getAuthorityClient(clientClassName);
155 String authoritySpecifier = RefName.shortIdToPath(authorityInstance.getTitleRef()); // e.g., urn:cspace:name(ulan)
158 // Test to see if the authority instance exists already.
160 AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(serviceName.toLowerCase());
162 response = authorityResource.get(null, null, authoritySpecifier);
163 } catch (CSWebApplicationException e) {
164 response = e.getResponse(); // If the authority doesn't exist, we expect a 404 error
168 // If it doesn't exist (status is not 200), then try to create the authority instance
170 status = response.getStatus();
171 if (status != Response.Status.OK.getStatusCode()) {
172 String xmlPayload = client.createAuthorityInstance(authorityInstance.getTitleRef(), authorityInstance.getTitle());
173 response = authorityResource.createAuthority(xmlPayload);
174 status = response.getStatus();
175 if (status != Response.Status.CREATED.getStatusCode()) {
176 throw new CSWebApplicationException(response);
180 if (status == Response.Status.OK.getStatusCode()) {
181 logger.log(Level.FINE, String.format("Authority of type '%s' with the short ID of '%s' existed already.",
182 serviceName, authorityInstance.getTitleRef()));
183 } else if (status == Response.Status.CREATED.getStatusCode()) {
184 logger.log(Level.INFO, String.format("Created a new authority of type '%s' with the short ID of '%s'.",
185 serviceName, authorityInstance.getTitleRef()));
187 logger.log(Level.WARNING, String.format("Unknown status '%d' encountered when creating or fetching authority of type '%s' with the short ID of '%s'.",
188 serviceName, authorityInstance.getTitleRef()));
192 // Next, try to create or verify the authority terms.
194 initializeAuthorityInstanceTerms(authorityResource, client, authoritySpecifier, resourceMap, authorityInstance, serviceName, cspaceTenant);
197 private void initializeAuthorityInstanceTerms(
198 AuthorityResource authorityResource,
199 AuthorityClient client,
200 String authoritySpecifier,
201 ResourceMap resourceMap,
202 AuthorityInstanceType authorityInstance,
204 CSpaceTenant tenant) throws Exception {
207 Response response = null;
209 TermList termListElement = authorityInstance.getTermList();
210 if (termListElement == null) {
214 for (Term term : termListElement.getTerm()) {
216 // Check to see if the term already exists
219 String termSpecifier = RefName.shortIdToPath(term.getId());
220 authorityResource.getAuthorityItem(null, null, resourceMap, authoritySpecifier, termSpecifier);
221 status = Response.Status.OK.getStatusCode();
222 } catch (CSWebApplicationException e) {
223 response = e.getResponse(); // If the authority doesn't exist, we expect a 404 error
224 status = response.getStatus();
228 // If the term doesn't exist, create it.
230 if (status != Response.Status.OK.getStatusCode()) {
231 String termShortId = term.getId();
232 String termDisplayName = term.getContent().trim();
233 String xmlPayload = client.createAuthorityItemInstance(termShortId, termDisplayName);
235 authorityResource.createAuthorityItem(resourceMap, null, authoritySpecifier, xmlPayload);
236 logger.log(Level.FINE, String.format("Created a new term '%s:%s' in the authority of type '%s' with the short ID of '%s'.",
237 termDisplayName, termShortId, serviceName, authorityInstance.getTitleRef()));
238 } catch (CSWebApplicationException e) {
239 response = e.getResponse();
240 status = response.getStatus();
241 if (status != Response.Status.CREATED.getStatusCode()) {
242 throw new CSWebApplicationException(response);