This project has retired. For details please refer to its Attic page.
JUDDIApiImpl xref
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.api.impl;
18  
19  import java.io.StringWriter;
20  import java.math.BigInteger;
21  import java.rmi.RemoteException;
22  import java.text.SimpleDateFormat;
23  import java.util.ArrayList;
24  import java.util.Date;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  
30  import javax.jws.WebService;
31  import javax.persistence.EntityManager;
32  import javax.persistence.EntityTransaction;
33  import javax.persistence.Query;
34  import javax.xml.bind.JAXBContext;
35  import javax.xml.bind.Marshaller;
36  import javax.xml.ws.Holder;
37  
38  import org.apache.commons.logging.Log;
39  import org.apache.commons.logging.LogFactory;
40  import org.apache.juddi.ClassUtil;
41  import static org.apache.juddi.api.impl.JUDDIApiImpl.sub;
42  import org.apache.juddi.api.util.JUDDIQuery;
43  import org.apache.juddi.api.util.QueryStatus;
44  import org.apache.juddi.api_v3.AdminSaveBusinessWrapper;
45  import org.apache.juddi.api_v3.AdminSaveTModelWrapper;
46  import org.apache.juddi.api_v3.Clerk;
47  import org.apache.juddi.api_v3.ClerkDetail;
48  import org.apache.juddi.api_v3.ClerkList;
49  import org.apache.juddi.api_v3.ClientSubscriptionInfoDetail;
50  import org.apache.juddi.api_v3.DeleteClerk;
51  import org.apache.juddi.api_v3.DeleteClientSubscriptionInfo;
52  import org.apache.juddi.api_v3.DeleteNode;
53  import org.apache.juddi.api_v3.DeletePublisher;
54  import org.apache.juddi.api_v3.GetAllClientSubscriptionInfoDetail;
55  import org.apache.juddi.api_v3.GetAllPublisherDetail;
56  import org.apache.juddi.api_v3.GetClientSubscriptionInfoDetail;
57  import org.apache.juddi.api_v3.GetEntityHistoryMessageRequest;
58  import org.apache.juddi.api_v3.GetEntityHistoryMessageResponse;
59  import org.apache.juddi.api_v3.GetFailedReplicationChangeRecordsMessageRequest;
60  import org.apache.juddi.api_v3.GetFailedReplicationChangeRecordsMessageResponse;
61  import org.apache.juddi.api_v3.GetPublisherDetail;
62  import org.apache.juddi.api_v3.NodeDetail;
63  import org.apache.juddi.api_v3.NodeList;
64  import org.apache.juddi.api_v3.PublisherDetail;
65  import org.apache.juddi.api_v3.SaveClerk;
66  import org.apache.juddi.api_v3.SaveClientSubscriptionInfo;
67  import org.apache.juddi.api_v3.SaveNode;
68  import org.apache.juddi.api_v3.SavePublisher;
69  import org.apache.juddi.api_v3.SubscriptionWrapper;
70  import org.apache.juddi.api_v3.SyncSubscription;
71  import org.apache.juddi.api_v3.SyncSubscriptionDetail;
72  import org.apache.juddi.config.AppConfig;
73  import org.apache.juddi.config.PersistenceManager;
74  import org.apache.juddi.config.Property;
75  import org.apache.juddi.mapping.MappingApiToModel;
76  import org.apache.juddi.mapping.MappingModelToApi;
77  import org.apache.juddi.model.BusinessEntity;
78  import org.apache.juddi.model.ChangeRecord;
79  import org.apache.juddi.model.ClientSubscriptionInfo;
80  import org.apache.juddi.model.Node;
81  import org.apache.juddi.model.Publisher;
82  import org.apache.juddi.model.ReplicationConfiguration;
83  import org.apache.juddi.model.Tmodel;
84  import org.apache.juddi.model.UddiEntityPublisher;
85  import org.apache.juddi.replication.ReplicationNotifier;
86  import org.apache.juddi.subscription.NotificationList;
87  import org.apache.juddi.subscription.notify.TemporaryMailContainer;
88  import org.apache.juddi.subscription.notify.USERFRIENDLYSMTPNotifier;
89  import org.apache.juddi.v3.client.transport.Transport;
90  import org.apache.juddi.v3.error.ErrorMessage;
91  import org.apache.juddi.v3.error.FatalErrorException;
92  import org.apache.juddi.v3.error.InvalidKeyPassedException;
93  import org.apache.juddi.v3.error.InvalidValueException;
94  import org.apache.juddi.v3.error.UserMismatchException;
95  import org.apache.juddi.v3_service.JUDDIApiPortType;
96  import org.apache.juddi.validation.ValidateClerk;
97  import org.apache.juddi.validation.ValidateClientSubscriptionInfo;
98  import org.apache.juddi.validation.ValidateNode;
99  import org.apache.juddi.validation.ValidatePublish;
100 import org.apache.juddi.validation.ValidatePublisher;
101 import org.apache.juddi.validation.ValidateReplication;
102 import org.uddi.api_v3.AuthToken;
103 import org.uddi.api_v3.BusinessInfo;
104 import org.uddi.api_v3.BusinessInfos;
105 import org.uddi.api_v3.Contact;
106 import org.uddi.api_v3.DeleteTModel;
107 import org.uddi.api_v3.DispositionReport;
108 import org.uddi.api_v3.GetRegisteredInfo;
109 import org.uddi.api_v3.InfoSelection;
110 import org.uddi.api_v3.PersonName;
111 import org.uddi.api_v3.RegisteredInfo;
112 import org.uddi.api_v3.Result;
113 import org.uddi.api_v3.SaveBusiness;
114 import org.uddi.api_v3.SaveTModel;
115 import org.uddi.api_v3.TModelInfo;
116 import org.uddi.api_v3.TModelInfos;
117 import org.uddi.repl_v3.ChangeRecords;
118 import org.uddi.repl_v3.CommunicationGraph;
119 import org.uddi.repl_v3.Operator;
120 import org.uddi.repl_v3.OperatorStatusType;
121 import org.uddi.sub_v3.GetSubscriptionResults;
122 import org.uddi.sub_v3.Subscription;
123 import org.uddi.sub_v3.SubscriptionResultsList;
124 import org.uddi.v3_service.DispositionReportFaultMessage;
125 import org.uddi.v3_service.UDDISubscriptionPortType;
126 
127 /**
128  * Implements the jUDDI API service. These methods are outside of the UDDI spec
129  * and are specific to jUDDI. They are primarily used for administrative
130  * functions.
131  *
132  * @author <a href="mailto:jfaath@apache.org">Jeff Faath</a>
133  * @author <a href="mailto:kstam@apache.org">Kurt T Stam</a>
134  * @author <a href="mailto:alexoree@apache.org">Alex O'Ree</a>
135  */
136 @WebService(serviceName = "JUDDIApiService",
137         endpointInterface = "org.apache.juddi.v3_service.JUDDIApiPortType",
138         targetNamespace = "urn:juddi-apache-org:v3_service"
139         //, wsdlLocation = "classpath:/juddi_api_v1.wsdl"
140 )
141 public class JUDDIApiImpl extends AuthenticatedService implements JUDDIApiPortType {
142 
143         private Log log = LogFactory.getLog(this.getClass());
144         private UDDIServiceCounter serviceCounter = ServiceCounterLifecycleResource.getServiceCounter(this.getClass());
145 
146         /**
147          * Saves publisher(s) to the persistence layer. This method is specific
148          * to jUDDI. Administrative privilege required.
149          *
150          * @param body
151          * @return PublisherDetail
152          * @throws DispositionReportFaultMessage
153          */
154         public PublisherDetail savePublisher(SavePublisher body)
155                 throws DispositionReportFaultMessage {
156                 long startTime = System.currentTimeMillis();
157                 EntityManager em = PersistenceManager.getEntityManager();
158                 EntityTransaction tx = em.getTransaction();
159                 try {
160                         tx.begin();
161 
162                         UddiEntityPublisher publisher = this.getEntityPublisher(em, body.getAuthInfo());
163 
164                         new ValidatePublish(publisher).validateSavePublisher(em, body);
165 
166                         PublisherDetail result = new PublisherDetail();
167 
168                         List<org.apache.juddi.api_v3.Publisher> apiPublisherList = body.getPublisher();
169                         for (org.apache.juddi.api_v3.Publisher apiPublisher : apiPublisherList) {
170 
171                                 org.apache.juddi.model.Publisher modelPublisher = new org.apache.juddi.model.Publisher();
172 
173                                 MappingApiToModel.mapPublisher(apiPublisher, modelPublisher);
174 
175                                 Object existingUddiEntity = em.find(modelPublisher.getClass(), modelPublisher.getAuthorizedName());
176                                 if (existingUddiEntity != null) {
177                                         em.remove(existingUddiEntity);
178                                 }
179 
180                                 em.persist(modelPublisher);
181 
182                                 result.getPublisher().add(apiPublisher);
183                         }
184 
185                         tx.commit();
186                         long procTime = System.currentTimeMillis() - startTime;
187                         serviceCounter.update(JUDDIQuery.SAVE_PUBLISHER,
188                                 QueryStatus.SUCCESS, procTime);
189                         return result;
190                 } catch (DispositionReportFaultMessage drfm) {
191                         long procTime = System.currentTimeMillis() - startTime;
192                         serviceCounter.update(JUDDIQuery.SAVE_PUBLISHER,
193                                 QueryStatus.FAILED, procTime);
194                         throw drfm;
195                 } finally {
196                         if (tx.isActive()) {
197                                 tx.rollback();
198                         }
199                         em.close();
200                 }
201         }
202 
203         /**
204          * Deletes publisher(s) from the persistence layer. This method is
205          * specific to jUDDI. Administrative privilege required. Also removes
206          * all registered business entities of the user and marks all created
207          * tModels as "deleted" but not does not remove the tModel from
208          * persistence. All subscriptions are also destroyed
209          *
210          * @param body
211          * @throws DispositionReportFaultMessage
212          */
213         @Override
214         public void deletePublisher(DeletePublisher body)
215                 throws DispositionReportFaultMessage {
216                 long startTime = System.currentTimeMillis();
217                 EntityManager em = PersistenceManager.getEntityManager();
218                 EntityTransaction tx = em.getTransaction();
219                 try {
220                         tx.begin();
221 
222                         UddiEntityPublisher publisher = this.getEntityPublisher(em, body.getAuthInfo());
223 
224                         new ValidatePublish(publisher).validateDeletePublisher(em, body);
225 
226                         List<String> entityKeyList = body.getPublisherId();
227                         List<Publisher> deletedPubs = new ArrayList<Publisher>();
228                         for (String entityKey : entityKeyList) {
229                                 Publisher obj = em.find(org.apache.juddi.model.Publisher.class, entityKey);
230                                 deletedPubs.add(obj);
231                                 //get an authtoken for this publisher so that we can get its registeredInfo
232                                 UDDISecurityImpl security = new UDDISecurityImpl();
233                                 AuthToken authToken = security.getAuthToken(entityKey);
234 
235                                 GetRegisteredInfo r = new GetRegisteredInfo();
236                                 r.setAuthInfo(authToken.getAuthInfo());
237                                 r.setInfoSelection(InfoSelection.ALL);
238 
239                                 log.info("removing all businesses owned by publisher " + entityKey + ".");
240                                 UDDIPublicationImpl publish = new UDDIPublicationImpl();
241                                 RegisteredInfo registeredInfo = publish.getRegisteredInfo(r);
242                                 BusinessInfos businessInfos = registeredInfo.getBusinessInfos();
243                                 if (businessInfos != null && businessInfos.getBusinessInfo() != null) {
244                                         Iterator<BusinessInfo> iter = businessInfos.getBusinessInfo().iterator();
245                                         while (iter.hasNext()) {
246                                                 BusinessInfo businessInfo = iter.next();
247                                                 Object business = em.find(org.apache.juddi.model.BusinessEntity.class, businessInfo.getBusinessKey());
248                                                 em.remove(business);
249                                         }
250                                 }
251 
252                                 log.info("mark all tmodels for publisher " + entityKey + " as deleted.");
253                                 TModelInfos tmodelInfos = registeredInfo.getTModelInfos();
254                                 if (tmodelInfos != null && tmodelInfos.getTModelInfo() != null) {
255                                         Iterator<TModelInfo> iter = tmodelInfos.getTModelInfo().iterator();
256                                         while (iter.hasNext()) {
257                                                 TModelInfo tModelInfo = iter.next();
258                                                 Tmodel tmodel = (Tmodel) em.find(org.apache.juddi.model.Tmodel.class, tModelInfo.getTModelKey());
259                                                 tmodel.setDeleted(true);
260                                                 em.persist(tmodel);
261                                         }
262                                 }
263                                 log.info("remove all persisted AuthTokens for publisher " + entityKey + ".");
264                                 Query q1 = em.createQuery("DELETE FROM AuthToken auth WHERE auth.authorizedName = ?1");
265                                 q1.setParameter(1, entityKey);
266                                 q1.executeUpdate();
267                                 log.info("remove all subscriptions for publisher " + entityKey + ".");
268                                 q1 = em.createQuery("DELETE FROM Subscription s WHERE s.authorizedName = ?1");
269                                 q1.setParameter(1, entityKey);
270                                 q1.executeUpdate();
271 
272                                 log.info("removing publisher " + entityKey + ".");
273                                 //delete the publisher
274                                 em.remove(obj);
275                         }
276 
277                         tx.commit();
278                         for (Publisher p: deletedPubs){
279                                 USERFRIENDLYSMTPNotifier.notifyAccountDeleted(new TemporaryMailContainer(null, p, (Publisher) publisher));
280                         }
281                         long procTime = System.currentTimeMillis() - startTime;
282                         serviceCounter.update(JUDDIQuery.DELETE_PUBLISHER,
283                                 QueryStatus.SUCCESS, procTime);
284                 } catch (DispositionReportFaultMessage drfm) {
285                         long procTime = System.currentTimeMillis() - startTime;
286                         serviceCounter.update(JUDDIQuery.DELETE_PUBLISHER,
287                                 QueryStatus.FAILED, procTime);
288                         throw drfm;
289                 } finally {
290                         if (tx.isActive()) {
291                                 tx.rollback();
292                         }
293                         em.close();
294                 }
295         }
296 
297         /**
298          * Retrieves publisher(s) from the persistence layer. This method is
299          * specific to jUDDI. Administrative privilege required.
300          *
301          * @param body
302          * @return PublisherDetail
303          * @throws DispositionReportFaultMessage
304          */
305         public PublisherDetail getPublisherDetail(GetPublisherDetail body)
306                 throws DispositionReportFaultMessage {
307                 long startTime = System.currentTimeMillis();
308                 new ValidatePublisher(null).validateGetPublisherDetail(body);
309 
310                 EntityManager em = PersistenceManager.getEntityManager();
311                 EntityTransaction tx = em.getTransaction();
312                 try {
313                         tx.begin();
314 
315                         this.getEntityPublisher(em, body.getAuthInfo());
316 
317                         PublisherDetail result = new PublisherDetail();
318 
319                         List<String> publisherIdList = body.getPublisherId();
320                         for (String publisherId : publisherIdList) {
321                                 org.apache.juddi.model.Publisher modelPublisher = null;
322                                 try {
323                                         modelPublisher = em.find(org.apache.juddi.model.Publisher.class, publisherId);
324                                 } catch (ClassCastException e) {
325                                 }
326                                 if (modelPublisher == null) {
327                                         throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.PublisherNotFound", publisherId));
328                                 }
329 
330                                 org.apache.juddi.api_v3.Publisher apiPublisher = new org.apache.juddi.api_v3.Publisher();
331 
332                                 MappingModelToApi.mapPublisher(modelPublisher, apiPublisher);
333 
334                                 result.getPublisher().add(apiPublisher);
335                         }
336 
337                         tx.commit();
338                         long procTime = System.currentTimeMillis() - startTime;
339                         serviceCounter.update(JUDDIQuery.GET_PUBLISHER_DETAIL,
340                                 QueryStatus.SUCCESS, procTime);
341                         return result;
342                 } catch (DispositionReportFaultMessage drfm) {
343                         long procTime = System.currentTimeMillis() - startTime;
344                         serviceCounter.update(JUDDIQuery.GET_PUBLISHER_DETAIL,
345                                 QueryStatus.FAILED, procTime);
346                         throw drfm;
347                 } finally {
348                         if (tx.isActive()) {
349                                 tx.rollback();
350                         }
351                         em.close();
352                 }
353 
354         }
355 
356         /**
357          * Retrieves all publisher from the persistence layer. This method is
358          * specific to jUDDI. Administrative privilege required. Use caution
359          * when calling, result set is not bound. If there are many publishers,
360          * it is possible to have a result set that is too large
361          *
362          * @param body
363          * @return PublisherDetail
364          * @throws DispositionReportFaultMessage
365          * @throws RemoteException
366          */
367         @SuppressWarnings("unchecked")
368         public PublisherDetail getAllPublisherDetail(GetAllPublisherDetail body)
369                 throws DispositionReportFaultMessage, RemoteException {
370                 long startTime = System.currentTimeMillis();
371                 new ValidatePublisher(null).validateGetAllPublisherDetail(body);
372 
373                 EntityManager em = PersistenceManager.getEntityManager();
374                 EntityTransaction tx = em.getTransaction();
375                 try {
376                         tx.begin();
377 
378                         this.getEntityPublisher(em, body.getAuthInfo());
379 
380                         PublisherDetail result = new PublisherDetail();
381 
382                         Query query = em.createQuery("SELECT p from Publisher as p");
383                         List<Publisher> modelPublisherList = query.getResultList();
384 
385                         for (Publisher modelPublisher : modelPublisherList) {
386 
387                                 org.apache.juddi.api_v3.Publisher apiPublisher = new org.apache.juddi.api_v3.Publisher();
388 
389                                 MappingModelToApi.mapPublisher(modelPublisher, apiPublisher);
390 
391                                 result.getPublisher().add(apiPublisher);
392                         }
393 
394                         tx.commit();
395                         long procTime = System.currentTimeMillis() - startTime;
396                         serviceCounter.update(JUDDIQuery.GET_ALL_PUBLISHER_DETAIL,
397                                 QueryStatus.SUCCESS, procTime);
398                         return result;
399                 } catch (DispositionReportFaultMessage drfm) {
400                         long procTime = System.currentTimeMillis() - startTime;
401                         serviceCounter.update(JUDDIQuery.GET_ALL_PUBLISHER_DETAIL,
402                                 QueryStatus.FAILED, procTime);
403                         throw drfm;
404                 } finally {
405                         if (tx.isActive()) {
406                                 tx.rollback();
407                         }
408                         em.close();
409                 }
410         }
411 
412         /**
413          * Completely deletes a tModel from the persistence layer.
414          * Administrative privilege required. All entities that reference this
415          * tModel will no longer be able to use the tModel if jUDDI Option
416          * Enforce referential Integrity is enabled.<br>
417          * Required permission, you must be am administrator
418          * {@link Property#JUDDI_ENFORCE_REFERENTIAL_INTEGRITY}. In addition,
419          * tModels that are owned by another node via replication cannot be
420          * deleted using this method and will throw an exception
421          *
422          *
423          * @param body
424          * @throws DispositionReportFaultMessage
425          */
426         @Override
427         public void adminDeleteTModel(DeleteTModel body)
428                 throws DispositionReportFaultMessage {
429                 long startTime = System.currentTimeMillis();
430                 EntityManager em = PersistenceManager.getEntityManager();
431                 EntityTransaction tx = em.getTransaction();
432                 try {
433                         tx.begin();
434 
435                         UddiEntityPublisher publisher = this.getEntityPublisher(em, body.getAuthInfo());
436 
437                         new ValidatePublish(publisher).validateAdminDeleteTModel(em, body);
438 
439                         //TODO if referiental integrity is turned on, check to see if this is referenced anywhere and prevent the delete
440                         List<ChangeRecord> changes = new ArrayList<ChangeRecord>();
441                         List<String> entityKeyList = body.getTModelKey();
442                         for (String entityKey : entityKeyList) {
443                                 org.apache.juddi.model.Tmodel obj = em.find(org.apache.juddi.model.Tmodel.class, entityKey);
444 
445                                 if (obj == null) {
446                                         throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.TModelNotFound", entityKey));
447                                 }
448                                 if (!obj.getNodeId().equals(getNode())) {
449                                         throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.TModelNodeOwner", entityKey + " this node " + getNode() + " owning node " + obj.getNodeId()));
450                                 }
451                                 em.remove(obj);
452                                 changes.add(UDDIPublicationImpl.getChangeRecord_deleteTModelDelete(entityKey, getNode(), df));
453 
454                         }
455 
456                         tx.commit();
457                         for (ChangeRecord cr : changes) {
458                                 ReplicationNotifier.enqueue(cr);
459                         }
460                         long procTime = System.currentTimeMillis() - startTime;
461                         serviceCounter.update(JUDDIQuery.ADMIN_DELETE_TMODEL,
462                                 QueryStatus.SUCCESS, procTime);
463                 } catch (DispositionReportFaultMessage drfm) {
464                         long procTime = System.currentTimeMillis() - startTime;
465                         serviceCounter.update(JUDDIQuery.ADMIN_DELETE_TMODEL,
466                                 QueryStatus.FAILED, procTime);
467                         throw drfm;
468                 } finally {
469                         if (tx.isActive()) {
470                                 tx.rollback();
471                         }
472                         em.close();
473                 }
474         }
475 
476         /**
477          * Delete's a client's subscription information. This is typically used
478          * for server to server subscriptions Administrative privilege required.
479          *
480          * @param body
481          * @throws DispositionReportFaultMessage
482          * @throws RemoteException
483          */
484         public void deleteClientSubscriptionInfo(DeleteClientSubscriptionInfo body)
485                 throws DispositionReportFaultMessage, RemoteException {
486                 long startTime = System.currentTimeMillis();
487                 EntityManager em = PersistenceManager.getEntityManager();
488                 EntityTransaction tx = em.getTransaction();
489                 try {
490                         tx.begin();
491 
492                         UddiEntityPublisher publisher = this.getEntityPublisher(em, body.getAuthInfo());
493 
494                         new ValidateClientSubscriptionInfo(publisher).validateDeleteClientSubscriptionInfo(em, body);
495 
496                         List<String> entityKeyList = body.getSubscriptionKey();
497                         for (String entityKey : entityKeyList) {
498                                 Object obj = em.find(org.apache.juddi.model.ClientSubscriptionInfo.class, entityKey);
499                                 em.remove(obj);
500                         }
501 
502                         tx.commit();
503                         long procTime = System.currentTimeMillis() - startTime;
504                         serviceCounter.update(JUDDIQuery.DELETE_CLIENT_SUB,
505                                 QueryStatus.SUCCESS, procTime);
506                 } catch (DispositionReportFaultMessage drfm) {
507                         long procTime = System.currentTimeMillis() - startTime;
508                         serviceCounter.update(JUDDIQuery.DELETE_CLIENT_SUB,
509                                 QueryStatus.FAILED, procTime);
510                         throw drfm;
511 
512                 } finally {
513                         if (tx.isActive()) {
514                                 tx.rollback();
515                         }
516                         em.close();
517                 }
518 
519         }
520 
521         /**
522          * Adds client subscription information. This effectively links a server
523          * to serverr subscription to clerk Administrative privilege required.
524          *
525          * @param body
526          * @return ClientSubscriptionInfoDetail
527          * @throws DispositionReportFaultMessage
528          * @throws RemoteException
529          */
530         public ClientSubscriptionInfoDetail saveClientSubscriptionInfo(SaveClientSubscriptionInfo body)
531                 throws DispositionReportFaultMessage, RemoteException {
532                 long startTime = System.currentTimeMillis();
533                 EntityManager em = PersistenceManager.getEntityManager();
534                 EntityTransaction tx = em.getTransaction();
535                 try {
536                         tx.begin();
537 
538                         UddiEntityPublisher publisher = this.getEntityPublisher(em, body.getAuthInfo());
539 
540                         new ValidateClientSubscriptionInfo(publisher).validateSaveClientSubscriptionInfo(em, body);
541 
542                         ClientSubscriptionInfoDetail result = new ClientSubscriptionInfoDetail();
543 
544                         List<org.apache.juddi.api_v3.ClientSubscriptionInfo> apiClientSubscriptionInfoList = body.getClientSubscriptionInfo();
545                         for (org.apache.juddi.api_v3.ClientSubscriptionInfo apiClientSubscriptionInfo : apiClientSubscriptionInfoList) {
546 
547                                 org.apache.juddi.model.ClientSubscriptionInfo modelClientSubscriptionInfo = new org.apache.juddi.model.ClientSubscriptionInfo();
548 
549                                 MappingApiToModel.mapClientSubscriptionInfo(apiClientSubscriptionInfo, modelClientSubscriptionInfo);
550 
551                                 Object existingUddiEntity = em.find(modelClientSubscriptionInfo.getClass(), modelClientSubscriptionInfo.getSubscriptionKey());
552                                 if (existingUddiEntity != null) {
553                                         em.remove(existingUddiEntity);
554                                 }
555 
556                                 em.persist(modelClientSubscriptionInfo);
557 
558                                 result.getClientSubscriptionInfo().add(apiClientSubscriptionInfo);
559                         }
560 
561                         tx.commit();
562 
563                         long procTime = System.currentTimeMillis() - startTime;
564                         serviceCounter.update(JUDDIQuery.SAVE_CLIENT_SUB,
565                                 QueryStatus.SUCCESS, procTime);
566                         return result;
567                 } catch (DispositionReportFaultMessage drfm) {
568                         long procTime = System.currentTimeMillis() - startTime;
569                         serviceCounter.update(JUDDIQuery.SAVE_CLIENT_SUB,
570                                 QueryStatus.FAILED, procTime);
571                         throw drfm;
572 
573                 } finally {
574                         if (tx.isActive()) {
575                                 tx.rollback();
576                         }
577                         em.close();
578                 }
579         }
580 
581         /**
582          * Gets all client subscription information. This is used for server to
583          * server subscriptions Administrative privilege required.
584          *
585          * @param body
586          * @return ClientSubscriptionInfoDetail
587          * @throws DispositionReportFaultMessage
588          */
589         @SuppressWarnings("unchecked")
590         public ClientSubscriptionInfoDetail getAllClientSubscriptionInfoDetail(GetAllClientSubscriptionInfoDetail body)
591                 throws DispositionReportFaultMessage {
592                 long startTime = System.currentTimeMillis();
593                 new ValidateClientSubscriptionInfo(null).validateGetAllClientSubscriptionDetail(body);
594 
595                 EntityManager em = PersistenceManager.getEntityManager();
596                 EntityTransaction tx = em.getTransaction();
597                 try {
598                         tx.begin();
599 
600                         this.getEntityPublisher(em, body.getAuthInfo());
601 
602                         ClientSubscriptionInfoDetail result = new ClientSubscriptionInfoDetail();
603 
604                         Query query = em.createQuery("SELECT cs from ClientSubscriptionInfo as cs");
605                         List<org.apache.juddi.model.ClientSubscriptionInfo> modelClientSubscriptionInfoList = query.getResultList();
606 
607                         for (ClientSubscriptionInfo modelClientSubscriptionInfo : modelClientSubscriptionInfoList) {
608 
609                                 org.apache.juddi.api_v3.ClientSubscriptionInfo apiClientSubscriptionInfo = new org.apache.juddi.api_v3.ClientSubscriptionInfo();
610 
611                                 MappingModelToApi.mapClientSubscriptionInfo(modelClientSubscriptionInfo, apiClientSubscriptionInfo, em);
612 
613                                 result.getClientSubscriptionInfo().add(apiClientSubscriptionInfo);
614                         }
615 
616                         tx.commit();
617                         long procTime = System.currentTimeMillis() - startTime;
618                         serviceCounter.update(JUDDIQuery.GET_ALL_CLIENT_SUB,
619                                 QueryStatus.SUCCESS, procTime);
620                         return result;
621                 } catch (DispositionReportFaultMessage drfm) {
622                         long procTime = System.currentTimeMillis() - startTime;
623                         serviceCounter.update(JUDDIQuery.GET_ALL_CLIENT_SUB,
624                                 QueryStatus.FAILED, procTime);
625                         throw drfm;
626 
627                 } finally {
628                         if (tx.isActive()) {
629                                 tx.rollback();
630                         }
631                         em.close();
632                 }
633 
634         }
635 
636         /**
637          * Retrieves clientSubscriptionKey(s) from the persistence layer. This
638          * method is specific to jUDDI. Used for server to server subscriptions
639          * Administrative privilege required.
640          *
641          * @param body
642          * @return ClientSubscriptionInfoDetail
643          * @throws DispositionReportFaultMessage
644          */
645         public ClientSubscriptionInfoDetail getClientSubscriptionInfoDetail(GetClientSubscriptionInfoDetail body)
646                 throws DispositionReportFaultMessage {
647                 long startTime = System.currentTimeMillis();
648                 new ValidateClientSubscriptionInfo(null).validateGetClientSubscriptionInfoDetail(body);
649 
650                 EntityManager em = PersistenceManager.getEntityManager();
651                 EntityTransaction tx = em.getTransaction();
652                 try {
653                         tx.begin();
654 
655                         this.getEntityPublisher(em, body.getAuthInfo());
656 
657                         ClientSubscriptionInfoDetail result = new ClientSubscriptionInfoDetail();
658 
659                         List<String> subscriptionKeyList = body.getClientSubscriptionKey();
660                         for (String subscriptionKey : subscriptionKeyList) {
661 
662                                 org.apache.juddi.model.ClientSubscriptionInfo modelClientSubscriptionInfo = null;
663 
664                                 try {
665                                         modelClientSubscriptionInfo = em.find(org.apache.juddi.model.ClientSubscriptionInfo.class, subscriptionKey);
666                                 } catch (ClassCastException e) {
667                                 }
668                                 if (modelClientSubscriptionInfo == null) {
669                                         throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.SubscripKeyNotFound", subscriptionKey));
670                                 }
671 
672                                 org.apache.juddi.api_v3.ClientSubscriptionInfo apiClientSubscriptionInfo = new org.apache.juddi.api_v3.ClientSubscriptionInfo();
673 
674                                 MappingModelToApi.mapClientSubscriptionInfo(modelClientSubscriptionInfo, apiClientSubscriptionInfo, em);
675 
676                                 result.getClientSubscriptionInfo().add(apiClientSubscriptionInfo);
677                         }
678 
679                         tx.commit();
680 
681                         long procTime = System.currentTimeMillis() - startTime;
682                         serviceCounter.update(JUDDIQuery.GET_CLIENT_SUB,
683                                 QueryStatus.SUCCESS, procTime);
684                         return result;
685                 } catch (DispositionReportFaultMessage drfm) {
686                         long procTime = System.currentTimeMillis() - startTime;
687                         serviceCounter.update(JUDDIQuery.GET_CLIENT_SUB,
688                                 QueryStatus.FAILED, procTime);
689                         throw drfm;
690                 } finally {
691                         if (tx.isActive()) {
692                                 tx.rollback();
693                         }
694                         em.close();
695                 }
696 
697         }
698 
699         /**
700          * Saves clerk(s) to the persistence layer. This method is specific to
701          * jUDDI. This is used for server to server subscriptions and for future
702          * use with replication. Administrative privilege required.
703          *
704          * @param body
705          * @return ClerkDetail
706          * @throws DispositionReportFaultMessage
707          */
708         @Override
709         public ClerkDetail saveClerk(SaveClerk body)
710                 throws DispositionReportFaultMessage {
711                 long startTime = System.currentTimeMillis();
712                 EntityManager em = PersistenceManager.getEntityManager();
713                 EntityTransaction tx = em.getTransaction();
714                 try {
715                         tx.begin();
716 
717                         UddiEntityPublisher publisher = this.getEntityPublisher(em, body.getAuthInfo());
718 
719                         new ValidateClerk(publisher).validateSaveClerk(em, body);
720 
721                         ClerkDetail result = new ClerkDetail();
722 
723                         List<org.apache.juddi.api_v3.Clerk> apiClerkList = body.getClerk();;
724                         for (org.apache.juddi.api_v3.Clerk apiClerk : apiClerkList) {
725 
726                                 org.apache.juddi.model.Clerk modelClerk = new org.apache.juddi.model.Clerk();
727 
728                                 MappingApiToModel.mapClerk(apiClerk, modelClerk);
729                                 org.apache.juddi.model.Node node2 = em.find(org.apache.juddi.model.Node.class, apiClerk.getNode().getName());
730                                 if (node2 == null) {
731                                         //it doesn't exist yet
732                                         node2 = new Node();
733                                         MappingApiToModel.mapNode(apiClerk.getNode(), node2);
734                                         em.persist(node2);
735                                 }
736 
737                                 modelClerk.setNode(node2.getName());
738                                 Object existingUddiEntity = em.find(modelClerk.getClass(), modelClerk.getClerkName());
739                                 if (existingUddiEntity != null) {
740 
741                                         em.merge(modelClerk);
742                                 } else {
743                                         em.persist(modelClerk);
744                                 }
745 
746                                 result.getClerk().add(apiClerk);
747                         }
748 
749                         tx.commit();
750                         long procTime = System.currentTimeMillis() - startTime;
751                         serviceCounter.update(JUDDIQuery.SAVE_CLERK,
752                                 QueryStatus.SUCCESS, procTime);
753                         return result;
754                 } catch (DispositionReportFaultMessage drfm) {
755                         long procTime = System.currentTimeMillis() - startTime;
756                         serviceCounter.update(JUDDIQuery.SAVE_CLERK,
757                                 QueryStatus.FAILED, procTime);
758                         throw drfm;
759 
760                 } finally {
761                         if (tx.isActive()) {
762                                 tx.rollback();
763                         }
764                         em.close();
765                 }
766         }
767 
768         /**
769          * Saves nodes(s) to the persistence layer. This method is specific to
770          * jUDDI. Administrative privilege required. This is used for server to
771          * server subscriptions and for future use with replication.
772          * Administrative privilege required.
773          *
774          * @param body
775          * @return NodeDetail
776          * @throws DispositionReportFaultMessage
777          */
778         public NodeDetail saveNode(SaveNode body)
779                 throws DispositionReportFaultMessage {
780                 long startTime = System.currentTimeMillis();
781                 EntityManager em = PersistenceManager.getEntityManager();
782                 EntityTransaction tx = em.getTransaction();
783                 try {
784                         tx.begin();
785 
786                         UddiEntityPublisher publisher = this.getEntityPublisher(em, body.getAuthInfo());
787 
788                         new ValidateNode(publisher).validateSaveNode(em, body);
789 
790                         NodeDetail result = new NodeDetail();
791 
792                         List<org.apache.juddi.api_v3.Node> apiNodeList = body.getNode();
793                         for (org.apache.juddi.api_v3.Node apiNode : apiNodeList) {
794 
795                                 org.apache.juddi.model.Node modelNode = new org.apache.juddi.model.Node();
796 
797                                 MappingApiToModel.mapNode(apiNode, modelNode);
798 
799                                 Object existingUddiEntity = em.find(modelNode.getClass(), modelNode.getName());
800                                 if (existingUddiEntity != null) {
801                                         em.merge(modelNode);
802                                 } else {
803                                         em.persist(modelNode);
804                                 }
805 
806                                 result.getNode().add(apiNode);
807                         }
808 
809                         tx.commit();
810                         long procTime = System.currentTimeMillis() - startTime;
811                         serviceCounter.update(JUDDIQuery.SAVE_NODE,
812                                 QueryStatus.SUCCESS, procTime);
813                         return result;
814                 } catch (DispositionReportFaultMessage drfm) {
815                         long procTime = System.currentTimeMillis() - startTime;
816                         serviceCounter.update(JUDDIQuery.SAVE_NODE,
817                                 QueryStatus.FAILED, procTime);
818                         throw drfm;
819 
820                 } finally {
821                         if (tx.isActive()) {
822                                 tx.rollback();
823                         }
824                         em.close();
825                 }
826         }
827 
828         /**
829          * Instructs the registry to perform a synchronous subscription
830          * response.
831          *
832          * @param body
833          * @return SyncSubscriptionDetail
834          * @throws DispositionReportFaultMessage
835          * @throws RemoteException
836          */
837         @SuppressWarnings("unchecked")
838         @Override
839         public SyncSubscriptionDetail invokeSyncSubscription(
840                 SyncSubscription body) throws DispositionReportFaultMessage,
841                 RemoteException {
842                 long startTime = System.currentTimeMillis();
843                 //validate
844                 SyncSubscriptionDetail syncSubscriptionDetail = new SyncSubscriptionDetail();
845 
846                 Map<String, org.apache.juddi.api_v3.ClientSubscriptionInfo> clientSubscriptionInfoMap
847                         = new HashMap<String, org.apache.juddi.api_v3.ClientSubscriptionInfo>();
848                 //find the clerks to go with these subscriptions
849                 EntityManager em = PersistenceManager.getEntityManager();
850                 EntityTransaction tx = em.getTransaction();
851                 try {
852                         tx.begin();
853 
854                         this.getEntityPublisher(em, body.getAuthInfo());
855                         for (GetSubscriptionResults getSubscriptionResult : body.getGetSubscriptionResultsList()) {
856                                 String subscriptionKey = getSubscriptionResult.getSubscriptionKey();
857                                 org.apache.juddi.model.ClientSubscriptionInfo modelClientSubscriptionInfo = null;
858 
859                                 try {
860                                         modelClientSubscriptionInfo = em.find(org.apache.juddi.model.ClientSubscriptionInfo.class, subscriptionKey);
861                                 } catch (ClassCastException e) {
862                                 }
863                                 if (modelClientSubscriptionInfo == null) {
864                                         throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.SubscripKeyNotFound", subscriptionKey));
865                                 }
866                                 org.apache.juddi.api_v3.ClientSubscriptionInfo apiClientSubscriptionInfo = new org.apache.juddi.api_v3.ClientSubscriptionInfo();
867                                 MappingModelToApi.mapClientSubscriptionInfo(modelClientSubscriptionInfo, apiClientSubscriptionInfo, em);
868                                 clientSubscriptionInfoMap.put(apiClientSubscriptionInfo.getSubscriptionKey(), apiClientSubscriptionInfo);
869                         }
870 
871                         tx.commit();
872                 } catch (DispositionReportFaultMessage drfm) {
873                         long procTime = System.currentTimeMillis() - startTime;
874                         serviceCounter.update(JUDDIQuery.INVOKE_SYNCSUB,
875                                 QueryStatus.FAILED, procTime);
876                         throw drfm;
877 
878                 } finally {
879                         if (tx.isActive()) {
880                                 tx.rollback();
881                         }
882                         em.close();
883                 }
884 
885                 for (GetSubscriptionResults getSubscriptionResult : body.getGetSubscriptionResultsList()) {
886                         try {
887                                 String subscriptionKey = getSubscriptionResult.getSubscriptionKey();
888                                 Clerk fromClerk = clientSubscriptionInfoMap.get(subscriptionKey).getFromClerk();
889                                 Clerk toClerk = clientSubscriptionInfoMap.get(subscriptionKey).getToClerk();
890                                 String clazz = fromClerk.getNode().getProxyTransport();
891                                 Class<?> transportClass = ClassUtil.forName(clazz, this.getClass());
892                                 Transport transport = (Transport) transportClass.getConstructor(String.class
893                                 ).newInstance(fromClerk.getNode().getName());
894                                 UDDISubscriptionPortType subscriptionService = transport.getUDDISubscriptionService(fromClerk.getNode().getSubscriptionUrl());
895                                 SubscriptionResultsList list = subscriptionService.getSubscriptionResults(getSubscriptionResult);
896 
897                                 JAXBContext context = JAXBContext.newInstance(list.getClass());
898                                 Marshaller marshaller = context.createMarshaller();
899                                 StringWriter sw = new StringWriter();
900 
901                                 marshaller.marshal(list, sw);
902 
903                                 log.info(
904                                         "Notification received by UDDISubscriptionListenerService : " + sw.toString());
905 
906                                 NotificationList<String> nl = NotificationList.getInstance();
907 
908                                 nl.getNotifications()
909                                         .add(sw.toString());
910 
911                                 //update the registry with the notification list.
912                                 XRegisterHelper.handle(fromClerk, toClerk, list);
913 
914                                 syncSubscriptionDetail.getSubscriptionResultsList()
915                                         .add(list);
916                         } catch (Exception ce) {
917                                 log.error(ce.getMessage(), ce);
918                                 long procTime = System.currentTimeMillis() - startTime;
919                                 serviceCounter.update(JUDDIQuery.SAVE_NODE,
920                                         QueryStatus.FAILED, procTime);
921                                 if (ce instanceof DispositionReportFaultMessage) {
922                                         throw (DispositionReportFaultMessage) ce;
923                                 }
924                                 if (ce instanceof RemoteException) {
925                                         DispositionReportFaultMessage x = new FatalErrorException(new ErrorMessage("errors.subscriptionnotifier.client", ce.getMessage()));
926                                         throw x;
927                                 }
928                         }
929                 }
930                 //for now sending a clean object back
931 
932                 long procTime = System.currentTimeMillis() - startTime;
933                 serviceCounter.update(JUDDIQuery.INVOKE_SYNCSUB,
934                         QueryStatus.SUCCESS, procTime);
935                 return syncSubscriptionDetail;
936         }
937 
938         @Override
939         public NodeList getAllNodes(String authInfo) throws DispositionReportFaultMessage, RemoteException {
940                 long startTime = System.currentTimeMillis();
941                 NodeList r = new NodeList();
942 
943                 EntityManager em = PersistenceManager.getEntityManager();
944                 EntityTransaction tx = em.getTransaction();
945                 try {
946                         tx.begin();
947 
948                         UddiEntityPublisher publisher = this.getEntityPublisher(em, authInfo);
949 
950                         new ValidatePublish(publisher).validateGetAllNodes();
951 
952                         StringBuilder sql = new StringBuilder();
953                         sql.append("select distinct c from Node c ");
954                         sql.toString();
955                         Query qry = em.createQuery(sql.toString());
956                         List<org.apache.juddi.model.Node> resultList = qry.getResultList();
957                         for (int i = 0; i < resultList.size(); i++) {
958                                 org.apache.juddi.api_v3.Node api = new org.apache.juddi.api_v3.Node();
959                                 MappingModelToApi.mapNode(resultList.get(i), api);
960                                 r.getNode().add(api);
961 
962                         }
963 
964                         tx.commit();
965                         long procTime = System.currentTimeMillis() - startTime;
966                         serviceCounter.update(JUDDIQuery.GET_ALL_NODES,
967                                 QueryStatus.SUCCESS, procTime);
968                 } catch (DispositionReportFaultMessage drfm) {
969                         long procTime = System.currentTimeMillis() - startTime;
970                         serviceCounter.update(JUDDIQuery.GET_ALL_NODES,
971                                 QueryStatus.FAILED, procTime);
972                         throw drfm;
973                 } finally {
974                         if (tx.isActive()) {
975                                 tx.rollback();
976                         }
977                         em.close();
978                 }
979 
980                 return r;
981         }
982 
983         @Override
984         public ClerkList getAllClerks(String authInfo) throws DispositionReportFaultMessage, RemoteException {
985                 long startTime = System.currentTimeMillis();
986                 ClerkList ret = new ClerkList();
987                 EntityManager em = PersistenceManager.getEntityManager();
988                 EntityTransaction tx = em.getTransaction();
989                 try {
990                         tx.begin();
991 
992                         UddiEntityPublisher publisher = this.getEntityPublisher(em, authInfo);
993 
994                         new ValidatePublish(publisher).validateGetAllNodes();
995 
996                         StringBuilder sql = new StringBuilder();
997                         sql.append("select distinct c from Clerk c ");
998                         sql.toString();
999                         Query qry = em.createQuery(sql.toString());
1000                         List<org.apache.juddi.model.Clerk> resultList = qry.getResultList();
1001                         for (int i = 0; i < resultList.size(); i++) {
1002                                 Clerk api = new Clerk();
1003                                 MappingModelToApi.mapClerk(resultList.get(i), api, em);
1004                                 ret.getClerk().add(api);
1005 
1006                         }
1007                         tx.commit();
1008                         long procTime = System.currentTimeMillis() - startTime;
1009                         serviceCounter.update(JUDDIQuery.GET_ALL_CLERKS,
1010                                 QueryStatus.SUCCESS, procTime);
1011                 } catch (DispositionReportFaultMessage drfm) {
1012                         long procTime = System.currentTimeMillis() - startTime;
1013                         serviceCounter.update(JUDDIQuery.GET_ALL_CLERKS,
1014                                 QueryStatus.FAILED, procTime);
1015                         throw drfm;
1016 
1017                 } finally {
1018                         if (tx.isActive()) {
1019                                 tx.rollback();
1020                         }
1021                         em.close();
1022                 }
1023 
1024                 return ret;
1025 
1026         }
1027 
1028         @Override
1029         public void deleteNode(DeleteNode req) throws DispositionReportFaultMessage, RemoteException {
1030                 long startTime = System.currentTimeMillis();
1031                 boolean found = false;
1032                 EntityManager em = PersistenceManager.getEntityManager();
1033                 EntityTransaction tx = em.getTransaction();
1034                 try {
1035                         tx.begin();
1036                         //TODO if the given node is in the replication config, prevent deletion
1037                         UddiEntityPublisher publisher = this.getEntityPublisher(em, req.getAuthInfo());
1038                         new ValidatePublish(publisher).validateDeleteNode(em, req, getReplicationNodes(req.getAuthInfo()));
1039 
1040                         org.apache.juddi.model.Node existingUddiEntity = em.find(org.apache.juddi.model.Node.class, req.getNodeID());
1041                         if (existingUddiEntity != null) {
1042 
1043                                 //cascade delete all clerks tied to this node, confirm that it works
1044                                 Query createQuery = em.createQuery("delete from Clerk c where c.node = :nodename");
1045                                 createQuery.setParameter("nodename", req.getNodeID());
1046                                 createQuery.executeUpdate();
1047 
1048                                 em.remove(existingUddiEntity);
1049                                 found = true;
1050                         } else {
1051                                 throw new InvalidKeyPassedException(new ErrorMessage("errors.deleteNode.NotFound"));
1052                         }
1053 
1054                         tx.commit();
1055                         long procTime = System.currentTimeMillis() - startTime;
1056                         serviceCounter.update(JUDDIQuery.DELETE_NODE,
1057                                 QueryStatus.SUCCESS, procTime);
1058                 } catch (DispositionReportFaultMessage drfm) {
1059                         long procTime = System.currentTimeMillis() - startTime;
1060                         serviceCounter.update(JUDDIQuery.DELETE_NODE,
1061                                 QueryStatus.FAILED, procTime);
1062                         throw drfm;
1063 
1064                 } finally {
1065                         if (tx.isActive()) {
1066                                 tx.rollback();
1067                         }
1068                         em.close();
1069                 }
1070 
1071                 if (!found) {
1072 
1073                         throw new InvalidKeyPassedException(new ErrorMessage("errors.deleteNode.NotFound", req.getNodeID()));
1074                 }
1075         }
1076 
1077         @Override
1078         public void deleteClerk(DeleteClerk req) throws DispositionReportFaultMessage, RemoteException {
1079                 long startTime = System.currentTimeMillis();
1080                 boolean found = false;
1081                 EntityManager em = PersistenceManager.getEntityManager();
1082                 EntityTransaction tx = em.getTransaction();
1083                 try {
1084                         tx.begin();
1085 
1086                         UddiEntityPublisher publisher = this.getEntityPublisher(em, req.getAuthInfo());
1087 
1088                         new ValidatePublish(publisher).validateDeleteClerk(em, req);
1089 
1090                         org.apache.juddi.model.Clerk existingUddiEntity = em.find(org.apache.juddi.model.Clerk.class, req.getClerkID());
1091                         if (existingUddiEntity
1092                                 != null) {
1093                                 em.remove(existingUddiEntity);
1094                                 found = true;
1095                         }
1096 
1097                         tx.commit();
1098                         long procTime = System.currentTimeMillis() - startTime;
1099                         serviceCounter.update(JUDDIQuery.DELETE_CLERK,
1100                                 QueryStatus.SUCCESS, procTime);
1101                 } catch (DispositionReportFaultMessage drfm) {
1102                         long procTime = System.currentTimeMillis() - startTime;
1103                         serviceCounter.update(JUDDIQuery.DELETE_CLERK,
1104                                 QueryStatus.FAILED, procTime);
1105                         throw drfm;
1106 
1107                 } finally {
1108                         if (tx.isActive()) {
1109                                 tx.rollback();
1110                         }
1111                         em.close();
1112                 }
1113 
1114                 if (!found) {
1115                         throw new InvalidKeyPassedException(new ErrorMessage("errors.deleteClerk.NotFound"));
1116                 }
1117 
1118         }
1119 
1120         /*
1121          * enables tmodel owners to setup valid values for tmodel instance infos
1122          * to use?
1123          *
1124          * @param authInfo
1125          * @param values
1126          * @return
1127          * @throws DispositionReportFaultMessage
1128          
1129          @Override
1130          public DispositionReport setAllValidValues(String authInfo, List<ValidValues> values) throws DispositionReportFaultMessage, RemoteException {
1131          throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1132          /*  EntityManager em = PersistenceManager.getEntityManager();
1133          UddiEntityPublisher entityPublisher = getEntityPublisher(em, authInfo);
1134 
1135          new ValidateValueSetValidation(entityPublisher).validateSetAllValidValues(values);
1136 
1137          EntityTransaction tx = em.getTransaction();
1138          try {
1139 
1140          // is this tModel used anywhere?, if so, validate all instances against the new rule?
1141          tx.begin();
1142 
1143          //each tmodel/value set
1144          for (int i = 0; i < values.size(); i++) {
1145          //remove any existing references to the key
1146          ValueSetValues find = em.find(ValueSetValues.class, values.get(i).getTModekKey());
1147 
1148          if (find != null) {
1149          find.setValidatorClass(values.get(i).getValidationClass());
1150          em.persist(find);
1151 
1152          } else {
1153          org.apache.juddi.model.ValueSetValues vv = new ValueSetValues();
1154          vv.setTModelKey(values.get(i).getTModekKey());
1155          vv.setValidatorClass(values.get(i).getValidationClass());
1156          em.persist(vv);
1157          }
1158          }
1159 
1160          tx.commit();
1161          } finally {
1162          if (tx.isActive()) {
1163          tx.rollback();
1164          }
1165          em.close();
1166          }
1167          DispositionReport r = new DispositionReport();
1168          r.getResult().add(new Result());
1169          return r;
1170          }*/
1171         @Override
1172         public void adminDeleteSubscription(String authInfo, List<String> subscriptionKey) throws DispositionReportFaultMessage, RemoteException {
1173 
1174                 long startTime = System.currentTimeMillis();
1175 
1176                 EntityManager em = PersistenceManager.getEntityManager();
1177                 EntityTransaction tx = em.getTransaction();
1178                 try {
1179                         tx.begin();
1180 
1181                         UddiEntityPublisher requestor = this.getEntityPublisher(em, authInfo);
1182                         if (!((Publisher) requestor).isAdmin()) {
1183                                 throw new UserMismatchException(new ErrorMessage("errors.AdminReqd"));
1184                         }
1185                         //new ValidateSubscription(publisher).validateDeleteSubscription(em, body);
1186                         List<TemporaryMailContainer> notifications = new ArrayList<TemporaryMailContainer>();
1187                         List<String> subscriptionKeyList = subscriptionKey;
1188                         for (String key : subscriptionKeyList) {
1189                                 if (key != null && key.length() > 0) {
1190                                         org.apache.juddi.model.Subscription obj = em.find(org.apache.juddi.model.Subscription.class, key);
1191                                         Publisher publisher = em.find(Publisher.class, obj.getAuthorizedName());
1192                                         notifications.add(new TemporaryMailContainer(obj, publisher, (Publisher) requestor));
1193                                         em.remove(obj);
1194                                 }
1195                         }
1196 
1197                         tx.commit();
1198                         for (TemporaryMailContainer t : notifications) {
1199                                 USERFRIENDLYSMTPNotifier.notifySubscriptionDeleted(t);
1200                         }
1201                         notifications.clear();
1202                         notifications = null;
1203                         long procTime = System.currentTimeMillis() - startTime;
1204                         serviceCounter.update(JUDDIQuery.ADMIN_DELETE_SUB,
1205                                 QueryStatus.SUCCESS, procTime);
1206                 } catch (DispositionReportFaultMessage drfm) {
1207                         long procTime = System.currentTimeMillis() - startTime;
1208                         serviceCounter.update(JUDDIQuery.ADMIN_DELETE_SUB,
1209                                 QueryStatus.FAILED, procTime);
1210                         throw drfm;
1211                 } finally {
1212                         if (tx.isActive()) {
1213                                 tx.rollback();
1214                         }
1215                         em.close();
1216                 }
1217 
1218         }
1219 
1220         @Override
1221         public DispositionReport adminSaveBusiness(String authInfo, List<AdminSaveBusinessWrapper> values) throws DispositionReportFaultMessage, RemoteException {
1222                 long startTime = System.currentTimeMillis();
1223                 EntityManager em = PersistenceManager.getEntityManager();
1224                 EntityTransaction tx = em.getTransaction();
1225                 try {
1226                         tx.begin();
1227                         UddiEntityPublisher requestor = this.getEntityPublisher(em, authInfo);
1228                         if (!((Publisher) requestor).isAdmin()) {
1229                                 throw new UserMismatchException(new ErrorMessage("errors.AdminReqd"));
1230                         }
1231 
1232                         for (int i = 0; i < values.size(); i++) {
1233                                 //impersonate the user
1234                                 AuthToken authToken = sec.getAuthToken(values.get(i).getPublisherID());
1235 
1236                                 SaveBusiness stm = new SaveBusiness();
1237 
1238                                 stm.setAuthInfo(authToken.getAuthInfo());
1239                                 stm.getBusinessEntity().addAll(values.get(i).getBusinessEntity());
1240                                 pub.saveBusiness(stm);
1241                         }
1242 
1243                         tx.commit();
1244                         long procTime = System.currentTimeMillis() - startTime;
1245                         serviceCounter.update(JUDDIQuery.ADMIN_SAVE_BUSINESS,
1246                                 QueryStatus.SUCCESS, procTime);
1247                 } catch (DispositionReportFaultMessage drfm) {
1248                         long procTime = System.currentTimeMillis() - startTime;
1249                         serviceCounter.update(JUDDIQuery.ADMIN_SAVE_BUSINESS,
1250                                 QueryStatus.FAILED, procTime);
1251                         throw drfm;
1252 
1253                 } finally {
1254                         if (tx.isActive()) {
1255                                 tx.rollback();
1256                         }
1257                         em.close();
1258                 }
1259 
1260                 DispositionReport r = new DispositionReport();
1261                 return r;
1262 
1263         }
1264 
1265         @Override
1266         public DispositionReport adminSaveTModel(String authInfo, List<AdminSaveTModelWrapper> values) throws DispositionReportFaultMessage, RemoteException {
1267                 long startTime = System.currentTimeMillis();
1268                 EntityManager em = PersistenceManager.getEntityManager();
1269                 EntityTransaction tx = em.getTransaction();
1270                 try {
1271                         tx.begin();
1272                         UddiEntityPublisher requestor = this.getEntityPublisher(em, authInfo);
1273                         if (!((Publisher) requestor).isAdmin()) {
1274                                 throw new UserMismatchException(new ErrorMessage("errors.AdminReqd"));
1275                         }
1276 
1277                         for (int i = 0; i < values.size(); i++) {
1278                                 //impersonate the user
1279                                 AuthToken authToken = sec.getAuthToken(values.get(i).getPublisherID());
1280                                 SaveTModel stm = new SaveTModel();
1281                                 stm.setAuthInfo(authToken.getAuthInfo());
1282                                 stm.getTModel().addAll(values.get(i).getTModel());
1283                                 pub.saveTModel(stm);
1284                         }
1285                         tx.commit();
1286                         long procTime = System.currentTimeMillis() - startTime;
1287                         serviceCounter.update(JUDDIQuery.ADMIN_SAVE_TMODEL,
1288                                 QueryStatus.SUCCESS, procTime);
1289                 } catch (DispositionReportFaultMessage drfm) {
1290                         long procTime = System.currentTimeMillis() - startTime;
1291                         serviceCounter.update(JUDDIQuery.ADMIN_SAVE_TMODEL,
1292                                 QueryStatus.FAILED, procTime);
1293                         throw drfm;
1294 
1295                 } finally {
1296                         if (tx.isActive()) {
1297                                 tx.rollback();
1298                         }
1299                         em.close();
1300                 }
1301 
1302                 DispositionReport r = new DispositionReport();
1303                 return r;
1304         }
1305 
1306         @Override
1307         public List<SubscriptionWrapper> getAllClientSubscriptionInfo(String authInfo) throws DispositionReportFaultMessage, RemoteException {
1308                 long startTime = System.currentTimeMillis();
1309 
1310                 List<SubscriptionWrapper> r = new ArrayList<SubscriptionWrapper>();
1311 
1312                 EntityManager em = PersistenceManager.getEntityManager();
1313                 EntityTransaction tx = em.getTransaction();
1314                 try {
1315                         tx.begin();
1316 
1317                         UddiEntityPublisher publisher = this.getEntityPublisher(em, authInfo);
1318                         if (!((Publisher) publisher).isAdmin()) {
1319                                 throw new UserMismatchException(new ErrorMessage("errors.AdminReqd"));
1320                         }
1321 
1322                         StringBuilder sql = new StringBuilder();
1323                         sql.append("select distinct c from Subscription c ");
1324                         Query qry = em.createQuery(sql.toString());
1325                         List<org.apache.juddi.model.Subscription> resultList = qry.getResultList();
1326                         for (int i = 0; i < resultList.size(); i++) {
1327                                 Subscription sub = new Subscription();
1328                                 MappingModelToApi.mapSubscription(resultList.get(i), sub);
1329                                 SubscriptionWrapper x = new SubscriptionWrapper();
1330                                 x.getSubscription().add(sub);
1331                                 x.setPublisherIdOrUsername(resultList.get(i).getAuthorizedName());
1332                                 r.add(x);
1333                         }
1334 
1335                         tx.commit();
1336                         long procTime = System.currentTimeMillis() - startTime;
1337                         serviceCounter.update(JUDDIQuery.GET_ALL_CLIENT_SUB,
1338                                 QueryStatus.SUCCESS, procTime);
1339                 } catch (DispositionReportFaultMessage drfm) {
1340                         long procTime = System.currentTimeMillis() - startTime;
1341                         serviceCounter.update(JUDDIQuery.GET_ALL_CLIENT_SUB,
1342                                 QueryStatus.FAILED, procTime);
1343                         throw drfm;
1344                 } finally {
1345                         if (tx.isActive()) {
1346                                 tx.rollback();
1347                         }
1348                         em.close();
1349                 }
1350 
1351                 return r;
1352         }
1353 
1354         @Override
1355         public synchronized DispositionReport setReplicationNodes(String authInfo, org.uddi.repl_v3.ReplicationConfiguration replicationConfiguration) throws DispositionReportFaultMessage, RemoteException {
1356                 long startTime = System.currentTimeMillis();
1357 
1358                 EntityManager em = PersistenceManager.getEntityManager();
1359                 EntityTransaction tx = em.getTransaction();
1360                 try {
1361                         tx.begin();
1362 
1363                         org.uddi.repl_v3.ReplicationConfiguration oldConfig = null;
1364                         UddiEntityPublisher publisher = this.getEntityPublisher(em, authInfo);
1365                         if (!((Publisher) publisher).isAdmin()) {
1366                                 throw new UserMismatchException(new ErrorMessage("errors.AdminReqd"));
1367                         }
1368                         new ValidateReplication(publisher).validateSetReplicationNodes(replicationConfiguration, em, getNode(), AppConfig.getConfiguration());
1369 
1370                         org.apache.juddi.model.ReplicationConfiguration model = null;
1371                         logger.info(publisher.getAuthorizedName() + " is setting the replication config from " + getRequestorsIPAddress());// + " " + sw.toString());
1372                         try {
1373                                 model = (ReplicationConfiguration) em.createQuery("select c FROM ReplicationConfiguration c order by c.serialNumber desc").getSingleResult();
1374                         } catch (Exception ex) {
1375                         }
1376                         SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddkkmmZ");
1377                         if (model == null) {
1378                                 //this is a brand new configuration and we didn't have one before
1379                                 model = new ReplicationConfiguration();
1380                                 MappingApiToModel.mapReplicationConfiguration(replicationConfiguration, model, em);
1381                                 model.setSerialNumber(System.currentTimeMillis());
1382                                 model.setTimeOfConfigurationUpdate(sdf.format(new Date()));
1383                                 em.persist(model);
1384                                 //if (newReplicationNode(model)){
1385                                 //tell the replication notifier to start transfering with
1386                                 //the first change record
1387                                 //}
1388 
1389                         } else {
1390                                 //a config exists, remove it, add the new one
1391                                 //spec doesn't appear to mention if recording a change history on the config is required
1392                                 //assuming we'll keep it for now, might be useful later.
1393                                 //em.remove(model);
1394                                 oldConfig = new org.uddi.repl_v3.ReplicationConfiguration();
1395                                 MappingModelToApi.mapReplicationConfiguration(model, oldConfig);
1396 
1397                                 ReplicationConfiguration model2 = new ReplicationConfiguration();
1398                                 MappingApiToModel.mapReplicationConfiguration(replicationConfiguration, model2, em);
1399                                 model2.setSerialNumber(System.currentTimeMillis());
1400 
1401                                 model2.setTimeOfConfigurationUpdate(sdf.format(new Date()));
1402                                 em.persist(model2);
1403 
1404                         }
1405 
1406                         tx.commit();
1407                         UDDIReplicationImpl.notifyConfigurationChange(oldConfig, replicationConfiguration, this);
1408                         long procTime = System.currentTimeMillis() - startTime;
1409                         serviceCounter.update(JUDDIQuery.SET_REPLICATION_NODES,
1410                                 QueryStatus.SUCCESS, procTime);
1411                 } catch (DispositionReportFaultMessage drfm) {
1412                         long procTime = System.currentTimeMillis() - startTime;
1413                         serviceCounter.update(JUDDIQuery.SET_REPLICATION_NODES,
1414                                 QueryStatus.FAILED, procTime);
1415                         throw drfm;
1416                 } catch (Exception ex) {
1417                         logger.error(ex, ex);
1418                         throw new FatalErrorException(new ErrorMessage("E_fatalError", ex.getMessage()));
1419                 } finally {
1420                         if (tx.isActive()) {
1421                                 tx.rollback();
1422                         }
1423                         em.close();
1424                 }
1425                 DispositionReport d = new DispositionReport();
1426                 Result res = new Result();
1427 
1428                 d.getResult().add(res);
1429                 return d;
1430         }
1431 
1432         @Override
1433         public synchronized org.uddi.repl_v3.ReplicationConfiguration getReplicationNodes(String authInfo) throws DispositionReportFaultMessage, RemoteException {
1434                 long startTime = System.currentTimeMillis();
1435                 org.uddi.repl_v3.ReplicationConfiguration r = new org.uddi.repl_v3.ReplicationConfiguration();
1436 
1437                 EntityManager em = PersistenceManager.getEntityManager();
1438                 EntityTransaction tx = em.getTransaction();
1439                 try {
1440                         tx.begin();
1441 
1442                         UddiEntityPublisher publisher = this.getEntityPublisher(em, authInfo);
1443                         if (!((Publisher) publisher).isAdmin()) {
1444                                 throw new UserMismatchException(new ErrorMessage("errors.AdminReqd"));
1445                         }
1446 
1447                         StringBuilder sql = new StringBuilder();
1448                         sql.append("select c from ReplicationConfiguration c order by c.serialNumber desc");
1449                         //sql.toString();
1450                         Query qry = em.createQuery(sql.toString());
1451                         qry.setMaxResults(1);
1452 
1453                         org.apache.juddi.model.ReplicationConfiguration resultList = (org.apache.juddi.model.ReplicationConfiguration) qry.getSingleResult();
1454                         MappingModelToApi.mapReplicationConfiguration(resultList, r);
1455                         tx.commit();
1456                         long procTime = System.currentTimeMillis() - startTime;
1457                         serviceCounter.update(JUDDIQuery.GET_ALL_NODES,
1458                                 QueryStatus.SUCCESS, procTime);
1459                 } catch (DispositionReportFaultMessage drfm) {
1460                         long procTime = System.currentTimeMillis() - startTime;
1461                         serviceCounter.update(JUDDIQuery.GET_ALL_NODES,
1462                                 QueryStatus.FAILED, procTime);
1463                         throw drfm;
1464                 } catch (Exception ex) {
1465                         //possible that there is no config to return
1466                         logger.debug("Error caught, is there a replication config is avaiable? Returning a default config (no replication): ", ex);
1467 
1468                         r.setCommunicationGraph(new CommunicationGraph());
1469                         Operator op = new Operator();
1470                         op.setOperatorNodeID(getNode());
1471                         op.setSoapReplicationURL(baseUrlSSL + "replication/services/replication");
1472 
1473                         op.getContact().add(new Contact());
1474                         op.getContact().get(0).getPersonName().add(new PersonName("Unknown", null));
1475                         op.setOperatorStatus(OperatorStatusType.NORMAL);
1476 
1477                         r.getOperator().add(op);
1478                         r.getCommunicationGraph().getNode().add(getNode());
1479                         r.getCommunicationGraph().getControlledMessage().add("*");
1480                         long procTime = System.currentTimeMillis() - startTime;
1481                         r.setSerialNumber(0);
1482                         SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddkkmmZ");
1483                         r.setTimeOfConfigurationUpdate(sdf.format(new Date()));
1484                         r.setRegistryContact(new org.uddi.repl_v3.ReplicationConfiguration.RegistryContact());
1485                         try {
1486                                 // pull from root business
1487                                 if (!tx.isActive()) {
1488                                         tx = em.getTransaction();
1489                                 }
1490 
1491                                 BusinessEntity rootbiz = em.find(BusinessEntity.class, AppConfig.getConfiguration().getString(Property.JUDDI_NODE_ROOT_BUSINESS));
1492                                 if (rootbiz != null) {
1493 
1494                                         for (int i = 0; i < rootbiz.getContacts().size(); i++) {
1495                                                 Contact c = new Contact();
1496                                                 MappingModelToApi.mapContact(rootbiz.getContacts().get(i), c);
1497                                                 r.getRegistryContact().setContact(c);
1498                                                 break;
1499                                         }
1500 
1501                                 }
1502                                 tx.rollback();
1503 
1504                         } catch (Exception ex1) {
1505                                 logger.warn("unexpected error", ex1);
1506                         }
1507                         if (r.getRegistryContact().getContact() == null) {
1508                                 r.getRegistryContact().setContact(new Contact());
1509                                 r.getRegistryContact().getContact().getPersonName().add(new PersonName("Unknown", null));
1510                         }
1511                         serviceCounter.update(JUDDIQuery.GET_REPLICATION_NODES,
1512                                 QueryStatus.SUCCESS, procTime);
1513 
1514                 } finally {
1515                         if (tx.isActive()) {
1516                                 tx.rollback();
1517                         }
1518                         em.close();
1519                 }
1520 
1521                 r.setMaximumTimeToGetChanges(BigInteger.ONE);
1522                 r.setMaximumTimeToSyncRegistry(BigInteger.ONE);
1523                 //StringWriter sw = new StringWriter();
1524                 //JAXB.marshal(r, sw);
1525                 //logger.info("dumping returned replication config " + sw.toString());
1526                 return r;
1527         }
1528 
1529         static UDDISubscriptionImpl sub = new UDDISubscriptionImpl();
1530         static UDDISecurityImpl sec = new UDDISecurityImpl();
1531         static UDDIPublicationImpl pub = new UDDIPublicationImpl();
1532 
1533         @Override
1534         public void adminSaveSubscription(String authInfo, String publisherOrUsername, Holder<List<Subscription>> subscriptions) throws DispositionReportFaultMessage {
1535                 long startTime = System.currentTimeMillis();
1536                 EntityManager em = PersistenceManager.getEntityManager();
1537                 EntityTransaction tx = em.getTransaction();
1538                 try {
1539                         tx.begin();
1540                         UddiEntityPublisher requestor = this.getEntityPublisher(em, authInfo);
1541                         if (!((Publisher) requestor).isAdmin()) {
1542                                 throw new UserMismatchException(new ErrorMessage("errors.AdminReqd"));
1543                         }
1544                         //impersonate the user
1545                         AuthToken authToken = sec.getAuthToken(publisherOrUsername);
1546                         sub.saveSubscription(authToken.getAuthInfo(), subscriptions);
1547                         tx.commit();
1548                         long procTime = System.currentTimeMillis() - startTime;
1549                         serviceCounter.update(JUDDIQuery.ADMIN_SAVE_SUB,
1550                                 QueryStatus.SUCCESS, procTime);
1551                 } catch (DispositionReportFaultMessage drfm) {
1552                         long procTime = System.currentTimeMillis() - startTime;
1553                         serviceCounter.update(JUDDIQuery.ADMIN_SAVE_SUB,
1554                                 QueryStatus.FAILED, procTime);
1555                         throw drfm;
1556 
1557                 } finally {
1558                         if (tx.isActive()) {
1559                                 tx.rollback();
1560                         }
1561                         em.close();
1562                 }
1563 
1564         }
1565 
1566         /**
1567          * {@inheritDoc }
1568          *
1569          * @param body
1570          * @return item history or null if not found
1571          * @throws DispositionReportFaultMessage
1572          * @throws RemoteException
1573          */
1574         @Override
1575         public GetEntityHistoryMessageResponse getEntityHistory(GetEntityHistoryMessageRequest body) throws DispositionReportFaultMessage, RemoteException {
1576                 long startTime = System.currentTimeMillis();
1577                 if (body == null) {
1578                         throw new InvalidValueException(new ErrorMessage("errors.NullInput"));
1579                 }
1580                 EntityManager em = PersistenceManager.getEntityManager();
1581                 EntityTransaction tx = em.getTransaction();
1582                 try {
1583                         tx.begin();
1584                         UddiEntityPublisher requestor = this.getEntityPublisher(em, body.getAuthInfo());
1585                         if (!((Publisher) requestor).isAdmin()) {
1586                                 throw new UserMismatchException(new ErrorMessage("errors.AdminReqd"));
1587                         }
1588                         if (body.getMaxRecords() <= 0) {
1589                                 body.setMaxRecords(20);
1590                         }
1591                         if (body.getOffset() < 0) {
1592                                 body.setOffset(0);
1593                         }
1594                         Query createQuery = em.createQuery("select m from ChangeRecord m where m.entityKey = :key order by m.id DESC");
1595                         createQuery.setMaxResults((int) body.getMaxRecords());
1596                         createQuery.setParameter("key", body.getEntityKey());
1597                         createQuery.setFirstResult((int) body.getOffset());
1598                         List<ChangeRecord> resultList = createQuery.getResultList();
1599                         GetEntityHistoryMessageResponse res = new GetEntityHistoryMessageResponse();
1600                         res.setChangeRecords(new ChangeRecords());
1601                         for (ChangeRecord cr : resultList) {
1602                                 res.getChangeRecords().getChangeRecord().add(MappingModelToApi.mapChangeRecord(cr));
1603                         }
1604 
1605                         tx.rollback();
1606                         long procTime = System.currentTimeMillis() - startTime;
1607                         serviceCounter.update(JUDDIQuery.ADMIN_GET_HISTORY,
1608                                 QueryStatus.SUCCESS, procTime);
1609                         return res;
1610                 } catch (DispositionReportFaultMessage drfm) {
1611                         long procTime = System.currentTimeMillis() - startTime;
1612                         serviceCounter.update(JUDDIQuery.ADMIN_GET_HISTORY,
1613                                 QueryStatus.FAILED, procTime);
1614                         throw drfm;
1615 
1616                 } finally {
1617                         if (tx.isActive()) {
1618                                 tx.rollback();
1619                         }
1620                         em.close();
1621                 }
1622         }
1623 
1624         /**
1625          * {@inheritDoc }
1626          *
1627          * @param body
1628          * @return
1629          * @throws DispositionReportFaultMessage
1630          * @throws RemoteException
1631          */
1632         @Override
1633         public GetFailedReplicationChangeRecordsMessageResponse getFailedReplicationChangeRecords(
1634                 GetFailedReplicationChangeRecordsMessageRequest body)
1635                 throws DispositionReportFaultMessage, RemoteException {
1636                 //public GetFailedReplicationChangeRecordsMessageResponse getFailedReplicationChangeRecords(GetFailedReplicationChangeRecordsMessageRequest body) throws DispositionReportFaultMessage, RemoteException {
1637                 long startTime = System.currentTimeMillis();
1638                 if (body == null) {
1639                         throw new InvalidValueException(new ErrorMessage("errors.NullInput"));
1640                 }
1641                 EntityManager em = PersistenceManager.getEntityManager();
1642                 EntityTransaction tx = em.getTransaction();
1643                 try {
1644                         tx.begin();
1645                         UddiEntityPublisher requestor = this.getEntityPublisher(em, body.getAuthInfo());
1646                         if (!((Publisher) requestor).isAdmin()) {
1647                                 throw new UserMismatchException(new ErrorMessage("errors.AdminReqd"));
1648                         }
1649                         if (body.getMaxRecords() <= 0) {
1650                                 body.setMaxRecords(20);
1651                         }
1652                         if (body.getOffset() < 0) {
1653                                 body.setOffset(0);
1654                         }
1655                         Query createQuery = em.createQuery("select m from ChangeRecord m where m.isAppliedLocally=false order by m.id DESC ");
1656                         createQuery.setMaxResults((int) body.getMaxRecords());
1657                         createQuery.setFirstResult((int) body.getOffset());
1658                         List<ChangeRecord> resultList = createQuery.getResultList();
1659                         GetFailedReplicationChangeRecordsMessageResponse res = new GetFailedReplicationChangeRecordsMessageResponse();
1660                         res.setChangeRecords(new ChangeRecords());
1661                         for (ChangeRecord cr : resultList) {
1662                                 res.getChangeRecords().getChangeRecord().add(MappingModelToApi.mapChangeRecord(cr));
1663                         }
1664 
1665                         tx.rollback();
1666                         long procTime = System.currentTimeMillis() - startTime;
1667                         serviceCounter.update(JUDDIQuery.ADMIN_GET_FAILED_CRS,
1668                                 QueryStatus.SUCCESS, procTime);
1669                         return res;
1670                 } catch (DispositionReportFaultMessage drfm) {
1671                         long procTime = System.currentTimeMillis() - startTime;
1672                         serviceCounter.update(JUDDIQuery.ADMIN_GET_FAILED_CRS,
1673                                 QueryStatus.FAILED, procTime);
1674                         throw drfm;
1675 
1676                 } finally {
1677                         if (tx.isActive()) {
1678                                 tx.rollback();
1679                         }
1680                         em.close();
1681                 }
1682         }
1683 }