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 javax.persistence.EntityManager;
28 import javax.persistence.EntityManagerFactory;
29 import org.collectionspace.services.account.AccountsCommon;
30 import org.collectionspace.services.account.storage.csidp.UserStorageClient;
31 import org.collectionspace.services.authentication.User;
32 import org.collectionspace.services.common.context.ServiceContext;
33 import org.collectionspace.services.common.document.BadRequestException;
34 import org.collectionspace.services.common.document.DocumentException;
35 import org.collectionspace.services.common.document.DocumentHandler;
36 import org.collectionspace.services.common.document.DocumentHandler.Action;
37 import org.collectionspace.services.common.document.DocumentNotFoundException;
38 import org.collectionspace.services.common.document.DocumentWrapper;
39 import org.collectionspace.services.common.document.DocumentWrapperImpl;
40 import org.collectionspace.services.common.document.JaxbUtils;
41 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
42 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 * AccountStorageClient deals with both Account and CSIP's
49 * state in persistent storage. The rationale behind creating this class is that
50 * this class manages pesistence for both account and CSIP's user. Transactions
51 * are used where possible to permorme the persistence operations atomically.
54 public class AccountStorageClient extends JpaStorageClientImpl {
56 private final Logger logger = LoggerFactory.getLogger(AccountStorageClient.class);
57 private UserStorageClient userStorageClient = new UserStorageClient();
59 public AccountStorageClient() {
63 public String create(ServiceContext ctx,
64 DocumentHandler handler) throws BadRequestException,
68 throw new IllegalArgumentException(
69 "AccountStorageClient.create : ctx is missing");
71 if (handler == null) {
72 throw new IllegalArgumentException(
73 "AccountStorageClient.create: handler is missing");
75 EntityManagerFactory emf = null;
76 EntityManager em = null;
77 AccountsCommon account = (AccountsCommon) handler.getCommonPart();
79 handler.prepare(Action.CREATE);
80 DocumentWrapper<AccountsCommon> wrapDoc =
81 new DocumentWrapperImpl<AccountsCommon>(account);
82 handler.handle(Action.CREATE, wrapDoc);
83 emf = JpaStorageUtils.getEntityManagerFactory();
84 em = emf.createEntityManager();
85 em.getTransaction().begin();
86 //if userid and password are given, add to default id provider
87 if (account.getUserId() != null &&
88 isForCSIdP(account.getPassword())) {
89 User user = userStorageClient.create(account.getUserId(),
90 account.getPassword());
93 // if (accountReceived.getTenant() != null) {
94 // UserTenant ut = createTenantAssoc(accountReceived);
97 account.setCreatedAtItem(new Date());
99 em.getTransaction().commit();
100 handler.complete(Action.CREATE, wrapDoc);
101 return (String) JaxbUtils.getValue(account, "getCsid");
102 } catch (BadRequestException bre) {
103 if (em != null && em.getTransaction().isActive()) {
104 em.getTransaction().rollback();
107 } catch (Exception e) {
108 if (logger.isDebugEnabled()) {
109 logger.debug("Caught exception ", e);
111 boolean uniqueConstraint = false;
112 if (userStorageClient.get(em, account.getUserId()) != null) {
113 //might be unique constraint violation
114 uniqueConstraint = true;
116 if (em != null && em.getTransaction().isActive()) {
117 em.getTransaction().rollback();
119 if (uniqueConstraint) {
120 String msg = "UserId exists. Non unique userId=" + account.getUserId();
122 throw new BadRequestException(msg);
124 throw new DocumentException(e);
127 JpaStorageUtils.releaseEntityManagerFactory(emf);
133 public void update(ServiceContext ctx, String id, DocumentHandler handler)
134 throws BadRequestException, DocumentNotFoundException,
137 throw new IllegalArgumentException(
138 "AccountStorageClient.update : ctx is missing");
140 if (handler == null) {
141 throw new IllegalArgumentException(
142 "AccountStorageClient.update: handler is missing");
144 EntityManagerFactory emf = null;
145 EntityManager em = null;
147 handler.prepare(Action.UPDATE);
148 AccountsCommon accountReceived = (AccountsCommon) handler.getCommonPart();
149 emf = JpaStorageUtils.getEntityManagerFactory();
150 em = emf.createEntityManager();
151 em.getTransaction().begin();
152 AccountsCommon accountFound = getAccount(em, id);
153 checkAllowedUpdates(accountReceived, accountFound);
154 //if userid and password are given, add to default id provider
155 if (accountReceived.getUserId() != null
156 && isForCSIdP(accountReceived.getPassword())) {
157 userStorageClient.update(em,
158 accountReceived.getUserId(),
159 accountReceived.getPassword());
161 DocumentWrapper<AccountsCommon> wrapDoc =
162 new DocumentWrapperImpl<AccountsCommon>(accountFound);
163 handler.handle(Action.UPDATE, wrapDoc);
164 em.getTransaction().commit();
165 handler.complete(Action.UPDATE, wrapDoc);
166 } catch (BadRequestException bre) {
167 if (em != null && em.getTransaction().isActive()) {
168 em.getTransaction().rollback();
171 } catch (DocumentException de) {
172 if (em != null && em.getTransaction().isActive()) {
173 em.getTransaction().rollback();
176 } catch (Exception e) {
177 if (logger.isDebugEnabled()) {
178 logger.debug("Caught exception ", e);
180 throw new DocumentException(e);
183 JpaStorageUtils.releaseEntityManagerFactory(emf);
189 public void delete(ServiceContext ctx, String id)
190 throws DocumentNotFoundException,
193 if (logger.isDebugEnabled()) {
194 logger.debug("deleting entity with id=" + id);
197 throw new IllegalArgumentException(
198 "AccountStorageClient.delete : ctx is missing");
200 EntityManagerFactory emf = null;
201 EntityManager em = null;
203 emf = JpaStorageUtils.getEntityManagerFactory();
204 em = emf.createEntityManager();
206 AccountsCommon accountFound = getAccount(em, id);
207 em.getTransaction().begin();
208 //if userid gives any indication about the id provider, it should
209 //be used to avoid delete
210 userStorageClient.delete(em, accountFound.getUserId());
211 em.remove(accountFound);
212 em.getTransaction().commit();
214 } catch (DocumentException de) {
215 if (em != null && em.getTransaction().isActive()) {
216 em.getTransaction().rollback();
219 } catch (Exception e) {
220 if (logger.isDebugEnabled()) {
221 logger.debug("Caught exception ", e);
223 if (em != null && em.getTransaction().isActive()) {
224 em.getTransaction().rollback();
226 throw new DocumentException(e);
229 JpaStorageUtils.releaseEntityManagerFactory(emf);
234 private AccountsCommon getAccount(EntityManager em, String id) throws DocumentNotFoundException {
235 AccountsCommon accountFound = em.find(AccountsCommon.class, id);
236 if (accountFound == null) {
237 if (em != null && em.getTransaction().isActive()) {
238 em.getTransaction().rollback();
240 String msg = "could not find account with id=" + id;
242 throw new DocumentNotFoundException(msg);
247 private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException {
248 if (!fromAccount.getUserId().equals(toAccount.getUserId())) {
249 String msg = "userId=" + toAccount.getUserId() + " of existing account does not match "
250 + "the userId=" + fromAccount.getUserId()
251 + " with csid=" + fromAccount.getCsid();
253 if (logger.isDebugEnabled()) {
254 logger.debug(msg + " found userid=" + fromAccount.getUserId());
256 throw new BadRequestException(msg);
262 * isForCSIdP deteremines if the create/update is also needed for CS IdP
266 private boolean isForCSIdP(byte[] bpass) {
267 return bpass != null && bpass.length > 0;
269 // private UserTenant createTenantAssoc(AccountsCommon accountReceived) {
270 // UserTenant userTenant = new UserTenant();
271 // userTenant.setUserId(accountReceived.getUserId());
272 // List<AccountsCommon.Tenant> atl = accountReceived.getTenant();
273 // List<UserTenant.Tenant> utl =
274 // new ArrayList<UserTenant.Tenant>();
275 // for (AccountsCommon.Tenant at : atl) {
276 // UserTenant.Tenant ut = new UserTenant.Tenant();
277 // ut.setId(at.getId());
278 // ut.setName(at.getName());
281 // userTenant.setTenant(utl);
282 // return userTenant;