]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
1a0df03bf5a838bc96ed32a647b2160509327691
[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
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.DocumentFilter;
36 import org.collectionspace.services.common.document.DocumentHandler;
37 import org.collectionspace.services.common.document.DocumentHandler.Action;
38 import org.collectionspace.services.common.document.DocumentNotFoundException;
39 import org.collectionspace.services.common.document.DocumentWrapper;
40 import org.collectionspace.services.common.document.DocumentWrapperImpl;
41 import org.collectionspace.services.common.document.JaxbUtils;
42 import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
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 @SuppressWarnings({ "rawtypes", "unchecked" })
57 public class AccountStorageClient extends JpaStorageClientImpl {
58
59     private final Logger logger = LoggerFactory.getLogger(AccountStorageClient.class);
60     private UserStorageClient userStorageClient = new UserStorageClient();
61
62     public AccountStorageClient() {
63     }
64
65         @Override
66     public String create(ServiceContext ctx,
67             DocumentHandler handler) throws BadRequestException,
68             DocumentException {
69         String result = null;
70         
71         AccountsCommon account = null;
72         JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();       
73         try {
74             account = (AccountsCommon) handler.getCommonPart();
75             handler.prepare(Action.CREATE);
76             DocumentWrapper<AccountsCommon> wrapDoc = new DocumentWrapperImpl<AccountsCommon>(account);
77             handler.handle(Action.CREATE, wrapDoc);
78             jpaConnectionContext.beginTransaction();
79             //
80             // If userid and password are given, add to default ID provider -i.e., add it to the Spring Security account list
81             //
82             if (account.getUserId() != null && isForCSpaceIdentityProvider(account.getPassword())) {
83                 User user = userStorageClient.create(account.getUserId(), account.getPassword());
84                     jpaConnectionContext.persist(user);
85             }
86             //
87             // Now add the account to the CSpace list of accounts
88             //
89             account.setCreatedAtItem(new Date());
90             jpaConnectionContext.persist(account);              
91             //
92             // Finish creating related resources -e.g., account-role relationships
93             //
94             handler.complete(Action.CREATE, wrapDoc);
95             jpaConnectionContext.commitTransaction();
96
97             result = (String)JaxbUtils.getValue(account, "getCsid");
98         } catch (BadRequestException bre) {
99                 jpaConnectionContext.markForRollback();
100             throw bre;
101         } catch (Exception e) {
102             if (logger.isDebugEnabled()) {
103                 logger.debug("Caught exception ", e);
104             }
105             boolean uniqueConstraint = false;
106             if (userStorageClient.get(ctx, account.getUserId()) != null) {
107                 //might be unique constraint violation
108                 uniqueConstraint = true;
109             }
110             
111                 jpaConnectionContext.markForRollback();
112
113             if (uniqueConstraint) {
114                 String msg = "UserId exists. Non unique userId=" + account.getUserId();
115                 logger.error(msg);
116                 throw new BadRequestException(msg);
117             }
118             throw new DocumentException(e);
119         } finally {
120             ctx.closeConnection();
121         }
122         
123         return result;
124     }
125
126     @Override
127     public void get(ServiceContext ctx, String id, DocumentHandler handler)
128             throws DocumentNotFoundException, DocumentException {
129         DocumentFilter docFilter = handler.getDocumentFilter();
130         if (docFilter == null) {
131             docFilter = handler.createDocumentFilter();
132         }
133
134         JPATransactionContext jpaTransactionContext = (JPATransactionContext)ctx.openConnection();
135         try {
136             handler.prepare(Action.GET);
137             Object o = null;
138             String whereClause = " JOIN a.tenants as at where csid = :csid and at.tenantId = :tenantId";
139             HashMap<String, Object> params = new HashMap<String, Object>();
140             params.put("csid", id);
141             params.put("tenantId", ctx.getTenantId());
142
143             o = JpaStorageUtils.getEntity(jpaTransactionContext, 
144                     "org.collectionspace.services.account.AccountsCommon", whereClause, params);
145             if (null == o) {
146                 String msg = "could not find entity with id=" + id;
147                 throw new DocumentNotFoundException(msg);
148             }
149             DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(o);
150             handler.handle(Action.GET, wrapDoc);
151             handler.complete(Action.GET, wrapDoc);
152         } catch (DocumentException de) {
153             throw de;
154         } catch (Exception e) {
155             if (logger.isDebugEnabled()) {
156                 logger.debug("Caught exception ", e);
157             }
158             throw new DocumentException(e);
159         } finally {
160                 ctx.closeConnection();
161         }
162         
163     }
164
165     @Override
166     public void update(ServiceContext ctx, String id, DocumentHandler handler)
167             throws BadRequestException, DocumentNotFoundException,
168             DocumentException {
169
170         JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();        
171         try {
172             jpaConnectionContext.beginTransaction();
173
174             handler.prepare(Action.UPDATE);
175             AccountsCommon accountReceived = (AccountsCommon) handler.getCommonPart();
176             AccountsCommon accountFound = getAccount(jpaConnectionContext, id);
177             checkAllowedUpdates(accountReceived, accountFound);
178             //if userid and password are given, add to default id provider
179             // Note that this ignores the immutable flag, as we allow
180             // password changes.
181             if (accountReceived.getUserId() != null && isForCSpaceIdentityProvider(accountReceived.getPassword())) {
182                 userStorageClient.update(jpaConnectionContext,
183                         accountReceived.getUserId(),
184                         accountReceived.getPassword());
185             }
186             DocumentWrapper<AccountsCommon> wrapDoc =
187                     new DocumentWrapperImpl<AccountsCommon>(accountFound);
188             handler.handle(Action.UPDATE, wrapDoc);
189             handler.complete(Action.UPDATE, wrapDoc); 
190             jpaConnectionContext.commitTransaction();
191             //
192             // Don't sanitize until we've committed changes to the DB
193             //
194             handler.sanitize(wrapDoc);
195         } catch (BadRequestException bre) {
196                 jpaConnectionContext.markForRollback();
197             throw bre;
198         } catch (DocumentException de) {
199                 jpaConnectionContext.markForRollback();
200             throw de;
201         } catch (Exception e) {
202                 jpaConnectionContext.markForRollback();
203             throw new DocumentException(e);
204         } finally {
205             ctx.closeConnection();
206         }
207     }
208
209     @Override
210     public void delete(ServiceContext ctx, String id)
211             throws DocumentNotFoundException,
212             DocumentException {
213
214         if (logger.isDebugEnabled()) {
215             logger.debug("deleting entity with id=" + id);
216         }
217         
218         JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();        
219         try {
220             AccountsCommon accountFound = getAccount(jpaConnectionContext, id);
221             jpaConnectionContext.beginTransaction();
222             //if userid gives any indication about the id provider, it should
223             //be used to avoid  delete
224             userStorageClient.delete(jpaConnectionContext, accountFound.getUserId());
225             jpaConnectionContext.remove(accountFound);
226             jpaConnectionContext.commitTransaction();
227         } catch (DocumentException de) {
228                 jpaConnectionContext.markForRollback();
229             throw de;
230         } catch (Exception e) {
231             if (logger.isDebugEnabled()) {
232                 logger.debug("Caught exception ", e);
233             }
234             jpaConnectionContext.markForRollback();
235             throw new DocumentException(e);
236         } finally {
237             ctx.closeConnection();
238         }
239     }
240
241     private AccountsCommon getAccount(JPATransactionContext jpaConnectionContext, String id) throws DocumentNotFoundException {
242         AccountsCommon accountFound = (AccountsCommon) jpaConnectionContext.find(AccountsCommon.class, id);
243         if (accountFound == null) {
244             String msg = "could not find account with id=" + id;
245             logger.error(msg);
246             throw new DocumentNotFoundException(msg);
247         }
248         
249         return accountFound;
250     }
251
252     private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException {
253         if (!fromAccount.getUserId().equals(toAccount.getUserId())) {
254             String msg = "userId=" + toAccount.getUserId() + " of existing account does not match "
255                     + "the userId=" + fromAccount.getUserId()
256                     + " with csid=" + fromAccount.getCsid();
257             logger.error(msg);
258             if (logger.isDebugEnabled()) {
259                 logger.debug(msg + " found userid=" + fromAccount.getUserId());
260             }
261             throw new BadRequestException(msg);
262         }
263         return true;
264     }
265
266     /**
267      * isForCSIdP deteremines if the create/update is also needed for CS IdP
268      * @param bpass
269      * @return
270      */
271     private boolean isForCSpaceIdentityProvider(byte[] bpass) {
272         return bpass != null && bpass.length > 0;
273     }
274 //    private UserTenant createTenantAssoc(AccountsCommon accountReceived) {
275 //        UserTenant userTenant = new UserTenant();
276 //        userTenant.setUserId(accountReceived.getUserId());
277 //        List<AccountsCommon.Tenant> atl = accountReceived.getTenant();
278 //        List<UserTenant.Tenant> utl =
279 //                new ArrayList<UserTenant.Tenant>();
280 //        for (AccountsCommon.Tenant at : atl) {
281 //            UserTenant.Tenant ut = new UserTenant.Tenant();
282 //            ut.setId(at.getId());
283 //            ut.setName(at.getName());
284 //            utl.add(ut);
285 //        }
286 //        userTenant.setTenant(utl);
287 //        return userTenant;
288 //    }
289 }