View Javadoc
1   /*
2    * Copyright 2001-2008 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  package org.apache.juddi.validation;
18  
19  import java.io.UnsupportedEncodingException;
20  import java.util.ArrayList;
21  import java.util.Collections;
22  import java.util.Date;
23  import java.util.List;
24  import java.util.Vector;
25  
26  import javax.persistence.EntityManager;
27  import javax.persistence.Query;
28  import static org.apache.juddi.api.impl.AuthenticatedService.UTF8;
29  
30  import org.apache.juddi.model.TransferTokenKey;
31  import org.apache.juddi.model.UddiEntity;
32  import org.apache.juddi.model.UddiEntityPublisher;
33  import org.apache.juddi.query.util.DynamicQuery;
34  import org.apache.juddi.v3.error.ErrorMessage;
35  import org.apache.juddi.v3.error.FatalErrorException;
36  import org.apache.juddi.v3.error.InvalidKeyPassedException;
37  import org.apache.juddi.v3.error.InvalidValueException;
38  import org.apache.juddi.v3.error.TokenAlreadyExistsException;
39  import org.apache.juddi.v3.error.TransferNotAllowedException;
40  import org.apache.juddi.v3.error.UserMismatchException;
41  import org.apache.juddi.v3.error.ValueNotAllowedException;
42  import org.uddi.custody_v3.DiscardTransferToken;
43  import org.uddi.custody_v3.KeyBag;
44  import org.uddi.custody_v3.TransferEntities;
45  import org.uddi.v3_service.DispositionReportFaultMessage;
46  
47  /**
48   * @author <a href="mailto:jfaath@apache.org">Jeff Faath</a>
49   */
50  public class ValidateCustodyTransfer extends ValidateUDDIApi {
51  
52          public ValidateCustodyTransfer(UddiEntityPublisher publisher) {
53                  super(publisher);
54          }
55  
56          public void validateDiscardTransferToken(EntityManager em, DiscardTransferToken body) throws DispositionReportFaultMessage {
57                  // No null input
58                  if (body == null) {
59                          throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
60                  }
61  
62                  KeyBag keyBag = body.getKeyBag();
63  
64                  // The call must contain at least a transfer token or keyBag
65                  if (body.getTransferToken() == null && keyBag == null) {
66                          throw new FatalErrorException(new ErrorMessage("errors.discardtransfertoken.NoInput"));
67                  }
68  
69                  if (keyBag != null) {
70                          List<String> keyList = keyBag.getKey();
71                          if (keyList == null || keyList.size() == 0) {
72                                  throw new ValueNotAllowedException(new ErrorMessage("errors.keybag.NoInput"));
73                          }
74  
75                          // Test that publisher owns keys using operational info.
76                          int i = 0;
77                          for (String key : keyList) {
78                                  // Per section 4.4: keys must be case-folded
79                                  key = key.toLowerCase();
80                                  keyList.set(i, key);
81  
82                                  UddiEntity uddiEntity = em.find(UddiEntity.class, key);
83  
84  				// According to spec, it's ok if a key doesn't match any known entities, it will just be ignored.  However, the publisher must own
85                                  // the entity in order to discard the associated token.
86                                  if (uddiEntity != null) {
87                                          if (!publisher.isOwner(uddiEntity)) {
88                                                  throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidOwner", key));
89                                          }
90  
91                                  }
92  
93                                  i++;
94                          }
95  
96                  }
97  
98          }
99  
100         public void validateGetTransferToken(EntityManager em, KeyBag keyBag) throws DispositionReportFaultMessage {
101 
102                 // No null input
103                 if (keyBag == null) {
104                         throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
105                 }
106 
107                 List<String> keyList = keyBag.getKey();
108                 if (keyList == null || keyList.size() == 0) {
109                         throw new ValueNotAllowedException(new ErrorMessage("errors.keybag.NoInput"));
110                 }
111 
112                 // Test that publisher owns keys using operational info.
113                 Vector<DynamicQuery.Parameter> params = new Vector<DynamicQuery.Parameter>(0);
114                 int i = 0;
115                 for (String key : keyList) {
116                         // Per section 4.4: keys must be case-folded
117                         key = key.toLowerCase();
118                         keyList.set(i, key);
119 
120                         UddiEntity uddiEntity = em.find(UddiEntity.class, key);
121 
122                         if (uddiEntity == null) {
123                                 throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.EntityNotFound", key));
124                         }
125 
126                         // Only BusinessEntities or TModels are allowed to be transferred
127                         if (!(uddiEntity instanceof org.apache.juddi.model.BusinessEntity)
128                                 && !(uddiEntity instanceof org.apache.juddi.model.Tmodel)) {
129                                 throw new InvalidKeyPassedException(new ErrorMessage("errors.gettransfertoken.InvalidEntity", key));
130                         }
131 
132                         if (!publisher.isOwner(uddiEntity)) {
133                                 throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidOwner", key));
134                         }
135 
136                         // Creating parameters for key-checking query
137                         DynamicQuery.Parameter param = new DynamicQuery.Parameter("UPPER(ttk.entityKey)",
138                                 key.toUpperCase(),
139                                 DynamicQuery.PREDICATE_EQUALS);
140                         params.add(param);
141 
142                 }
143 
144                 // Make sure keys aren't implicated in another transfer request
145                 DynamicQuery checkKeysQry = new DynamicQuery();
146                 checkKeysQry.append("select ttk.entityKey from TransferTokenKey ttk ");
147                 checkKeysQry.WHERE().pad().appendGroupedOr(params.toArray(new DynamicQuery.Parameter[0]));
148 
149                 Query qry = checkKeysQry.buildJPAQuery(em);
150                 List<?> obj = qry.getResultList();
151                 if (obj != null && obj.size() > 0) {
152                         throw new TokenAlreadyExistsException(new ErrorMessage("errors.gettransfertoken.KeyExists", (String) obj.get(0)));
153                 }
154 
155         }
156         
157         public void validateTransferLocalEntities(EntityManager em, String transferTokenId, List<String> apiKeyList) throws DispositionReportFaultMessage {
158                 org.apache.juddi.model.TransferToken modelTransferToken = em.find(org.apache.juddi.model.TransferToken.class, transferTokenId);
159                         //JUDDI-272 only block transfer if the destination is not the originator of the token
160                         if (modelTransferToken == null) {
161                                 throw new TransferNotAllowedException(new ErrorMessage("errors.transferentities.TokenNotFound", transferTokenId));
162                         }
163 
164                         Date now = new Date();
165                         if (now.after(modelTransferToken.getExpirationDate())) {
166                                 throw new TransferNotAllowedException(new ErrorMessage("errors.transferentities.TokenExpired", transferTokenId));
167                         }
168 
169                         List<TransferTokenKey> transferKeyList = modelTransferToken.getTransferKeys();
170                         List<String> modelKeyList = new ArrayList<String>(0);
171                         if (transferKeyList != null && transferKeyList.size() > 0) {
172                                 for (TransferTokenKey ttk : transferKeyList) {
173                                         modelKeyList.add(ttk.getEntityKey());
174                                 }
175                         }
176 
177                         // The keys in the supplied key bag must match exactly the keys in the stored transfer and the entities must exist
178                         Collections.sort(apiKeyList);
179                         Collections.sort(modelKeyList);
180                         int count = 0;
181                         if (modelKeyList.size() != apiKeyList.size()) {
182                                 throw new TransferNotAllowedException(new ErrorMessage("errors.transferentities.KeySizeMismatch"));
183                         }
184                         for (String key : apiKeyList) {
185                                 // Per section 4.4: keys must be case-folded
186                                 key = key.toLowerCase();
187                                 apiKeyList.set(count, key);
188 
189                                 if (!key.equalsIgnoreCase(modelKeyList.get(count))) {
190                                         throw new TransferNotAllowedException(new ErrorMessage("errors.transferentities.KeyMismatch", key + " & " + modelKeyList.get(count)));
191                                 }
192 
193                                 UddiEntity uddiEntity = em.find(UddiEntity.class, key);
194                                 if (uddiEntity == null) {
195                                         throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.EntityNotFound", key));
196                                 }
197                                 count++;
198                         }
199 
200         }
201 
202         /**
203          * returns true if all items to be transfered are within this node (no
204          * node to node transfers) false for transfer between nodes
205          *
206          * @param em
207          * @param body
208          * @return
209          * @throws DispositionReportFaultMessage
210          */
211         public boolean validateTransferEntities(EntityManager em, TransferEntities body) throws DispositionReportFaultMessage {
212 
213                 boolean ret = true;
214                 // No null input
215                 if (body == null) {
216                         throw new FatalErrorException(new ErrorMessage("errors.NullInput"));
217                 }
218 
219                 org.uddi.custody_v3.TransferToken apiTransferToken = body.getTransferToken();
220                 if (apiTransferToken == null) {
221                         throw new FatalErrorException(new ErrorMessage("errors.transfertoken.NullInput"));
222                 }
223 
224                 KeyBag keyBag = body.getKeyBag();
225                 if (keyBag == null) {
226                         throw new FatalErrorException(new ErrorMessage("errors.keybag.NullInput"));
227                 }
228 
229                 List<String> apiKeyList = keyBag.getKey();
230                 if (apiKeyList == null || apiKeyList.size() == 0) {
231                         throw new ValueNotAllowedException(new ErrorMessage("errors.keybag.NoInput"));
232                 }
233 
234                 String transferTokenId = null;
235                 try{
236                     transferTokenId = new String(apiTransferToken.getOpaqueToken(), UTF8);
237                 } catch (UnsupportedEncodingException ex) {
238                     throw new InvalidValueException(new ErrorMessage("errors.stringEncoding"));
239                 }
240                 if (nodeID.equals(apiTransferToken.getNodeID())) {
241                         validateTransferLocalEntities(em, transferTokenId, apiKeyList);
242                 } else {
243                         return false;
244                 }
245                 return ret;
246         }
247 }