]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
cd54e782ba1fffa9f65a99ebf68d9e5d31c0ea5b
[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 javax.persistence.EntityManager;
28 import javax.persistence.EntityManagerFactory;
29 import javax.persistence.Query;
30 import org.collectionspace.services.account.AccountsCommon;
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.security.SecurityUtils;
42 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
43 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
44
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 /**
49  * AccountStorageClient deals with both Account and CSIP's
50  * state in persistent storage. The rationale behind creating this class is that
51  * this class manages pesistence for both account and CSIP's user. Transactions
52  * are used where possible to permorme the persistence operations atomically.
53  * @author 
54  */
55 public class AccountStorageClient extends JpaStorageClientImpl {
56
57     private final Logger logger = LoggerFactory.getLogger(AccountStorageClient.class);
58
59     public AccountStorageClient() {
60     }
61
62     @Override
63     public String create(ServiceContext ctx,
64             DocumentHandler handler) throws BadRequestException,
65             DocumentException {
66
67         if (ctx == null) {
68             throw new IllegalArgumentException(
69                     "AccountStorageClient.create : ctx is missing");
70         }
71         if (handler == null) {
72             throw new IllegalArgumentException(
73                     "AccountStorageClient.create: handler is missing");
74         }
75         EntityManagerFactory emf = null;
76         EntityManager em = null;
77         try {
78             handler.prepare(Action.CREATE);
79             AccountsCommon account = (AccountsCommon) handler.getCommonPart();
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 && account.getPassword() != null) {
88                 User user = createUser(account);
89                 em.persist(user);
90             }
91 //            if (accountReceived.getTenant() != null) {
92 //                UserTenant ut = createTenantAssoc(accountReceived);
93 //                em.persist(ut);
94 //            }
95             account.setCreatedAtItem(new Date());
96             em.persist(account);
97             em.getTransaction().commit();
98             handler.complete(Action.CREATE, wrapDoc);
99             return (String) JaxbUtils.getValue(account, "getCsid");
100         } catch (BadRequestException bre) {
101             if (em != null && em.getTransaction().isActive()) {
102                 em.getTransaction().rollback();
103             }
104             throw bre;
105         } catch (Exception e) {
106             if (em != null && em.getTransaction().isActive()) {
107                 em.getTransaction().rollback();
108             }
109             if (logger.isDebugEnabled()) {
110                 logger.debug("Caught exception ", e);
111             }
112             throw new DocumentException(e);
113         } finally {
114             if (em != null) {
115                 JpaStorageUtils.releaseEntityManagerFactory(emf);
116             }
117         }
118     }
119
120     @Override
121     public void update(ServiceContext ctx, String id, DocumentHandler handler)
122             throws BadRequestException, DocumentNotFoundException,
123             DocumentException {
124         if (ctx == null) {
125             throw new IllegalArgumentException(
126                     "AccountStorageClient.update : ctx is missing");
127         }
128         if (handler == null) {
129             throw new IllegalArgumentException(
130                     "AccountStorageClient.update: handler is missing");
131         }
132         EntityManagerFactory emf = null;
133         EntityManager em = null;
134         try {
135             handler.prepare(Action.UPDATE);
136             AccountsCommon accountReceived = (AccountsCommon) handler.getCommonPart();
137             emf = JpaStorageUtils.getEntityManagerFactory();
138             em = emf.createEntityManager();
139             em.getTransaction().begin();
140             AccountsCommon accountFound = getAccount(em, id);
141             checkAllowedUpdates(accountReceived, accountFound);
142             //if userid and password are given, add to default id provider
143             if (accountReceived.getUserId() != null
144                     && hasPassword(accountReceived.getPassword())) {
145                 updateUser(em, accountReceived);
146             }
147             DocumentWrapper<AccountsCommon> wrapDoc =
148                     new DocumentWrapperImpl<AccountsCommon>(accountFound);
149             handler.handle(Action.UPDATE, wrapDoc);
150             em.getTransaction().commit();
151             handler.complete(Action.UPDATE, wrapDoc);
152         } catch (BadRequestException bre) {
153             if (em != null && em.getTransaction().isActive()) {
154                 em.getTransaction().rollback();
155             }
156             throw bre;
157         } catch (DocumentException de) {
158             if (em != null && em.getTransaction().isActive()) {
159                 em.getTransaction().rollback();
160             }
161             throw de;
162         } catch (Exception e) {
163             if (logger.isDebugEnabled()) {
164                 logger.debug("Caught exception ", e);
165             }
166             throw new DocumentException(e);
167         } finally {
168             if (emf != null) {
169                 JpaStorageUtils.releaseEntityManagerFactory(emf);
170             }
171         }
172     }
173
174     @Override
175     public void delete(ServiceContext ctx, String id)
176             throws DocumentNotFoundException,
177             DocumentException {
178
179         if (logger.isDebugEnabled()) {
180             logger.debug("deleting entity with id=" + id);
181         }
182         if (ctx == null) {
183             throw new IllegalArgumentException(
184                     "AccountStorageClient.delete : ctx is missing");
185         }
186         EntityManagerFactory emf = null;
187         EntityManager em = null;
188         try {
189             emf = JpaStorageUtils.getEntityManagerFactory();
190             em = emf.createEntityManager();
191             //TODO investigate if deep delete is possible
192             //query an delete is inefficient
193             AccountsCommon accountFound = getAccount(em, id);
194
195             //TODO: add tenant id
196
197             //if userid gives any indication about the id provider, it should
198             //be used to avoid the following approach
199             Query usrDel = null;
200             User userLocal = getUser(em, accountFound);
201             if (userLocal != null) {
202                 StringBuilder usrDelStr = new StringBuilder("DELETE FROM ");
203                 usrDelStr.append(User.class.getCanonicalName());
204                 usrDelStr.append(" WHERE username = :username");
205                 //TODO: add tenant id
206                 usrDel = em.createQuery(usrDelStr.toString());
207                 usrDel.setParameter("username", accountFound.getUserId());
208             }
209             em.getTransaction().begin();
210
211             if (userLocal != null) {
212                 int usrDelCount = usrDel.executeUpdate();
213                 if (usrDelCount != 1) {
214                     if (em != null && em.getTransaction().isActive()) {
215                         em.getTransaction().rollback();
216                     }
217                     String msg = "could not find user with username=" + accountFound.getUserId();
218                     logger.error(msg);
219                     throw new DocumentNotFoundException(msg);
220                 }
221             }
222             em.remove(accountFound);
223             em.getTransaction().commit();
224
225         } catch (DocumentException de) {
226             if (em != null && em.getTransaction().isActive()) {
227                 em.getTransaction().rollback();
228             }
229             throw de;
230         } catch (Exception e) {
231             if (logger.isDebugEnabled()) {
232                 logger.debug("Caught exception ", e);
233             }
234             if (em != null && em.getTransaction().isActive()) {
235                 em.getTransaction().rollback();
236             }
237             throw new DocumentException(e);
238         } finally {
239             if (emf != null) {
240                 JpaStorageUtils.releaseEntityManagerFactory(emf);
241             }
242         }
243     }
244
245     private AccountsCommon getAccount(EntityManager em, String id) throws DocumentNotFoundException {
246         AccountsCommon accountFound = em.find(AccountsCommon.class, id);
247         if (accountFound == null) {
248             if (em != null && em.getTransaction().isActive()) {
249                 em.getTransaction().rollback();
250             }
251             String msg = "could not find account with id=" + id;
252             logger.error(msg);
253             throw new DocumentNotFoundException(msg);
254         }
255         return accountFound;
256     }
257
258     private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException {
259         if (!fromAccount.getUserId().equals(toAccount.getUserId())) {
260             String msg = "User id " + toAccount.getUserId() + " does not match "
261                     + "for given account with csid=" + fromAccount.getCsid();
262             logger.error(msg);
263             logger.debug(msg + " found userid=" + fromAccount.getUserId());
264             throw new BadRequestException(msg);
265         }
266         return true;
267     }
268
269     private User createUser(AccountsCommon account) throws Exception {
270         User user = new User();
271         user.setUsername(account.getUserId());
272         if (hasPassword(account.getPassword())) {
273             user.setPasswd(getEncPassword(account));
274         }
275         user.setCreatedAtItem(new Date());
276         return user;
277     }
278
279     private User getUser(EntityManager em, AccountsCommon account) throws DocumentNotFoundException {
280         User userFound = em.find(User.class, account.getUserId());
281         if (userFound == null) {
282             if (em != null && em.getTransaction().isActive()) {
283                 em.getTransaction().rollback();
284             }
285             String msg = "could not find user with id=" + account.getUserId();
286             logger.error(msg);
287             throw new DocumentNotFoundException(msg);
288         }
289         return userFound;
290     }
291
292     private void updateUser(EntityManager em, AccountsCommon account) throws Exception {
293         User userFound = getUser(em, account);
294         if (userFound != null) {
295             userFound.setPasswd(getEncPassword(account));
296             userFound.setUpdatedAtItem(new Date());
297             if (logger.isDebugEnabled()) {
298                 logger.debug("updated user=" + JaxbUtils.toString(userFound, User.class));
299             }
300             em.persist(userFound);
301         }
302     }
303
304     private String getEncPassword(AccountsCommon account) throws BadRequestException {
305         //jaxb unmarshaller already unmarshal xs:base64Binary, no need to b64 decode
306         //byte[] bpass = Base64.decodeBase64(accountReceived.getPassword());
307         try {
308             SecurityUtils.validatePassword(new String(account.getPassword()));
309         } catch (Exception e) {
310             throw new BadRequestException(e.getMessage());
311         }
312         String secEncPasswd = SecurityUtils.createPasswordHash(
313                 account.getUserId(), new String(account.getPassword()));
314         return secEncPasswd;
315     }
316
317     private boolean hasPassword(byte[] bpass) {
318         return bpass != null && bpass.length > 0;
319     }
320 //    private UserTenant createTenantAssoc(AccountsCommon accountReceived) {
321 //        UserTenant userTenant = new UserTenant();
322 //        userTenant.setUserId(accountReceived.getUserId());
323 //        List<AccountsCommon.Tenant> atl = accountReceived.getTenant();
324 //        List<UserTenant.Tenant> utl =
325 //                new ArrayList<UserTenant.Tenant>();
326 //        for (AccountsCommon.Tenant at : atl) {
327 //            UserTenant.Tenant ut = new UserTenant.Tenant();
328 //            ut.setId(at.getId());
329 //            ut.setName(at.getName());
330 //            utl.add(ut);
331 //        }
332 //        userTenant.setTenant(utl);
333 //        return userTenant;
334 //    }
335 }