2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
24 package org.collectionspace.services.account.storage;
26 import java.util.Date;
27 import java.util.HashMap;
28 import javax.persistence.EntityManager;
29 import javax.persistence.EntityManagerFactory;
31 import org.collectionspace.services.account.AccountsCommon;
32 import org.collectionspace.services.account.storage.csidp.UserStorageClient;
33 import org.collectionspace.services.authentication.User;
34 import org.collectionspace.services.common.context.ServiceContext;
35 import org.collectionspace.services.common.document.BadRequestException;
36 import org.collectionspace.services.common.document.DocumentException;
37 import org.collectionspace.services.common.document.DocumentFilter;
38 import org.collectionspace.services.common.document.DocumentHandler;
39 import org.collectionspace.services.common.document.DocumentHandler.Action;
40 import org.collectionspace.services.common.document.DocumentNotFoundException;
41 import org.collectionspace.services.common.document.DocumentWrapper;
42 import org.collectionspace.services.common.document.DocumentWrapperImpl;
43 import org.collectionspace.services.common.document.JaxbUtils;
44 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
45 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
51 * AccountStorageClient deals with both Account and CSIdP's
52 * state in persistent storage. The rationale behind creating this class is that
53 * this class manages pesistence for both account and CSIP's user. Transactions
54 * are used where possible to permorme the persistence operations atomically.
57 public class AccountStorageClient extends JpaStorageClientImpl {
59 private final Logger logger = LoggerFactory.getLogger(AccountStorageClient.class);
60 private UserStorageClient userStorageClient = new UserStorageClient();
62 public AccountStorageClient() {
66 public String create(ServiceContext ctx,
67 DocumentHandler handler) throws BadRequestException,
71 throw new IllegalArgumentException(
72 "AccountStorageClient.create : ctx is missing");
74 if (handler == null) {
75 throw new IllegalArgumentException(
76 "AccountStorageClient.create: handler is missing");
78 EntityManagerFactory emf = null;
79 EntityManager em = null;
80 AccountsCommon account = (AccountsCommon) handler.getCommonPart();
82 handler.prepare(Action.CREATE);
83 DocumentWrapper<AccountsCommon> wrapDoc =
84 new DocumentWrapperImpl<AccountsCommon>(account);
85 handler.handle(Action.CREATE, wrapDoc);
86 emf = JpaStorageUtils.getEntityManagerFactory();
87 em = emf.createEntityManager();
88 em.getTransaction().begin();
89 //if userid and password are given, add to default id provider
90 if (account.getUserId() != null &&
91 isForCSIdP(account.getPassword())) {
92 User user = userStorageClient.create(account.getUserId(),
93 account.getPassword());
96 // if (accountReceived.getTenant() != null) {
97 // UserTenant ut = createTenantAssoc(accountReceived);
100 account.setCreatedAtItem(new Date());
102 em.getTransaction().commit();
103 handler.complete(Action.CREATE, wrapDoc);
104 return (String) JaxbUtils.getValue(account, "getCsid");
105 } catch (BadRequestException bre) {
106 if (em != null && em.getTransaction().isActive()) {
107 em.getTransaction().rollback();
110 } catch (Exception e) {
111 if (logger.isDebugEnabled()) {
112 logger.debug("Caught exception ", e);
114 boolean uniqueConstraint = false;
115 if (userStorageClient.get(em, account.getUserId()) != null) {
116 //might be unique constraint violation
117 uniqueConstraint = true;
119 if (em != null && em.getTransaction().isActive()) {
120 em.getTransaction().rollback();
122 if (uniqueConstraint) {
123 String msg = "UserId exists. Non unique userId=" + account.getUserId();
125 throw new BadRequestException(msg);
127 throw new DocumentException(e);
130 JpaStorageUtils.releaseEntityManagerFactory(emf);
136 public void get(ServiceContext ctx, String id, DocumentHandler handler)
137 throws DocumentNotFoundException, DocumentException {
139 throw new IllegalArgumentException(
140 "get: ctx is missing");
142 if (handler == null) {
143 throw new IllegalArgumentException(
144 "get: handler is missing");
146 DocumentFilter docFilter = handler.getDocumentFilter();
147 if (docFilter == null) {
148 docFilter = handler.createDocumentFilter();
152 handler.prepare(Action.GET);
154 String whereClause = " JOIN a.tenants as at where csid = :csid and at.tenantId = :tenantId";
155 HashMap<String, Object> params = new HashMap<String, Object>();
156 params.put("csid", id);
157 params.put("tenantId", ctx.getTenantId());
159 o = JpaStorageUtils.getEntity(
160 "org.collectionspace.services.account.AccountsCommon", whereClause, params);
162 String msg = "could not find entity with id=" + id;
163 throw new DocumentNotFoundException(msg);
165 DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(o);
166 handler.handle(Action.GET, wrapDoc);
167 handler.complete(Action.GET, wrapDoc);
168 } catch (DocumentException de) {
170 } catch (Exception e) {
171 if (logger.isDebugEnabled()) {
172 logger.debug("Caught exception ", e);
174 throw new DocumentException(e);
179 public void update(ServiceContext ctx, String id, DocumentHandler handler)
180 throws BadRequestException, DocumentNotFoundException,
183 throw new IllegalArgumentException(
184 "AccountStorageClient.update : ctx is missing");
186 if (handler == null) {
187 throw new IllegalArgumentException(
188 "AccountStorageClient.update: handler is missing");
190 EntityManagerFactory emf = null;
191 EntityManager em = null;
193 handler.prepare(Action.UPDATE);
194 AccountsCommon accountReceived = (AccountsCommon) handler.getCommonPart();
195 emf = JpaStorageUtils.getEntityManagerFactory();
196 em = emf.createEntityManager();
197 em.getTransaction().begin();
198 AccountsCommon accountFound = getAccount(em, id);
199 checkAllowedUpdates(accountReceived, accountFound);
200 //if userid and password are given, add to default id provider
201 // Note that this ignores the immutable flag, as we allow
203 if (accountReceived.getUserId() != null
204 && isForCSIdP(accountReceived.getPassword())) {
205 userStorageClient.update(em,
206 accountReceived.getUserId(),
207 accountReceived.getPassword());
209 DocumentWrapper<AccountsCommon> wrapDoc =
210 new DocumentWrapperImpl<AccountsCommon>(accountFound);
211 handler.handle(Action.UPDATE, wrapDoc);
212 em.getTransaction().commit();
213 handler.complete(Action.UPDATE, wrapDoc);
214 } catch (BadRequestException bre) {
215 if (em != null && em.getTransaction().isActive()) {
216 em.getTransaction().rollback();
219 } catch (DocumentException de) {
220 if (em != null && em.getTransaction().isActive()) {
221 em.getTransaction().rollback();
224 } catch (Exception e) {
225 if (logger.isDebugEnabled()) {
226 logger.debug("Caught exception ", e);
228 throw new DocumentException(e);
231 JpaStorageUtils.releaseEntityManagerFactory(emf);
237 public void delete(ServiceContext ctx, String id)
238 throws DocumentNotFoundException,
241 if (logger.isDebugEnabled()) {
242 logger.debug("deleting entity with id=" + id);
245 throw new IllegalArgumentException(
246 "AccountStorageClient.delete : ctx is missing");
248 EntityManagerFactory emf = null;
249 EntityManager em = null;
251 emf = JpaStorageUtils.getEntityManagerFactory();
252 em = emf.createEntityManager();
254 AccountsCommon accountFound = getAccount(em, id);
255 em.getTransaction().begin();
256 //if userid gives any indication about the id provider, it should
257 //be used to avoid delete
258 userStorageClient.delete(em, accountFound.getUserId());
259 em.remove(accountFound);
260 em.getTransaction().commit();
262 } catch (DocumentException de) {
263 if (em != null && em.getTransaction().isActive()) {
264 em.getTransaction().rollback();
267 } catch (Exception e) {
268 if (logger.isDebugEnabled()) {
269 logger.debug("Caught exception ", e);
271 if (em != null && em.getTransaction().isActive()) {
272 em.getTransaction().rollback();
274 throw new DocumentException(e);
277 JpaStorageUtils.releaseEntityManagerFactory(emf);
282 private AccountsCommon getAccount(EntityManager em, String id) throws DocumentNotFoundException {
283 AccountsCommon accountFound = em.find(AccountsCommon.class, id);
284 if (accountFound == null) {
285 if (em != null && em.getTransaction().isActive()) {
286 em.getTransaction().rollback();
288 String msg = "could not find account with id=" + id;
290 throw new DocumentNotFoundException(msg);
295 private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException {
296 if (!fromAccount.getUserId().equals(toAccount.getUserId())) {
297 String msg = "userId=" + toAccount.getUserId() + " of existing account does not match "
298 + "the userId=" + fromAccount.getUserId()
299 + " with csid=" + fromAccount.getCsid();
301 if (logger.isDebugEnabled()) {
302 logger.debug(msg + " found userid=" + fromAccount.getUserId());
304 throw new BadRequestException(msg);
310 * isForCSIdP deteremines if the create/update is also needed for CS IdP
314 private boolean isForCSIdP(byte[] bpass) {
315 return bpass != null && bpass.length > 0;
317 // private UserTenant createTenantAssoc(AccountsCommon accountReceived) {
318 // UserTenant userTenant = new UserTenant();
319 // userTenant.setUserId(accountReceived.getUserId());
320 // List<AccountsCommon.Tenant> atl = accountReceived.getTenant();
321 // List<UserTenant.Tenant> utl =
322 // new ArrayList<UserTenant.Tenant>();
323 // for (AccountsCommon.Tenant at : atl) {
324 // UserTenant.Tenant ut = new UserTenant.Tenant();
325 // ut.setId(at.getId());
326 // ut.setName(at.getName());
329 // userTenant.setTenant(utl);
330 // return userTenant;