Repository: juddi Updated Branches: refs/heads/master 47d12803c -> 70903c270
JUDDI-256 adding basic unit test for transfer to/from publishers on the same node JUDDI-272 adding hooks for node to node transfer Project: http://git-wip-us.apache.org/repos/asf/juddi/repo Commit: http://git-wip-us.apache.org/repos/asf/juddi/commit/70903c27 Tree: http://git-wip-us.apache.org/repos/asf/juddi/tree/70903c27 Diff: http://git-wip-us.apache.org/repos/asf/juddi/diff/70903c27 Branch: refs/heads/master Commit: 70903c27054e1ebb8c064cc3a1afce9842c07cb5 Parents: 47d1280 Author: Alex <[email protected]> Authored: Mon Dec 22 21:09:26 2014 -0500 Committer: Alex <[email protected]> Committed: Mon Dec 22 21:09:26 2014 -0500 ---------------------------------------------------------------------- .../juddi/api/impl/UDDICustodyTransferImpl.java | 260 ++++++++++++------- .../juddi/api/impl/UDDIReplicationImpl.java | 153 ++++++++++- .../apache/juddi/model/UddiEntityPublisher.java | 5 +- .../juddi/replication/ReplicationNotifier.java | 2 - .../validation/ValidateCustodyTransfer.java | 23 +- .../juddi/validation/ValidateReplication.java | 30 +++ .../src/main/resources/messages.properties | 1 + .../api/impl/API_170_CustodyTransferTest.java | 129 +++++++++ 8 files changed, 480 insertions(+), 123 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/juddi/blob/70903c27/juddi-core/src/main/java/org/apache/juddi/api/impl/UDDICustodyTransferImpl.java ---------------------------------------------------------------------- diff --git a/juddi-core/src/main/java/org/apache/juddi/api/impl/UDDICustodyTransferImpl.java b/juddi-core/src/main/java/org/apache/juddi/api/impl/UDDICustodyTransferImpl.java index 2bb21f2..2c5d295 100644 --- a/juddi-core/src/main/java/org/apache/juddi/api/impl/UDDICustodyTransferImpl.java +++ b/juddi-core/src/main/java/org/apache/juddi/api/impl/UDDICustodyTransferImpl.java @@ -16,7 +16,9 @@ */ package org.apache.juddi.api.impl; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; +import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import java.util.UUID; @@ -31,6 +33,7 @@ import javax.persistence.Query; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.ws.BindingProvider; import javax.xml.ws.Holder; import org.apache.commons.configuration.ConfigurationException; @@ -38,18 +41,22 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.juddi.api.util.CustodyTransferQuery; import org.apache.juddi.api.util.QueryStatus; -import org.apache.juddi.api.util.ValueSetValidationQuery; import org.apache.juddi.config.AppConfig; import org.apache.juddi.config.PersistenceManager; import org.apache.juddi.config.Property; +import org.apache.juddi.mapping.MappingApiToModel; +import org.apache.juddi.mapping.MappingModelToApi; import org.apache.juddi.model.BindingTemplate; import org.apache.juddi.model.BusinessEntity; import org.apache.juddi.model.BusinessService; +import org.apache.juddi.model.Operator; +import org.apache.juddi.model.Tmodel; import org.apache.juddi.model.TransferTokenKey; import org.apache.juddi.model.UddiEntity; import org.apache.juddi.model.UddiEntityPublisher; import org.apache.juddi.query.util.DynamicQuery; import org.apache.juddi.replication.ReplicationNotifier; +import org.apache.juddi.v3.client.UDDIService; import org.apache.juddi.v3.error.ErrorMessage; import org.apache.juddi.v3.error.FatalErrorException; import org.apache.juddi.validation.ValidateCustodyTransfer; @@ -57,16 +64,22 @@ import org.uddi.api_v3.OperationalInfo; import org.uddi.custody_v3.DiscardTransferToken; import org.uddi.custody_v3.KeyBag; import org.uddi.custody_v3.TransferEntities; +import org.uddi.custody_v3.TransferOperationalInfo; +import org.uddi.repl_v3.ChangeRecord; +import org.uddi.repl_v3.ChangeRecordIDType; +import org.uddi.repl_v3.ChangeRecordNewData; +import org.uddi.repl_v3.TransferCustody; import org.uddi.v3_service.DispositionReportFaultMessage; import org.uddi.v3_service.UDDICustodyTransferPortType; +import org.uddi.v3_service.UDDIReplicationPortType; /** * This implements the UDDI v3 Custody Transfer API web service * */ @WebService(serviceName = "UDDICustodyTransferService", - endpointInterface = "org.uddi.v3_service.UDDICustodyTransferPortType", - targetNamespace = "urn:uddi-org:v3_service") + endpointInterface = "org.uddi.v3_service.UDDICustodyTransferPortType", + targetNamespace = "urn:uddi-org:v3_service") public class UDDICustodyTransferImpl extends AuthenticatedService implements UDDICustodyTransferPortType { public static final String TRANSFER_TOKEN_PREFIX = "transfertoken:"; @@ -77,7 +90,7 @@ public class UDDICustodyTransferImpl extends AuthenticatedService implements UDD private static DatatypeFactory df = null; private UDDIServiceCounter serviceCounter; - public UDDICustodyTransferImpl() { + public UDDICustodyTransferImpl() { super(); serviceCounter = ServiceCounterLifecycleResource.getServiceCounter(this.getClass()); if (df == null) { @@ -90,8 +103,9 @@ public class UDDICustodyTransferImpl extends AuthenticatedService implements UDD } @SuppressWarnings("unchecked") + @Override public void discardTransferToken(DiscardTransferToken body) - throws DispositionReportFaultMessage { + throws DispositionReportFaultMessage { long startTime = System.currentTimeMillis(); EntityManager em = PersistenceManager.getEntityManager(); @@ -119,8 +133,8 @@ public class UDDICustodyTransferImpl extends AuthenticatedService implements UDD for (String key : keyList) { // Creating parameters for key-checking query DynamicQuery.Parameter param = new DynamicQuery.Parameter("UPPER(ttk.entityKey)", - key.toUpperCase(), - DynamicQuery.PREDICATE_EQUALS); + key.toUpperCase(), + DynamicQuery.PREDICATE_EQUALS); params.add(param); } @@ -142,7 +156,7 @@ public class UDDICustodyTransferImpl extends AuthenticatedService implements UDD tx.commit(); long procTime = System.currentTimeMillis() - startTime; serviceCounter.update(CustodyTransferQuery.DISCARD_TRANSFERTOKEN, - QueryStatus.SUCCESS, procTime); + QueryStatus.SUCCESS, procTime); } finally { if (tx.isActive()) { @@ -152,9 +166,10 @@ public class UDDICustodyTransferImpl extends AuthenticatedService implements UDD } } + @Override public void getTransferToken(String authInfo, KeyBag keyBag, - Holder<String> nodeID, Holder<XMLGregorianCalendar> expirationTime, - Holder<byte[]> opaqueToken) throws DispositionReportFaultMessage { + Holder<String> nodeID, Holder<XMLGregorianCalendar> expirationTime, + Holder<byte[]> opaqueToken) throws DispositionReportFaultMessage { long startTime = System.currentTimeMillis(); EntityManager em = PersistenceManager.getEntityManager(); @@ -206,7 +221,7 @@ public class UDDICustodyTransferImpl extends AuthenticatedService implements UDD long procTime = System.currentTimeMillis() - startTime; serviceCounter.update(CustodyTransferQuery.GET_TRANSFERTOKEN, - QueryStatus.SUCCESS, procTime); + QueryStatus.SUCCESS, procTime); } finally { if (tx.isActive()) { @@ -216,111 +231,124 @@ public class UDDICustodyTransferImpl extends AuthenticatedService implements UDD } } + @Override public void transferEntities(TransferEntities body) - throws DispositionReportFaultMessage { + throws DispositionReportFaultMessage { long startTime = System.currentTimeMillis(); EntityManager em = PersistenceManager.getEntityManager(); EntityTransaction tx = em.getTransaction(); + List<ChangeRecord> changes = new ArrayList<ChangeRecord>(); try { tx.begin(); UddiEntityPublisher publisher = this.getEntityPublisher(em, body.getAuthInfo()); - new ValidateCustodyTransfer(publisher).validateTransferEntities(em, body); - - // Once validated, the ownership transfer is as simple as switching the publisher - KeyBag keyBag = body.getKeyBag(); - List<String> keyList = keyBag.getKey(); - //used for the change journal - List<OperationalInfo> op_info = new ArrayList<OperationalInfo>(); - for (String key : keyList) { - UddiEntity uddiEntity = em.find(UddiEntity.class, key); - uddiEntity.setAuthorizedName(publisher.getAuthorizedName()); - OperationalInfo o = new OperationalInfo(); - o.setAuthorizedName(publisher.getAuthorizedName()); - - GregorianCalendar gcal = new GregorianCalendar(); - gcal.setTime(uddiEntity.getCreated()); - o.setCreated(df.newXMLGregorianCalendar(gcal)); - - o.setEntityKey(uddiEntity.getEntityKey()); - - gcal = new GregorianCalendar(); - gcal.setTime(uddiEntity.getModified()); - o.setModified(df.newXMLGregorianCalendar(gcal)); - - gcal = new GregorianCalendar(); - gcal.setTime(uddiEntity.getModifiedIncludingChildren()); - o.setModifiedIncludingChildren(df.newXMLGregorianCalendar(gcal)); - o.setNodeID(uddiEntity.getNodeId()); - op_info.add(o); - - if (uddiEntity instanceof BusinessEntity) { - BusinessEntity be = (BusinessEntity) uddiEntity; - - List<BusinessService> bsList = be.getBusinessServices(); - for (BusinessService bs : bsList) { - bs.setAuthorizedName(publisher.getAuthorizedName()); - OperationalInfo o2 = new OperationalInfo(); - o2.setAuthorizedName(bs.getAuthorizedName()); - - gcal = new GregorianCalendar(); - gcal.setTime(bs.getCreated()); - o2.setCreated(df.newXMLGregorianCalendar(gcal)); - - o2.setEntityKey(bs.getEntityKey()); - - gcal = new GregorianCalendar(); - gcal.setTime(bs.getModified()); - o2.setModified(df.newXMLGregorianCalendar(gcal)); - - gcal = new GregorianCalendar(); - gcal.setTime(bs.getModifiedIncludingChildren()); - o2.setModifiedIncludingChildren(df.newXMLGregorianCalendar(gcal)); - o2.setNodeID(bs.getNodeId()); - op_info.add(o2); - - List<BindingTemplate> btList = bs.getBindingTemplates(); - for (BindingTemplate bt : btList) { - bt.setAuthorizedName(publisher.getAuthorizedName()); - OperationalInfo o3 = new OperationalInfo(); - o3.setAuthorizedName(bt.getAuthorizedName()); - - gcal = new GregorianCalendar(); - gcal.setTime(bt.getCreated()); - o3.setCreated(df.newXMLGregorianCalendar(gcal)); - - o3.setEntityKey(bt.getEntityKey()); - - gcal = new GregorianCalendar(); - gcal.setTime(bt.getModified()); - o3.setModified(df.newXMLGregorianCalendar(gcal)); - - gcal = new GregorianCalendar(); - gcal.setTime(bt.getModifiedIncludingChildren()); - o3.setModifiedIncludingChildren(df.newXMLGregorianCalendar(gcal)); - o3.setNodeID(bt.getNodeId()); - op_info.add(o3); + ValidateCustodyTransfer verifier = new ValidateCustodyTransfer(publisher); + + //if the destination transfer is to a different node, + if (!verifier.validateTransferEntities(em, body)) { + //i don't own these entities, so tell the ower to transfer to me. + + //look up the replication config endpoint for that node and trigger the transfer, then return + //ok this is a node to node transfer, first up a replication client to the destination node + String sourceNode = null; + try { + KeyBag keyBag = body.getKeyBag(); + List<String> keyList = keyBag.getKey(); + for (String key : keyList) { + UddiEntity uddiEntity = em.find(UddiEntity.class, key); + if (sourceNode != null + && !uddiEntity.getNodeId().equals(sourceNode)) { + throw new Exception("All entities to be transfer must be transfered to the same source and destination node"); } + sourceNode = uddiEntity.getNodeId(); } + + UDDIReplicationPortType replicationClient = getReplicationClient(sourceNode); + if (replicationClient == null) { + throw new Exception("Unknown node. is it in the replication graph?" + sourceNode); + } + TransferCustody transferCustody = new TransferCustody(); + transferCustody.setTransferToken(body.getTransferToken()); + transferCustody.setKeyBag(body.getKeyBag()); + transferCustody.setTransferOperationalInfo(new TransferOperationalInfo()); + transferCustody.getTransferOperationalInfo().setAuthorizedName(publisher.getAuthorizedName()); + transferCustody.getTransferOperationalInfo().setNodeID(node); + + replicationClient.transferCustody(transferCustody); + } catch (Exception ex) { + logger.error("Unable to transfer entities to node " + sourceNode + ".", ex); } - } + //and trigger the transfer + } else { - // After transfer is finished, the token can be removed - org.uddi.custody_v3.TransferToken apiTransferToken = body.getTransferToken(); - String transferTokenId = new String(apiTransferToken.getOpaqueToken()); - org.apache.juddi.model.TransferToken modelTransferToken = em.find(org.apache.juddi.model.TransferToken.class, transferTokenId); - em.remove(modelTransferToken); + // Once validated, the ownership transfer is as simple as switching the publisher + KeyBag keyBag = body.getKeyBag(); + List<String> keyList = keyBag.getKey(); + //used for the change journal + + for (String key : keyList) { + UddiEntity uddiEntity = em.find(UddiEntity.class, key); + uddiEntity.setAuthorizedName(publisher.getAuthorizedName()); + Date now = new Date(); + uddiEntity.setModified(now); + uddiEntity.setModifiedIncludingChildren(now); + + if (uddiEntity instanceof BusinessEntity) { + BusinessEntity be = (BusinessEntity) uddiEntity; + + List<BusinessService> bsList = be.getBusinessServices(); + for (BusinessService bs : bsList) { + bs.setAuthorizedName(publisher.getAuthorizedName()); + bs.setModified(now); + bs.setModifiedIncludingChildren(now); + + List<BindingTemplate> btList = bs.getBindingTemplates(); + for (BindingTemplate bt : btList) { + bt.setAuthorizedName(publisher.getAuthorizedName()); + bt.setModified(now); + bt.setModifiedIncludingChildren(now); + + } + } + } + ChangeRecord cr = new ChangeRecord(); + cr.setChangeRecordNewData(new ChangeRecordNewData()); + if (uddiEntity instanceof BusinessEntity) { + cr.getChangeRecordNewData().setBusinessEntity(new org.uddi.api_v3.BusinessEntity()); + MappingModelToApi.mapBusinessEntity((BusinessEntity) uddiEntity, cr.getChangeRecordNewData().getBusinessEntity()); + } + if (uddiEntity instanceof Tmodel) { + cr.getChangeRecordNewData().setTModel(new org.uddi.api_v3.TModel()); + MappingModelToApi.mapTModel((Tmodel) uddiEntity, cr.getChangeRecordNewData().getTModel()); + } + changes.add(cr); + em.persist(uddiEntity); + + } + // After transfer is finished, the token can be removed + org.uddi.custody_v3.TransferToken apiTransferToken = body.getTransferToken(); + String transferTokenId = new String(apiTransferToken.getOpaqueToken()); + org.apache.juddi.model.TransferToken modelTransferToken = em.find(org.apache.juddi.model.TransferToken.class, transferTokenId); + em.remove(modelTransferToken); + } tx.commit(); - //TODO do we need to do something for replication purposes here? - //OperationalInfoWrapper t = new OperationalInfoWrapper(); - //t.data = op_info; - //ReplicationNotifier.Enqueue(UDDIPublicationImpl.); + //we need to do something for replication purposes here + //enqueue notifications and storage of the changed records + for (ChangeRecord c: changes) + try { + c.setChangeID(new ChangeRecordIDType()); + c.getChangeID().setNodeID(node); + c.getChangeID().setOriginatingUSN(null); + ReplicationNotifier.Enqueue(MappingApiToModel.mapChangeRecord(c)); + } catch (UnsupportedEncodingException ex) { + Logger.getLogger(UDDICustodyTransferImpl.class.getName()).log(Level.SEVERE, null, ex); + } long procTime = System.currentTimeMillis() - startTime; serviceCounter.update(CustodyTransferQuery.TRANSFER_ENTITIES, - QueryStatus.SUCCESS, procTime); + QueryStatus.SUCCESS, procTime); } finally { if (tx.isActive()) { @@ -331,8 +359,40 @@ public class UDDICustodyTransferImpl extends AuthenticatedService implements UDD } - public class OperationalInfoWrapper { + private synchronized UDDIReplicationPortType getReplicationClient(String node) { + + UDDIService svc = new UDDIService(); + UDDIReplicationPortType replicationClient = svc.getUDDIReplicationPort(); + + EntityManager em = PersistenceManager.getEntityManager(); + EntityTransaction tx = em.getTransaction(); + try { + StringBuilder sql = new StringBuilder(); + sql.append("select c from ReplicationConfiguration c order by c.serialNumber desc"); + sql.toString(); + Query qry = em.createQuery(sql.toString()); + qry.setMaxResults(1); + + org.apache.juddi.model.ReplicationConfiguration resultList = (org.apache.juddi.model.ReplicationConfiguration) qry.getSingleResult(); + for (Operator o : resultList.getOperator()) { + if (o.getOperatorNodeID().equalsIgnoreCase(node)) { + ((BindingProvider) replicationClient).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, o.getSoapReplicationURL()); + + return replicationClient; + } + } + tx.rollback(); + + } catch (Exception ex) { + logger.fatal("Node not found (or there isn't a replication config)!" + node, ex); + } finally { + if (tx.isActive()) { + tx.rollback(); + } + em.close(); + } + //em.close(); + return null; - public List<OperationalInfo> data; } } http://git-wip-us.apache.org/repos/asf/juddi/blob/70903c27/juddi-core/src/main/java/org/apache/juddi/api/impl/UDDIReplicationImpl.java ---------------------------------------------------------------------- diff --git a/juddi-core/src/main/java/org/apache/juddi/api/impl/UDDIReplicationImpl.java b/juddi-core/src/main/java/org/apache/juddi/api/impl/UDDIReplicationImpl.java index ee48bd5..af3a46b 100644 --- a/juddi-core/src/main/java/org/apache/juddi/api/impl/UDDIReplicationImpl.java +++ b/juddi-core/src/main/java/org/apache/juddi/api/impl/UDDIReplicationImpl.java @@ -54,14 +54,18 @@ import org.apache.juddi.model.Operator; import org.apache.juddi.model.PublisherAssertion; import org.apache.juddi.model.PublisherAssertionId; import org.apache.juddi.model.Tmodel; +import org.apache.juddi.replication.ReplicationNotifier; import static org.apache.juddi.replication.ReplicationNotifier.FetchEdges; import org.apache.juddi.v3.client.UDDIService; import org.apache.juddi.v3.error.ErrorMessage; import org.apache.juddi.v3.error.FatalErrorException; +import org.apache.juddi.v3.error.TransferNotAllowedException; +import org.apache.juddi.validation.ValidateCustodyTransfer; import org.apache.juddi.validation.ValidateReplication; import org.uddi.api_v3.OperationalInfo; import org.uddi.custody_v3.DiscardTransferToken; import org.uddi.repl_v3.ChangeRecord; +import org.uddi.repl_v3.ChangeRecordAcknowledgement; import org.uddi.repl_v3.ChangeRecordIDType; import org.uddi.repl_v3.ChangeRecords; import org.uddi.repl_v3.DoPing; @@ -218,8 +222,9 @@ public class UDDIReplicationImpl extends AuthenticatedService implements UDDIRep @Override public void run() { - if (!queue.isEmpty()) + if (!queue.isEmpty()) { logger.info("Replication change puller thread started. Queue size: " + queue.size()); + } //ok someone told me there's a change available while (!queue.isEmpty()) { NotifyChangeRecordsAvailable poll = queue.poll(); @@ -469,12 +474,105 @@ public class UDDIReplicationImpl extends AuthenticatedService implements UDDIRep } //</editor-fold> + + if (rec.isAcknowledgementRequested()) { + ChangeRecord posack = new ChangeRecord(); + posack.setChangeRecordAcknowledgement(new ChangeRecordAcknowledgement()); + posack.getChangeRecordAcknowledgement().setAcknowledgedChange(rec.getChangeID()); + posack.setAcknowledgementRequested(false); + ReplicationNotifier.Enqueue(MappingApiToModel.mapChangeRecord(posack)); + } if (rec.getChangeRecordNewDataConditional() != null) { - //TODO + + if (rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo().getNodeID() == null) { + throw new Exception("Inbound replication data is missiong node id!"); + } + + //The operationalInfo element MUST contain the operational information associated with the indicated new data. + if (rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo() == null) { + logger.warn("Inbound replication data does not have the required OperationalInfo element and is NOT spec compliant. Data will be ignored"); + } else { + if (rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBindingTemplate() != null) { + //fetch the binding template if it exists already + //if it exists, + // confirm the owning node, it shouldn't be the local node id, if it is, throw + // the owning node should be the same as it was before + + BusinessService model = em.find(org.apache.juddi.model.BusinessService.class, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBindingTemplate().getServiceKey()); + if (model == null) { + logger.error("Replication error, attempting to insert a binding where the service doesn't exist yet"); + } else { + ValidateNodeIdMatches(model.getNodeId(), rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + + org.apache.juddi.model.BindingTemplate bt = em.find(org.apache.juddi.model.BindingTemplate.class, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBindingTemplate().getBindingKey()); + if (bt != null) { + em.remove(bt); + } + bt = new BindingTemplate(); + MappingApiToModel.mapBindingTemplate(rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBindingTemplate(), bt, model); + MappingApiToModel.mapOperationalInfo(bt, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + // MappingApiToModel.mapOperationalInfoIncludingChildren(model, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + em.persist(bt); + } + + } else if (rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBusinessEntity() != null) { + + BusinessEntity model = em.find(org.apache.juddi.model.BusinessEntity.class, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBusinessEntity().getBusinessKey()); + if (model != null) { + ValidateNodeIdMatches(model.getNodeId(), rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + //TODO revisit access control rules + em.remove(model); + } + model = new BusinessEntity(); + MappingApiToModel.mapBusinessEntity(rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBusinessEntity(), model); + // MappingApiToModel.mapOperationalInfo(model, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + + MappingApiToModel.mapOperationalInfoIncludingChildren(model, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + logger.warn("Name size on save is " + model.getBusinessNames().size()); + em.persist(model); + + } + if (rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBusinessService() != null) { + BusinessEntity find = em.find(org.apache.juddi.model.BusinessEntity.class, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBusinessService().getBusinessKey()); + if (find == null) { + logger.error("Replication error, attempting to insert a service where the business doesn't exist yet"); + } else { + + org.apache.juddi.model.BusinessService model = null; + model = em.find(org.apache.juddi.model.BusinessService.class, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBusinessService().getServiceKey()); + if (model != null) { + ValidateNodeIdMatches(model.getNodeId(), rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + em.remove(model); + } + + model = new org.apache.juddi.model.BusinessService(); + MappingApiToModel.mapBusinessService(rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getBusinessService(), model, find); + MappingApiToModel.mapOperationalInfo(model, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + MappingApiToModel.mapOperationalInfoIncludingChildren(model, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + + em.persist(model); + } + + } else if (rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getTModel() != null) { + + Tmodel model = em.find(org.apache.juddi.model.Tmodel.class, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getTModel().getTModelKey()); + if (model != null) { + ValidateNodeIdMatches(model.getNodeId(), rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + em.remove(model); + } + model = new Tmodel(); + MappingApiToModel.mapTModel(rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getTModel(), model); + + MappingApiToModel.mapOperationalInfo(model, rec.getChangeRecordNewDataConditional().getChangeRecordNewData().getOperationalInfo()); + + em.persist(model); + } + + } } if (rec.getChangeRecordNull() != null) { - //TODO + //No action required } if (rec.getChangeRecordCorrection() != null) { @@ -832,23 +930,30 @@ public class UDDIReplicationImpl extends AuthenticatedService implements UDDIRep public void notifyChangeRecordsAvailable(NotifyChangeRecordsAvailable body) throws DispositionReportFaultMessage { long startTime = System.currentTimeMillis(); - long procTime = System.currentTimeMillis() - startTime; - serviceCounter.update(ReplicationQuery.NOTIFY_CHANGERECORDSAVAILABLE, - QueryStatus.SUCCESS, procTime); + //some other node just told us there's new records available, call //getChangeRecords from the remote node asynch - new ValidateReplication(null).validateNotifyChangeRecordsAvailable(body, ctx); queue.add(body); logger.info(body.getNotifyingNode() + " just told me that there are change records available, enqueuing...size is " + queue.size()); //ValidateReplication.unsupportedAPICall(); + long procTime = System.currentTimeMillis() - startTime; + serviceCounter.update(ReplicationQuery.NOTIFY_CHANGERECORDSAVAILABLE, + QueryStatus.SUCCESS, procTime); } private static Queue<NotifyChangeRecordsAvailable> queue = null; /** * transfers custody of an entity from node1/user1 to node2/user2 - * + * + * assume this node is node 2. + * + * user1 on node1 requests a transfer token. node 1 issues the token. + * + * user1 now has a transfer token for their stuff + * user now takes the token to node 2 and calls transferEntities + *<img src="http://www.uddi.org/pubs/uddi-v3.0.2-20041019_files/image086.gif"> * @param body * @throws DispositionReportFaultMessage */ @@ -858,12 +963,35 @@ public class UDDIReplicationImpl extends AuthenticatedService implements UDDIRep long startTime = System.currentTimeMillis(); //*this node is transfering data to another node - //body.getTransferOperationalInfo(). - ValidateReplication.unsupportedAPICall(); + //ValidateReplication.unsupportedAPICall(); + //a remote node just told me to give up control of some of my entities EntityManager em = PersistenceManager.getEntityManager(); //EntityTransaction tx = em.getTransaction(); - + //confirm i have a replication config + boolean ok =false; + ReplicationConfiguration FetchEdges = ReplicationNotifier.FetchEdges(); + for (int i=0; i<FetchEdges.getOperator().size(); i++){ + //confirm that the destination node is in the replication config + if (FetchEdges.getOperator().get(i).getOperatorNodeID().equals(body.getTransferOperationalInfo().getNodeID())) + { + ok = true; + break; + } + } + if (!ok){ + throw new TransferNotAllowedException(new ErrorMessage("E_transferNotAllowedUnknownNode")); + } + + + + new ValidateReplication(null).validateTransfer(em,body); + + + //make the change + //enqueue in replication notifier + //discard the token + /** * The custodial node must verify that it has granted permission * to transfer the entities identified and that this permission @@ -903,6 +1031,9 @@ public class UDDIReplicationImpl extends AuthenticatedService implements UDDIRep dtt.setKeyBag(body.getKeyBag()); dtt.setTransferToken(body.getTransferToken()); new UDDICustodyTransferImpl().discardTransferToken(dtt); + long procTime = System.currentTimeMillis() - startTime; + serviceCounter.update(ReplicationQuery.TRANSFER_CUSTODY, + QueryStatus.SUCCESS, procTime); } } http://git-wip-us.apache.org/repos/asf/juddi/blob/70903c27/juddi-core/src/main/java/org/apache/juddi/model/UddiEntityPublisher.java ---------------------------------------------------------------------- diff --git a/juddi-core/src/main/java/org/apache/juddi/model/UddiEntityPublisher.java b/juddi-core/src/main/java/org/apache/juddi/model/UddiEntityPublisher.java index 255ed5f..20c9aed 100644 --- a/juddi-core/src/main/java/org/apache/juddi/model/UddiEntityPublisher.java +++ b/juddi-core/src/main/java/org/apache/juddi/model/UddiEntityPublisher.java @@ -97,20 +97,19 @@ public class UddiEntityPublisher { * @return true/false */ public boolean isOwner(UddiEntity entity){ - boolean ret = false; try { AppConfig instance = AppConfig.getInstance(); if (entity != null) { if (entity.getAuthorizedName().equals(getAuthorizedName()) && entity.getNodeId().equals((AppConfig.getConfiguration().getString(Property.JUDDI_NODE_ID)))) { - ret = true; + return true; } } } catch (Exception ex) { logger.log(Level.WARNING, "Error caught determining node id! Defaulting to access denied", ex); } - return ret; + return false; } http://git-wip-us.apache.org/repos/asf/juddi/blob/70903c27/juddi-core/src/main/java/org/apache/juddi/replication/ReplicationNotifier.java ---------------------------------------------------------------------- diff --git a/juddi-core/src/main/java/org/apache/juddi/replication/ReplicationNotifier.java b/juddi-core/src/main/java/org/apache/juddi/replication/ReplicationNotifier.java index b724ae5..9af0093 100644 --- a/juddi-core/src/main/java/org/apache/juddi/replication/ReplicationNotifier.java +++ b/juddi-core/src/main/java/org/apache/juddi/replication/ReplicationNotifier.java @@ -17,7 +17,6 @@ package org.apache.juddi.replication; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Queue; import java.util.Timer; @@ -40,7 +39,6 @@ import org.apache.juddi.model.ChangeRecord; import org.apache.juddi.model.ReplicationConfiguration; import org.apache.juddi.v3.client.UDDIService; import org.uddi.repl_v3.ChangeRecordIDType; -import org.uddi.repl_v3.CommunicationGraph; import org.uddi.repl_v3.HighWaterMarkVectorType; import org.uddi.repl_v3.NotifyChangeRecordsAvailable; import org.uddi.repl_v3.Operator; http://git-wip-us.apache.org/repos/asf/juddi/blob/70903c27/juddi-core/src/main/java/org/apache/juddi/validation/ValidateCustodyTransfer.java ---------------------------------------------------------------------- diff --git a/juddi-core/src/main/java/org/apache/juddi/validation/ValidateCustodyTransfer.java b/juddi-core/src/main/java/org/apache/juddi/validation/ValidateCustodyTransfer.java index 4b399ff..14b6d56 100644 --- a/juddi-core/src/main/java/org/apache/juddi/validation/ValidateCustodyTransfer.java +++ b/juddi-core/src/main/java/org/apache/juddi/validation/ValidateCustodyTransfer.java @@ -123,9 +123,9 @@ public class ValidateCustodyTransfer extends ValidateUDDIApi { throw new UserMismatchException(new ErrorMessage("errors.usermismatch.InvalidOwner", key)); // Creating parameters for key-checking query - DynamicQuery.Parameter param = new DynamicQuery.Parameter("UPPER(ttk.entityKey)", - key.toUpperCase(), - DynamicQuery.PREDICATE_EQUALS); + DynamicQuery.Parameter param = new DynamicQuery.Parameter("UPPER(ttk.entityKey)", + key.toUpperCase(), + DynamicQuery.PREDICATE_EQUALS); params.add(param); } @@ -142,8 +142,16 @@ public class ValidateCustodyTransfer extends ValidateUDDIApi { } - public void validateTransferEntities(EntityManager em, TransferEntities body) throws DispositionReportFaultMessage { - + /** + * returns true if all items to be transfered are within this node (no node to node transfers) + * @param em + * @param body + * @return + * @throws DispositionReportFaultMessage + */ + public boolean validateTransferEntities(EntityManager em, TransferEntities body) throws DispositionReportFaultMessage { + + boolean ret = true; // No null input if (body == null) throw new FatalErrorException(new ErrorMessage("errors.NullInput")); @@ -193,10 +201,11 @@ public class ValidateCustodyTransfer extends ValidateUDDIApi { UddiEntity uddiEntity = em.find(UddiEntity.class, key); if (uddiEntity == null) throw new InvalidKeyPassedException(new ErrorMessage("errors.invalidkey.EntityNotFound", key)); - + if (!uddiEntity.getNodeId().equalsIgnoreCase(nodeID)) + ret = false; count++; } + return ret; } - } http://git-wip-us.apache.org/repos/asf/juddi/blob/70903c27/juddi-core/src/main/java/org/apache/juddi/validation/ValidateReplication.java ---------------------------------------------------------------------- diff --git a/juddi-core/src/main/java/org/apache/juddi/validation/ValidateReplication.java b/juddi-core/src/main/java/org/apache/juddi/validation/ValidateReplication.java index df5a436..717b691 100644 --- a/juddi-core/src/main/java/org/apache/juddi/validation/ValidateReplication.java +++ b/juddi-core/src/main/java/org/apache/juddi/validation/ValidateReplication.java @@ -26,11 +26,13 @@ import org.apache.juddi.v3.error.ErrorMessage; import org.apache.juddi.v3.error.FatalErrorException; import org.apache.juddi.v3.error.InvalidValueException; import org.apache.juddi.v3.error.ValueNotAllowedException; +import org.uddi.custody_v3.TransferEntities; import org.uddi.repl_v3.CommunicationGraph.Edge; import org.uddi.repl_v3.HighWaterMarkVectorType; import org.uddi.repl_v3.NotifyChangeRecordsAvailable; import org.uddi.repl_v3.Operator; import org.uddi.repl_v3.ReplicationConfiguration; +import org.uddi.repl_v3.TransferCustody; import org.uddi.v3_service.DispositionReportFaultMessage; /** @@ -177,4 +179,32 @@ public class ValidateReplication extends ValidateUDDIApi { return false; } + public void validateTransfer(EntityManager em, TransferCustody body) throws DispositionReportFaultMessage { + + if (body == null) + throw new FatalErrorException(new ErrorMessage("errors.NullInput")); + if (body.getTransferToken()==null) + throw new FatalErrorException(new ErrorMessage("errors.NullInput")); + if (body.getKeyBag()==null) + throw new FatalErrorException(new ErrorMessage("errors.NullInput")); + if (body.getTransferOperationalInfo()==null) + throw new FatalErrorException(new ErrorMessage("errors.NullInput")); + + if (body.getTransferOperationalInfo().getNodeID()==null) + throw new FatalErrorException(new ErrorMessage("errors.NullInput")); + if (body.getTransferOperationalInfo().getAuthorizedName()==null) + throw new FatalErrorException(new ErrorMessage("errors.NullInput")); + + + //confirm i own the records in question + //confirm i issued the transfer token + + TransferEntities x = new TransferEntities(); + x.setKeyBag(body.getKeyBag()); + x.setTransferToken(body.getTransferToken()); + new ValidateCustodyTransfer(null).validateTransferEntities(em, x); + + + } + } http://git-wip-us.apache.org/repos/asf/juddi/blob/70903c27/juddi-core/src/main/resources/messages.properties ---------------------------------------------------------------------- diff --git a/juddi-core/src/main/resources/messages.properties b/juddi-core/src/main/resources/messages.properties index 3428580..bf11ed7 100644 --- a/juddi-core/src/main/resources/messages.properties +++ b/juddi-core/src/main/resources/messages.properties @@ -52,6 +52,7 @@ E_tokenAlreadyExists=Key already exists in transfer request E_tooManyOptions=Too many options E_transferAborted=Transfer Aborted E_transferNotAllowed=The transfer request is not allowed +E_transferNotAllowedUnknownNode=The transfer request is not allowed because the destination node is not in the replication config. E_unknownUser=The user ID and password pair passed in a get_authToken API is not known to the UDDI node or is not valid. E_unrecognizedVersion=The value of the namespace attribute is unsupported by the node being queried. E_unsupported=Unsupported feature or API. http://git-wip-us.apache.org/repos/asf/juddi/blob/70903c27/juddi-core/src/test/java/org/apache/juddi/api/impl/API_170_CustodyTransferTest.java ---------------------------------------------------------------------- diff --git a/juddi-core/src/test/java/org/apache/juddi/api/impl/API_170_CustodyTransferTest.java b/juddi-core/src/test/java/org/apache/juddi/api/impl/API_170_CustodyTransferTest.java new file mode 100644 index 0000000..75dbdb2 --- /dev/null +++ b/juddi-core/src/test/java/org/apache/juddi/api/impl/API_170_CustodyTransferTest.java @@ -0,0 +1,129 @@ +/* + * Copyright 2014 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.juddi.api.impl; + +import java.rmi.RemoteException; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.ws.Holder; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.juddi.Registry; +import org.apache.juddi.v3.tck.TckBusiness; +import org.apache.juddi.v3.tck.TckFindEntity; +import org.apache.juddi.v3.tck.TckPublisher; +import org.apache.juddi.v3.tck.TckSecurity; +import org.apache.juddi.v3.tck.TckTModel; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.uddi.api_v3.BusinessDetail; +import org.uddi.api_v3.GetBusinessDetail; +import org.uddi.api_v3.GetOperationalInfo; +import org.uddi.api_v3.OperationalInfos; +import org.uddi.custody_v3.KeyBag; +import org.uddi.custody_v3.TransferEntities; +import org.uddi.custody_v3.TransferToken; +import org.uddi.v3_service.UDDISecurityPortType; + +/** + * + * @author alex + */ +public class API_170_CustodyTransferTest { + + private static Log logger = LogFactory.getLog(API_030_BusinessEntityTest.class); + private static API_010_PublisherTest api010 = new API_010_PublisherTest(); + private static TckTModel tckTModel = new TckTModel(new UDDIPublicationImpl(), new UDDIInquiryImpl()); + private static TckBusiness tckBusiness = new TckBusiness(new UDDIPublicationImpl(), new UDDIInquiryImpl()); + private static TckFindEntity tckFindEntity = new TckFindEntity(new UDDIInquiryImpl()); + private static String authInfoMary = null; + private static String authInfoSam = null; + + @BeforeClass + public static void setup() throws ConfigurationException { + Registry.start(); + logger.info("API_030_BusinessEntityTest"); + logger.debug("Getting auth token.."); + try { + api010.saveJoePublisher(); + api010.saveSamSyndicator(); + UDDISecurityPortType security = new UDDISecurityImpl(); + authInfoMary = TckSecurity.getAuthToken(security, TckPublisher.getMaryPublisherId(), TckPublisher.getMaryPassword()); + authInfoSam = TckSecurity.getAuthToken(security, TckPublisher.getSamPublisherId(), TckPublisher.getSamPassword()); + String authInfoUDDI = TckSecurity.getAuthToken(security, TckPublisher.getUDDIPublisherId(), TckPublisher.getUDDIPassword()); + tckTModel.saveUDDIPublisherTmodel(authInfoUDDI); + tckTModel.saveTModels(authInfoUDDI, TckTModel.TMODELS_XML); + tckTModel.saveMaryPublisherTmodel(authInfoMary); + tckTModel.saveSamSyndicatorTmodel(authInfoSam); + } catch (RemoteException e) { + logger.error(e.getMessage(), e); + Assert.fail("Could not obtain authInfo token."); + } + } + + @AfterClass + public static void stopRegistry() throws ConfigurationException { + tckTModel.deleteCreatedTModels(authInfoMary); + tckTModel.deleteCreatedTModels(authInfoSam); + Registry.stop(); + } + + + @Test + public void testTransfer() throws Exception{ + UDDIInquiryImpl inquire = new UDDIInquiryImpl(); + + + //save sam's business + tckBusiness.saveSamSyndicatorBusiness(authInfoSam); + + //save mary's business + tckBusiness.saveMaryPublisherBusiness(authInfoMary); + + GetOperationalInfo goi = new GetOperationalInfo(); + goi.getEntityKey().add(TckBusiness.SAM_BUSINESS_KEY); + + OperationalInfos operationalInfo = inquire.getOperationalInfo(goi); + Assert.assertEquals(operationalInfo.getOperationalInfo().get(0).getAuthorizedName(), TckPublisher.getSamPublisherId()); + + //sam wants to transfer to mary, get a token + UDDICustodyTransferImpl custody = new UDDICustodyTransferImpl(); + KeyBag kb = new KeyBag(); + kb.getKey().add(TckBusiness.SAM_BUSINESS_KEY); + Holder<String> node = new Holder<String>(); + Holder<XMLGregorianCalendar> expires = new Holder<XMLGregorianCalendar>(); + Holder<byte[]> token = new Holder<byte[]>(); + custody.getTransferToken(authInfoSam,kb , node, expires, token); + + //use mary's account to accept and transfer + TransferEntities te = new TransferEntities(); + te.setAuthInfo(authInfoMary); + te.setKeyBag(kb); + te.setTransferToken(new TransferToken()); + te.getTransferToken().setExpirationTime(expires.value); + te.getTransferToken().setNodeID(node.value); + te.getTransferToken().setOpaqueToken(token.value); + custody.transferEntities(te); + + + + operationalInfo = inquire.getOperationalInfo(goi); + + Assert.assertEquals(operationalInfo.getOperationalInfo().get(0).getAuthorizedName(), TckPublisher.getMaryPublisherId()); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
