]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
2bf5b401eb373c2f9ca8e78ad5dd2ce7fea1424a
[tmp/jakarta-migration.git] /
1 /**
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:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
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.
23  */
24 package org.collectionspace.services.account.storage;
25
26 import java.util.Date;
27 import java.util.HashMap;
28 import javax.persistence.EntityManager;
29 import javax.persistence.EntityManagerFactory;
30 import org.collectionspace.services.account.AccountsCommon;
31 import org.collectionspace.services.account.storage.csidp.UserStorageClient;
32 import org.collectionspace.services.authentication.User;
33 import org.collectionspace.services.common.context.ServiceContext;
34 import org.collectionspace.services.common.document.BadRequestException;
35 import org.collectionspace.services.common.document.DocumentException;
36 import org.collectionspace.services.common.document.DocumentFilter;
37 import org.collectionspace.services.common.document.DocumentHandler;
38 import org.collectionspace.services.common.document.DocumentHandler.Action;
39 import org.collectionspace.services.common.document.DocumentNotFoundException;
40 import org.collectionspace.services.common.document.DocumentWrapper;
41 import org.collectionspace.services.common.document.DocumentWrapperImpl;
42 import org.collectionspace.services.common.document.JaxbUtils;
43 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
44 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
45
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 /**
50  * AccountStorageClient deals with both Account and CSIdP's
51  * state in persistent storage. The rationale behind creating this class is that
52  * this class manages pesistence for both account and CSIP's user. Transactions
53  * are used where possible to permorme the persistence operations atomically.
54  * @author 
55  */
56 public class AccountStorageClient extends JpaStorageClientImpl {
57
58     private final Logger logger = LoggerFactory.getLogger(AccountStorageClient.class);
59     private UserStorageClient userStorageClient = new UserStorageClient();
60
61     public AccountStorageClient() {
62     }
63
64     @Override
65     public String create(ServiceContext ctx,
66             DocumentHandler handler) throws BadRequestException,
67             DocumentException {
68
69         if (ctx == null) {
70             throw new IllegalArgumentException(
71                     "AccountStorageClient.create : ctx is missing");
72         }
73         if (handler == null) {
74             throw new IllegalArgumentException(
75                     "AccountStorageClient.create: handler is missing");
76         }
77         EntityManagerFactory emf = null;
78         EntityManager em = null;
79         AccountsCommon account = (AccountsCommon) handler.getCommonPart();
80         try {
81             handler.prepare(Action.CREATE);
82             DocumentWrapper<AccountsCommon> wrapDoc =
83                     new DocumentWrapperImpl<AccountsCommon>(account);
84             handler.handle(Action.CREATE, wrapDoc);
85             emf = JpaStorageUtils.getEntityManagerFactory();
86             em = emf.createEntityManager();
87             em.getTransaction().begin();
88             //if userid and password are given, add to default id provider
89             if (account.getUserId() != null &&
90                     isForCSIdP(account.getPassword())) {
91                 User user = userStorageClient.create(account.getUserId(),
92                         account.getPassword());
93                 em.persist(user);
94             }
95 //            if (accountReceived.getTenant() != null) {
96 //                UserTenant ut = createTenantAssoc(accountReceived);
97 //                em.persist(ut);
98 //            }
99             account.setCreatedAtItem(new Date());
100             em.persist(account);
101             em.getTransaction().commit();
102             handler.complete(Action.CREATE, wrapDoc);
103             return (String) JaxbUtils.getValue(account, "getCsid");
104         } catch (BadRequestException bre) {
105             if (em != null && em.getTransaction().isActive()) {
106                 em.getTransaction().rollback();
107             }
108             throw bre;
109         } catch (Exception e) {
110             if (logger.isDebugEnabled()) {
111                 logger.debug("Caught exception ", e);
112             }
113             boolean uniqueConstraint = false;
114             if (userStorageClient.get(em, account.getUserId()) != null) {
115                 //might be unique constraint violation
116                 uniqueConstraint = true;
117             }
118             if (em != null && em.getTransaction().isActive()) {
119                 em.getTransaction().rollback();
120             }
121             if (uniqueConstraint) {
122                 String msg = "UserId exists. Non unique userId=" + account.getUserId();
123                 logger.error(msg);
124                 throw new BadRequestException(msg);
125             }
126             throw new DocumentException(e);
127         } finally {
128             if (em != null) {
129                 JpaStorageUtils.releaseEntityManagerFactory(emf);
130             }
131         }
132     }
133
134         @Override
135     public void get(ServiceContext ctx, String id, DocumentHandler handler)
136             throws DocumentNotFoundException, DocumentException {
137         if (ctx == null) {
138             throw new IllegalArgumentException(
139                     "get: ctx is missing");
140         }
141         if (handler == null) {
142             throw new IllegalArgumentException(
143                     "get: handler is missing");
144         }
145         DocumentFilter docFilter = handler.getDocumentFilter();
146         if (docFilter == null) {
147             docFilter = handler.createDocumentFilter();
148         }
149         EntityManagerFactory emf = null;
150         EntityManager em = null;
151         try {
152             handler.prepare(Action.GET);
153             Object o = null;
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());
158
159             o = JpaStorageUtils.getEntity(
160                     "org.collectionspace.services.account.AccountsCommon", whereClause, params);
161             if (null == o) {
162                 if (em != null && em.getTransaction().isActive()) {
163                     em.getTransaction().rollback();
164                 }
165                 String msg = "could not find entity with id=" + id;
166                 throw new DocumentNotFoundException(msg);
167             }
168             DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(o);
169             handler.handle(Action.GET, wrapDoc);
170             handler.complete(Action.GET, wrapDoc);
171         } catch (DocumentException de) {
172             throw de;
173         } catch (Exception e) {
174             if (logger.isDebugEnabled()) {
175                 logger.debug("Caught exception ", e);
176             }
177             throw new DocumentException(e);
178         } finally {
179             if (emf != null) {
180                 JpaStorageUtils.releaseEntityManagerFactory(emf);
181             }
182         }
183     }
184
185     @Override
186     public void update(ServiceContext ctx, String id, DocumentHandler handler)
187             throws BadRequestException, DocumentNotFoundException,
188             DocumentException {
189         if (ctx == null) {
190             throw new IllegalArgumentException(
191                     "AccountStorageClient.update : ctx is missing");
192         }
193         if (handler == null) {
194             throw new IllegalArgumentException(
195                     "AccountStorageClient.update: handler is missing");
196         }
197         EntityManagerFactory emf = null;
198         EntityManager em = null;
199         try {
200             handler.prepare(Action.UPDATE);
201             AccountsCommon accountReceived = (AccountsCommon) handler.getCommonPart();
202             emf = JpaStorageUtils.getEntityManagerFactory();
203             em = emf.createEntityManager();
204             em.getTransaction().begin();
205             AccountsCommon accountFound = getAccount(em, id);
206             checkAllowedUpdates(accountReceived, accountFound);
207             //if userid and password are given, add to default id provider
208             // Note that this ignores the immutable flag, as we allow
209             // password changes.
210             if (accountReceived.getUserId() != null
211                     && isForCSIdP(accountReceived.getPassword())) {
212                 userStorageClient.update(em,
213                         accountReceived.getUserId(),
214                         accountReceived.getPassword());
215             }
216             DocumentWrapper<AccountsCommon> wrapDoc =
217                     new DocumentWrapperImpl<AccountsCommon>(accountFound);
218             handler.handle(Action.UPDATE, wrapDoc);
219             em.getTransaction().commit();
220             handler.complete(Action.UPDATE, wrapDoc);
221         } catch (BadRequestException bre) {
222             if (em != null && em.getTransaction().isActive()) {
223                 em.getTransaction().rollback();
224             }
225             throw bre;
226         } catch (DocumentException de) {
227             if (em != null && em.getTransaction().isActive()) {
228                 em.getTransaction().rollback();
229             }
230             throw de;
231         } catch (Exception e) {
232             if (logger.isDebugEnabled()) {
233                 logger.debug("Caught exception ", e);
234             }
235             throw new DocumentException(e);
236         } finally {
237             if (emf != null) {
238                 JpaStorageUtils.releaseEntityManagerFactory(emf);
239             }
240         }
241     }
242
243     @Override
244     public void delete(ServiceContext ctx, String id)
245             throws DocumentNotFoundException,
246             DocumentException {
247
248         if (logger.isDebugEnabled()) {
249             logger.debug("deleting entity with id=" + id);
250         }
251         if (ctx == null) {
252             throw new IllegalArgumentException(
253                     "AccountStorageClient.delete : ctx is missing");
254         }
255         EntityManagerFactory emf = null;
256         EntityManager em = null;
257         try {
258             emf = JpaStorageUtils.getEntityManagerFactory();
259             em = emf.createEntityManager();
260
261             AccountsCommon accountFound = getAccount(em, id);
262             em.getTransaction().begin();
263             //if userid gives any indication about the id provider, it should
264             //be used to avoid  delete
265             userStorageClient.delete(em, accountFound.getUserId());
266             em.remove(accountFound);
267             em.getTransaction().commit();
268
269         } catch (DocumentException de) {
270             if (em != null && em.getTransaction().isActive()) {
271                 em.getTransaction().rollback();
272             }
273             throw de;
274         } catch (Exception e) {
275             if (logger.isDebugEnabled()) {
276                 logger.debug("Caught exception ", e);
277             }
278             if (em != null && em.getTransaction().isActive()) {
279                 em.getTransaction().rollback();
280             }
281             throw new DocumentException(e);
282         } finally {
283             if (emf != null) {
284                 JpaStorageUtils.releaseEntityManagerFactory(emf);
285             }
286         }
287     }
288
289     private AccountsCommon getAccount(EntityManager em, String id) throws DocumentNotFoundException {
290         AccountsCommon accountFound = em.find(AccountsCommon.class, id);
291         if (accountFound == null) {
292             if (em != null && em.getTransaction().isActive()) {
293                 em.getTransaction().rollback();
294             }
295             String msg = "could not find account with id=" + id;
296             logger.error(msg);
297             throw new DocumentNotFoundException(msg);
298         }
299         return accountFound;
300     }
301
302     private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException {
303         if (!fromAccount.getUserId().equals(toAccount.getUserId())) {
304             String msg = "userId=" + toAccount.getUserId() + " of existing account does not match "
305                     + "the userId=" + fromAccount.getUserId()
306                     + " with csid=" + fromAccount.getCsid();
307             logger.error(msg);
308             if (logger.isDebugEnabled()) {
309                 logger.debug(msg + " found userid=" + fromAccount.getUserId());
310             }
311             throw new BadRequestException(msg);
312         }
313         return true;
314     }
315
316     /**
317      * isForCSIdP deteremines if the create/update is also needed for CS IdP
318      * @param bpass
319      * @return
320      */
321     private boolean isForCSIdP(byte[] bpass) {
322         return bpass != null && bpass.length > 0;
323     }
324 //    private UserTenant createTenantAssoc(AccountsCommon accountReceived) {
325 //        UserTenant userTenant = new UserTenant();
326 //        userTenant.setUserId(accountReceived.getUserId());
327 //        List<AccountsCommon.Tenant> atl = accountReceived.getTenant();
328 //        List<UserTenant.Tenant> utl =
329 //                new ArrayList<UserTenant.Tenant>();
330 //        for (AccountsCommon.Tenant at : atl) {
331 //            UserTenant.Tenant ut = new UserTenant.Tenant();
332 //            ut.setId(at.getId());
333 //            ut.setName(at.getName());
334 //            utl.add(ut);
335 //        }
336 //        userTenant.setTenant(utl);
337 //        return userTenant;
338 //    }
339 }