Java tutorial
/* * Copyright 2001-2008 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.validation; import java.math.BigInteger; import java.security.cert.CertificateException; import java.util.List; import java.util.Properties; import java.util.concurrent.atomic.AtomicReference; import javax.persistence.EntityManager; import javax.xml.ws.WebServiceContext; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.juddi.config.AppConfig; import org.apache.juddi.config.Property; import org.apache.juddi.model.Node; import org.apache.juddi.model.UddiEntityPublisher; import org.apache.juddi.v3.client.cryptor.CryptorFactory; import org.apache.juddi.v3.client.cryptor.DigSigUtil; 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.TransferNotAllowedException; 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; /** * @author <a href="mailto:alexoree@apache.org">Alex O'Ree</a> * Processing an inbound replication message may fail due to a server internal * error. The common behavior for all error cases is to return an E_fatalError * error code. Error reporting SHALL be that specified by Section 4.8 Success * and Error Reporting of this specification. */ public class ValidateReplication extends ValidateUDDIApi { private final static Log log = LogFactory.getLog(ValidateReplication.class); public ValidateReplication(UddiEntityPublisher publisher) { super(publisher); } public ValidateReplication(UddiEntityPublisher publisher, String nodeid) { super(publisher, nodeid); } public void validateNotifyChangeRecordsAvailable(NotifyChangeRecordsAvailable body, WebServiceContext ctx) throws DispositionReportFaultMessage { //TODO } public void validateGetChangeRecords(String requestingNode, HighWaterMarkVectorType changesAlreadySeen, BigInteger responseLimitCount, HighWaterMarkVectorType responseLimitVector, ReplicationConfiguration FetchEdges, WebServiceContext ctx) throws DispositionReportFaultMessage { //TODO if (requestingNode == null || requestingNode.trim().equalsIgnoreCase("")) { //requestingNode: The requestingNode element provides the identity of the calling node. //This is the unique key for the calling node and SHOULD be specified within the Replication Configuration Structure. throw new FatalErrorException(new ErrorMessage("errors.replication.nodeNotSpecified")); } //if (!ContainsNode(requestingNode, FetchEdges)) { // throw new FatalErrorException(new ErrorMessage("errors.replication.unknownNode")); //} if (changesAlreadySeen != null) { // changesAlreadySeen: The changesAlreadySeen element, if present, indicates changes from each //node that the requestor has successfully processed, and thus which should not be resent, if possible. //no validation needed? } if (responseLimitCount != null && responseLimitVector != null) { throw new FatalErrorException(new ErrorMessage("errors.replication.bothLimitsSpecified")); } if (responseLimitCount != null) { //can't be 0 since 0 is banned as being a change record id if (responseLimitCount.longValue() <= 0) { throw new FatalErrorException( new ErrorMessage("errors.replication.negativeLimit", responseLimitCount.toString())); } } if (responseLimitVector != null) { for (int i = 0; i < responseLimitVector.getHighWaterMark().size(); i++) { if (responseLimitVector.getHighWaterMark().get(i).getOriginatingUSN() == null || responseLimitVector.getHighWaterMark().get(i).getOriginatingUSN() <= 0) { throw new FatalErrorException(new ErrorMessage("errors.replication.limitVectorNull")); } if (responseLimitVector.getHighWaterMark().get(i).getNodeID() == null || responseLimitVector.getHighWaterMark().get(i).getNodeID().trim().equalsIgnoreCase("")) { throw new FatalErrorException(new ErrorMessage("errors.replication.limitVectorNoNode")); } } } /** * responseLimitCount or responseLimitVector: A caller MAY place * an upper bound on the number of change records he wishes to * receive in response to this message by either providing a * integer responseLimitCount, or, using responseLimitVector, * indicating for each node in the graph the first change * originating there that he does not wish to be returned. * */ } private static boolean ContainsNode(String requestingNode, ReplicationConfiguration FetchEdges) { if (FetchEdges == null) { return false; } if (FetchEdges.getCommunicationGraph() == null) { return false; } for (int i = 0; i < FetchEdges.getCommunicationGraph().getNode().size(); i++) { if (FetchEdges.getCommunicationGraph().getNode().get(i).equalsIgnoreCase(requestingNode)) { return true; } } return false; } public void validateSetReplicationNodes(ReplicationConfiguration replicationConfiguration, EntityManager em, String thisnode, Configuration config) throws DispositionReportFaultMessage, ConfigurationException { if (replicationConfiguration == null) { throw new InvalidValueException(new ErrorMessage("errors.replication.configNull")); } if (replicationConfiguration.getCommunicationGraph() == null) { throw new InvalidValueException(new ErrorMessage("errors.replication.configNull")); } if (replicationConfiguration.getRegistryContact() == null) { throw new InvalidValueException(new ErrorMessage("errors.replication.contactNull")); } if (replicationConfiguration.getRegistryContact().getContact() == null) { throw new InvalidValueException(new ErrorMessage("errors.replication.contactNull")); } if (replicationConfiguration.getRegistryContact().getContact().getPersonName().get(0) == null) { throw new InvalidValueException(new ErrorMessage("errors.replication.contactNull")); } if (replicationConfiguration.getOperator() == null || replicationConfiguration.getOperator().isEmpty()) { throw new InvalidValueException( new ErrorMessage("errors.replication.contactNull", "Operator is null or empty")); } for (int i = 0; i < replicationConfiguration.getOperator().size(); i++) { if (replicationConfiguration.getOperator().get(i).getSoapReplicationURL() == null || "".equals(replicationConfiguration.getOperator().get(i).getSoapReplicationURL())) { throw new InvalidValueException( new ErrorMessage("errors.replication.contactNull", "Replication URL is null or empty")); } if (!replicationConfiguration.getOperator().get(i).getSoapReplicationURL().toLowerCase() .startsWith("http")) { throw new InvalidValueException(new ErrorMessage("errors.replication.contactNull", "Replication URL is invalid, only HTTP is supported")); } if (replicationConfiguration.getOperator().get(i).getOperatorNodeID() == null || replicationConfiguration.getOperator().get(i).getOperatorNodeID().equalsIgnoreCase("")) { throw new InvalidValueException( new ErrorMessage("errors.replication.contactNull", "Node ID is not defined")); } } if (replicationConfiguration.getCommunicationGraph() != null) { for (String s : replicationConfiguration.getCommunicationGraph().getNode()) { if (!Contains(replicationConfiguration.getOperator(), s)) { throw new InvalidValueException(new ErrorMessage("errors.replication.configNodeNotFound")); } } for (Edge s : replicationConfiguration.getCommunicationGraph().getEdge()) { //TODO revisit this for correctness //Node find = null; //if (!thisnode.equalsIgnoreCase(s.getMessageReceiver())) { if (!Contains(replicationConfiguration.getOperator(), s.getMessageReceiver())) { throw new InvalidValueException(new ErrorMessage("errors.replication.configNodeNotFound")); //} } //find = null; //if (!thisnode.equalsIgnoreCase(s.getMessageSender())) { if (!Contains(replicationConfiguration.getOperator(), s.getMessageSender())) { throw new InvalidValueException(new ErrorMessage("errors.replication.configNodeNotFound")); //} } if (s.getMessageReceiver().equalsIgnoreCase(s.getMessageSender())) { throw new InvalidValueException(new ErrorMessage("errors.replication.configNodeLoop")); } for (String id : s.getMessageReceiverAlternate()) { if (!Contains(replicationConfiguration.getOperator(), id)) { throw new InvalidValueException(new ErrorMessage("errors.replication.configNodeNotFound")); } } } } boolean shouldcheck = config.getBoolean(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_ENABLE, false); initDigSig(config); if (shouldcheck && !replicationConfiguration.getSignature().isEmpty() && ds != null) { AtomicReference<String> outmsg = new AtomicReference<String>(); boolean ok = ds.verifySignedUddiEntity(replicationConfiguration, outmsg); if (!ok) { throw new FatalErrorException( new ErrorMessage("errors.digitalsignature.validationfailure" + " " + outmsg.get())); } } } private org.apache.juddi.v3.client.cryptor.DigSigUtil ds = null; private synchronized void initDigSig(Configuration config) { if (ds == null) { Properties p = new Properties(); /** * <trustStorePath>truststore.jks</trustStorePath> * <trustStoreType>JKS</trustStoreType> * <trustStorePassword * isPasswordEncrypted="false" * cryptoProvider="org.apache.juddi.v3.client.crypto.AES128Cryptor">password</trustStorePassword> * * <checkTimestamps>true</checkTimestamps> * <checkTrust>true</checkTrust> * <checkRevocationCRL>true</checkRevocationCRL> */ p.put(DigSigUtil.TRUSTSTORE_FILE, config .getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "trustStorePath", "")); p.put(DigSigUtil.TRUSTSTORE_FILETYPE, config .getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "trustStoreType", "")); String enc = config .getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "trustStorePassword", ""); if (config.getBoolean(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "trustStorePassword[@isPasswordEncrypted]", false)) { log.debug("trust password is encrypted, decrypting..."); String prov = config.getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "trustStorePassword[@cryptoProvider]", ""); try { p.setProperty(DigSigUtil.TRUSTSTORE_FILE_PASSWORD, CryptorFactory.getCryptor(prov).decrypt(enc)); } catch (Exception ex) { log.warn("unable to decrypt trust store password " + ex.getMessage()); log.debug("unable to decrypt trust store password " + ex.getMessage(), ex); } } else if (!"".equals(enc)) { log.warn("Hey, you should consider encrypting your trust store password!"); p.setProperty(DigSigUtil.TRUSTSTORE_FILE_PASSWORD, enc); } p.put(DigSigUtil.CHECK_REVOCATION_STATUS_CRL, config.getString( Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "checkRevocationCRL", "true")); p.put(DigSigUtil.CHECK_TRUST_CHAIN, config .getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "checkTrust", "true")); p.put(DigSigUtil.CHECK_TIMESTAMPS, config .getString(Property.JUDDI_REJECT_ENTITIES_WITH_INVALID_SIG_PREFIX + "checkTimestamps", "true")); try { ds = new DigSigUtil(p); } catch (CertificateException ex) { log.error("", ex); } //System.out.println("loaded from " + AppConfig.getConfigFileURL()); //p.list(System.out); } } private boolean Contains(List<Operator> operator, String s) { if (operator == null) { return false; } for (Operator o : operator) { if (o.getOperatorNodeID().equalsIgnoreCase(s)) { return true; } } return false; } public void validateTransfer(EntityManager em, TransferCustody body) throws DispositionReportFaultMessage { if (body == null) { throw new TransferNotAllowedException(new ErrorMessage("errors.NullInput")); } if (body.getTransferToken() == null) { throw new TransferNotAllowedException(new ErrorMessage("errors.NullInput")); } if (body.getKeyBag() == null) { throw new TransferNotAllowedException(new ErrorMessage("errors.NullInput")); } if (body.getTransferOperationalInfo() == null) { throw new TransferNotAllowedException(new ErrorMessage("errors.NullInput")); } if (body.getTransferOperationalInfo().getNodeID() == null) { throw new TransferNotAllowedException(new ErrorMessage("errors.NullInput")); } if (body.getTransferOperationalInfo().getAuthorizedName() == null) { throw new TransferNotAllowedException(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()); String transferTokenId = new String(body.getTransferToken().getOpaqueToken()); new ValidateCustodyTransfer(null).validateTransferLocalEntities(em, transferTokenId, body.getKeyBag().getKey()); } }