You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
653 lines
18 KiB
653 lines
18 KiB
using System;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using System.Data;
|
|
using System.Data.SqlClient;
|
|
using System.Xml;
|
|
using System.Xml.Serialization;
|
|
using System.Windows.Forms;
|
|
using System.Security.Principal;
|
|
|
|
using Microsoft.Win32;
|
|
|
|
using UDDI;
|
|
using UDDI.API;
|
|
using UDDI.API.Business;
|
|
using UDDI.Replication;
|
|
|
|
namespace UDDI.Tools
|
|
{
|
|
class FixDefaultURL
|
|
{
|
|
//
|
|
// Enumerated Types
|
|
//
|
|
enum LogType
|
|
{
|
|
ConsoleAndLog,
|
|
ConsoleOnly,
|
|
LogOnly
|
|
}
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
const string LogFileName = "fixdefaulturl.log.txt";
|
|
const string ExceptionFileName = "fixdefaulturl.exceptions.txt";
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
static StreamWriter logFile;
|
|
static StreamWriter exceptionsFile;
|
|
|
|
static void FixDefaultURLs()
|
|
{
|
|
//
|
|
// Get a list of business keys that have non-default discovery URLs.
|
|
//
|
|
ArrayList businessEntities = GetBusinessEntities();
|
|
int total = businessEntities.Count;
|
|
int current = 1;
|
|
int numberFixed = 0;
|
|
|
|
foreach( BusinessEntity businessEntity in businessEntities )
|
|
{
|
|
//
|
|
// Get values for this business.
|
|
//
|
|
businessEntity.Get();
|
|
|
|
//
|
|
// BusinessEntity.Get() may add the default one, we don't want it.
|
|
//
|
|
DiscoveryUrlCollection originalList = new DiscoveryUrlCollection();
|
|
originalList.Get( businessEntity.BusinessKey );
|
|
businessEntity.DiscoveryUrls = originalList;
|
|
|
|
Log( "*** Processing " + current++ + "/" + total + " *** " );
|
|
|
|
LogStartBusinessEntity( businessEntity );
|
|
|
|
DiscoveryUrlCollection filteredList = GetFilterList( businessEntity );
|
|
|
|
if( filteredList.Count < businessEntity.DiscoveryUrls.Count )
|
|
{
|
|
try
|
|
{
|
|
numberFixed++;
|
|
|
|
LogFixStart( filteredList );
|
|
|
|
ConnectionManager.BeginTransaction();
|
|
|
|
//
|
|
// Remove duplicate discovery URLs
|
|
//
|
|
businessEntity.DiscoveryUrls = filteredList;
|
|
|
|
//
|
|
// Fix change records
|
|
//
|
|
FixChangeRecords( businessEntity );
|
|
|
|
//
|
|
// Fix data. Saving the BusinessEntity will also create a ChangeRecordNew data in our replication stream.
|
|
// Other operators will consume this change record, which will update their databases.
|
|
//
|
|
|
|
FixData( businessEntity );
|
|
#if never
|
|
ChangeRecordNewData changeRecordNewData = new ChangeRecordNewData( businessEntity );
|
|
ChangeRecord fixData = new ChangeRecord( changeRecordNewData );
|
|
fixData.Process();
|
|
#endif
|
|
ConnectionManager.Commit();
|
|
|
|
LogFixEnd( businessEntity );
|
|
}
|
|
catch( Exception e)
|
|
{
|
|
WriteException( e );
|
|
ConnectionManager.Abort();
|
|
}
|
|
}
|
|
LogDoneBusinessEntity( businessEntity );
|
|
}
|
|
Log( "BusinessEntities fixed: " + numberFixed );
|
|
}
|
|
|
|
static void FixData( BusinessEntity businessEntity )
|
|
{
|
|
Log( "\t\tSTART Fixing Data" );
|
|
|
|
//
|
|
// Save the current user ID
|
|
//
|
|
string currentUserID = Context.User.ID;
|
|
|
|
try
|
|
{
|
|
//
|
|
// Set the current user to this user to the PUID for this business entity.
|
|
//
|
|
Context.User.ID = GetPUIDForBusinessEntity( businessEntity.BusinessKey );
|
|
|
|
//
|
|
// Save our business
|
|
//
|
|
businessEntity.Save();
|
|
|
|
Log( "\t\tDONE Fixing Data" );
|
|
}
|
|
finally
|
|
{
|
|
//
|
|
// Restore the ID
|
|
//
|
|
Context.User.ID = currentUserID;
|
|
}
|
|
}
|
|
|
|
static string GetPUIDForBusinessEntity( string businessKey )
|
|
{
|
|
SqlStoredProcedureAccessor puidSP = new SqlStoredProcedureAccessor();
|
|
puidSP.ProcedureName = "net_getPUIDForBusinessEntity";
|
|
|
|
puidSP.Parameters.Add( "@businessKey", SqlDbType.UniqueIdentifier );
|
|
puidSP.Parameters.SetGuidFromString( "@businessKey", businessKey );
|
|
|
|
SqlDataReaderAccessor reader = puidSP.ExecuteReader();
|
|
string puid = "";
|
|
|
|
try
|
|
{
|
|
reader.Read();
|
|
puid = reader.GetString( 0 );
|
|
}
|
|
finally
|
|
{
|
|
reader.Close();
|
|
}
|
|
|
|
return puid;
|
|
}
|
|
|
|
static void FixChangeRecords( BusinessEntity businessEntity )
|
|
{
|
|
//
|
|
// Get all related change records
|
|
//
|
|
ArrayList newDataChangeRecords = GetChangeRecordsForEntity( businessEntity );
|
|
|
|
//
|
|
// Create and process a correction for each change record.
|
|
//
|
|
Log( "\t\tSTART Processing Corrections" );
|
|
foreach( ChangeRecord changeRecord in newDataChangeRecords )
|
|
{
|
|
ChangeRecord changeRecordCorrection = CreateCorrection( changeRecord, businessEntity );
|
|
changeRecordCorrection.Process();
|
|
|
|
LogChangeRecordCorrection( changeRecord, changeRecordCorrection );
|
|
}
|
|
Log( "\t\tDONE Processing Corrections" );
|
|
}
|
|
|
|
static ChangeRecord CreateCorrection( ChangeRecord originalChangeRecord, BusinessEntity businessEntity )
|
|
{
|
|
ChangeRecordNewData changeRecordNewData = originalChangeRecord.Payload as ChangeRecordNewData;
|
|
changeRecordNewData.Entity = businessEntity;
|
|
|
|
ChangeRecordCorrection changeRecordCorrection = new ChangeRecordCorrection();
|
|
changeRecordCorrection.ChangeRecord = originalChangeRecord;
|
|
|
|
return new ChangeRecord( changeRecordCorrection );
|
|
}
|
|
|
|
static ArrayList GetChangeRecordsForEntity( BusinessEntity businessEntity )
|
|
{
|
|
string contextID = Guid.NewGuid().ToString();
|
|
string operatorKey = Config.GetString( "OperatorKey" );
|
|
ArrayList changeRecords = new ArrayList();
|
|
SqlDataReaderAccessor resultsReader = null;
|
|
|
|
try
|
|
{
|
|
//
|
|
// Get all the ChangeRecordNewData change records associated with this entity.
|
|
//
|
|
SqlStoredProcedureAccessor findSP = new SqlStoredProcedureAccessor();
|
|
findSP.ProcedureName = "net_find_changeRecordsByChangeType";
|
|
|
|
findSP.Parameters.Add( "@contextID", SqlDbType.UniqueIdentifier );
|
|
findSP.Parameters.Add( "@operatorKey", SqlDbType.UniqueIdentifier );
|
|
findSP.Parameters.Add( "@entityKey", SqlDbType.UniqueIdentifier );
|
|
findSP.Parameters.Add( "@changeTypeID", SqlDbType.TinyInt );
|
|
findSP.Parameters.Add( "@rows", SqlDbType.Int, ParameterDirection.Output );
|
|
|
|
findSP.Parameters.SetGuidFromString( "@contextID", contextID );
|
|
findSP.Parameters.SetGuidFromString( "@operatorKey", operatorKey );
|
|
findSP.Parameters.SetGuidFromString( "@entityKey", businessEntity.BusinessKey );
|
|
findSP.Parameters.SetShort( "@changeTypeID", ( short )ChangeRecordPayloadType.ChangeRecordNewData );
|
|
|
|
findSP.ExecuteNonQuery();
|
|
|
|
//
|
|
// Retrieve results
|
|
//
|
|
SqlStoredProcedureAccessor resultsSP = new SqlStoredProcedureAccessor();
|
|
|
|
resultsSP.ProcedureName = "net_find_changeRecords_commit";
|
|
|
|
resultsSP.Parameters.Add( "@contextID", SqlDbType.UniqueIdentifier );
|
|
resultsSP.Parameters.Add( "@responseLimitCount", SqlDbType.Int );
|
|
|
|
resultsSP.Parameters.SetGuidFromString( "@contextID", contextID );
|
|
resultsSP.Parameters.SetInt( "@responseLimitCount", 0 );
|
|
|
|
//
|
|
// Read our results and create change records from them.
|
|
//
|
|
resultsReader = resultsSP.ExecuteReader();
|
|
|
|
while( resultsReader.Read() )
|
|
{
|
|
ChangeRecord changeRecord = CreateChangeRecord( resultsReader );
|
|
if( null != changeRecord )
|
|
{
|
|
changeRecords.Add( changeRecord );
|
|
}
|
|
else
|
|
{
|
|
throw new Exception( "Could not create change record!" );
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
//
|
|
// Cleanup on failure.
|
|
//
|
|
SqlStoredProcedureAccessor cleanupSP = new SqlStoredProcedureAccessor();
|
|
|
|
cleanupSP.ProcedureName = "net_find_changeRecords_cleanup";
|
|
cleanupSP.Parameters.Add( "@contextID", SqlDbType.UniqueIdentifier );
|
|
cleanupSP.Parameters.SetGuidFromString( "@contextID", contextID );
|
|
|
|
cleanupSP.ExecuteNonQuery();
|
|
}
|
|
finally
|
|
{
|
|
if( null != resultsReader )
|
|
{
|
|
resultsReader.Close();
|
|
}
|
|
}
|
|
|
|
return changeRecords;
|
|
}
|
|
|
|
static ChangeRecord CreateChangeRecord( SqlDataReaderAccessor reader )
|
|
{
|
|
ChangeRecord changeRecord = null;
|
|
|
|
XmlSerializer serializer = null;
|
|
|
|
switch( (ChangeRecordPayloadType)reader.GetShort( "changeTypeID" ) )
|
|
{
|
|
case ChangeRecordPayloadType.ChangeRecordNull:
|
|
serializer = new XmlSerializer( typeof( ChangeRecordNull ) );
|
|
break;
|
|
|
|
case ChangeRecordPayloadType.ChangeRecordNewData:
|
|
serializer = new XmlSerializer( typeof( ChangeRecordNewData ) );
|
|
break;
|
|
|
|
case ChangeRecordPayloadType.ChangeRecordDelete:
|
|
serializer = new XmlSerializer( typeof( ChangeRecordDelete ) );
|
|
break;
|
|
|
|
case ChangeRecordPayloadType.ChangeRecordPublisherAssertion:
|
|
serializer = new XmlSerializer( typeof( ChangeRecordPublisherAssertion ) );
|
|
break;
|
|
|
|
case ChangeRecordPayloadType.ChangeRecordHide:
|
|
serializer = new XmlSerializer( typeof( ChangeRecordHide ) );
|
|
break;
|
|
|
|
case ChangeRecordPayloadType.ChangeRecordDeleteAssertion:
|
|
serializer = new XmlSerializer( typeof( ChangeRecordDeleteAssertion ) );
|
|
break;
|
|
|
|
case ChangeRecordPayloadType.ChangeRecordAcknowledgement:
|
|
serializer = new XmlSerializer( typeof( ChangeRecordAcknowledgement ) );
|
|
break;
|
|
|
|
case ChangeRecordPayloadType.ChangeRecordCorrection:
|
|
serializer = new XmlSerializer( typeof( ChangeRecordCorrection ) );
|
|
break;
|
|
}
|
|
|
|
StringReader stringReader = new StringReader( reader.GetString( "changeData" ) );
|
|
|
|
try
|
|
{
|
|
changeRecord = new ChangeRecord();
|
|
|
|
changeRecord.AcknowledgementRequested = ( reader.GetInt( "flag" ) & (int)ChangeRecordFlags.AcknowledgementRequested ) > 0;
|
|
changeRecord.ChangeID.NodeID = reader.GetString( "OperatorKey" );
|
|
changeRecord.ChangeID.OriginatingUSN = reader.GetLong( "USN" );
|
|
|
|
ChangeRecordBase changeRecordBase = ( ChangeRecordBase ) serializer.Deserialize( stringReader );
|
|
if( changeRecordBase is ChangeRecordCorrection )
|
|
{
|
|
//
|
|
// The query to find change records will do correction 'fixups'. That is, the changeData of this
|
|
// change record will be replaced with the changeData from the correction. The problem with this is
|
|
// that the original change data will now look like a correction. To distinguish these types of
|
|
// change records, we look to see if the OriginatingUSN's match. If the OriginatingUSN's match,
|
|
// we want they payload of the change record in this correction. This payload will contain the
|
|
// corrected data that we want.
|
|
//
|
|
ChangeRecordCorrection changeRecordCorrection = ( ChangeRecordCorrection ) changeRecordBase;
|
|
if( changeRecordCorrection.ChangeRecord.ChangeID.OriginatingUSN == changeRecord.ChangeID.OriginatingUSN )
|
|
{
|
|
changeRecordBase = changeRecordCorrection.ChangeRecord.Payload;
|
|
}
|
|
}
|
|
|
|
changeRecord.Payload = changeRecordBase;
|
|
}
|
|
finally
|
|
{
|
|
stringReader.Close();
|
|
}
|
|
|
|
return changeRecord;
|
|
}
|
|
|
|
static DiscoveryUrlCollection GetFilterList( BusinessEntity businessEntity )
|
|
{
|
|
DiscoveryUrlCollection filterList = new DiscoveryUrlCollection();
|
|
|
|
//
|
|
// Get the default URL
|
|
//
|
|
string defaultDiscoveryUrl= Config.GetString( "DefaultDiscoveryURL" ) + businessEntity.BusinessKey;
|
|
|
|
foreach( DiscoveryUrl discoveryUrl in businessEntity.DiscoveryUrls )
|
|
{
|
|
//
|
|
// Do a case in-sensitive search
|
|
//
|
|
if( string.Compare( discoveryUrl.Value, defaultDiscoveryUrl, true ) != 0 )
|
|
{
|
|
filterList.Add( discoveryUrl );
|
|
}
|
|
}
|
|
|
|
return filterList;
|
|
}
|
|
|
|
static ArrayList GetBusinessEntities()
|
|
{
|
|
ArrayList businessKeyList = new ArrayList();
|
|
|
|
SqlStoredProcedureAccessor sp = new SqlStoredProcedureAccessor();
|
|
sp.ProcedureName = "net_find_businessKeysWithDiscoveryURLs";
|
|
|
|
SqlDataReaderAccessor reader = sp.ExecuteReader();
|
|
|
|
ArrayList businessEntities = new ArrayList();
|
|
try
|
|
{
|
|
while( reader.Read() )
|
|
{
|
|
BusinessEntity businessEntity = new BusinessEntity( reader.GetGuidString( 0 ) );
|
|
businessEntities.Add( businessEntity );
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
reader.Close();
|
|
}
|
|
|
|
return businessEntities;
|
|
}
|
|
|
|
[STAThread]
|
|
static void Main(string[] args)
|
|
{
|
|
Log( "Microsoft (R) FixDefaultURL Migrate Utility", FixDefaultURL.LogType.ConsoleOnly );
|
|
Log( "Copyright (C) Microsoft Corp. 2002. All rights reserved.\n", FixDefaultURL.LogType.ConsoleOnly );
|
|
|
|
try
|
|
{
|
|
//
|
|
// Process command line arguments
|
|
//
|
|
ProcessCommandLineArgs( args );
|
|
|
|
//
|
|
// Init
|
|
//
|
|
Initialize();
|
|
|
|
//
|
|
// Fix our URLs
|
|
//
|
|
FixDefaultURLs();
|
|
}
|
|
catch( Exception e )
|
|
{
|
|
WriteException( "Uncaught exception: " + e.ToString() );
|
|
}
|
|
finally
|
|
{
|
|
logFile.Close();
|
|
|
|
if( null != exceptionsFile )
|
|
{
|
|
exceptionsFile.Close();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void ProcessCommandLineArgs( string[] commandLineArgs )
|
|
{
|
|
//
|
|
// No command line args.
|
|
//
|
|
}
|
|
|
|
static bool ValidatePublisher()
|
|
{
|
|
bool validPublisher = Context.User.IsRegistered;
|
|
|
|
//
|
|
// Make sure the user is a UDDI publisher.
|
|
//
|
|
if( false == validPublisher )
|
|
{
|
|
DialogResult dialogResult = MessageBox.Show( "You are not registered as a publisher on this UDDI Site? You must register before performing this operation. Would you like to register now?",
|
|
"UDDI",
|
|
MessageBoxButtons.YesNo );
|
|
|
|
if( DialogResult.Yes == dialogResult )
|
|
{
|
|
try
|
|
{
|
|
Context.User.Register();
|
|
validPublisher = Context.User.IsRegistered;
|
|
}
|
|
catch( Exception registrationException )
|
|
{
|
|
MessageBox.Show( "An exception occurred when trying to register:\r\n\r\n" + registrationException.ToString() );
|
|
}
|
|
}
|
|
}
|
|
|
|
return validPublisher;
|
|
}
|
|
|
|
static void Initialize()
|
|
{
|
|
//
|
|
// Open a connection to our UDDI database.
|
|
//
|
|
ConnectionManager.Open( true, false );
|
|
|
|
//
|
|
// Create our log file.
|
|
//
|
|
logFile = new StreamWriter( File.Open( LogFileName, FileMode.Append, FileAccess.Write, FileShare.Read ) );
|
|
logFile.WriteLine( "--------------------- STARTING NEW LOG (" + DateTime.Now.ToString() + ")--------------------- " );
|
|
|
|
//
|
|
// Get UDDI site configuration settings.
|
|
//
|
|
Config.Refresh();
|
|
|
|
//
|
|
// Make sure the user is allowed to run this program.
|
|
//
|
|
WindowsIdentity identity = WindowsIdentity.GetCurrent();
|
|
WindowsPrincipal principal = new WindowsPrincipal( identity );
|
|
|
|
Context.User.SetRole( principal );
|
|
|
|
if( !Context.User.IsAdministrator )
|
|
{
|
|
MessageBox.Show( "Access denied.\r\n\r\nThis program must be executed by a member of the '"
|
|
+ Config.GetString( "GroupName.Administrators" ) + "'\r\ngroup. The current user '"
|
|
+ identity.Name + "' is not a member of this group." );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Make sure the user is a valid publisher.
|
|
//
|
|
if( false == ValidatePublisher() )
|
|
{
|
|
Log( "You must be a UDDI publisher in order to run this program", LogType.ConsoleOnly );
|
|
System.Environment.Exit( 1 );
|
|
}
|
|
}
|
|
|
|
static void WriteException( Exception e )
|
|
{
|
|
WriteException( e.ToString() );
|
|
}
|
|
|
|
static void WriteException( string msg )
|
|
{
|
|
if( null == exceptionsFile )
|
|
{
|
|
//
|
|
// Create our exceptions file.
|
|
//
|
|
exceptionsFile = new StreamWriter( File.Open( ExceptionFileName, FileMode.Append, FileAccess.Write, FileShare.Read ) );
|
|
exceptionsFile.WriteLine( "--------------------- STARTING NEW LOG (" + DateTime.Now.ToString() + ")--------------------- " );
|
|
}
|
|
|
|
Log( exceptionsFile, msg, LogType.ConsoleAndLog );
|
|
}
|
|
|
|
static void Log( string message )
|
|
{
|
|
Log( message, LogType.ConsoleAndLog );
|
|
}
|
|
|
|
static void Log( string message, LogType logType )
|
|
{
|
|
Log( logFile, message, logType );
|
|
}
|
|
|
|
static void Log( StreamWriter log, string message, LogType logType )
|
|
{
|
|
switch ( logType )
|
|
{
|
|
case LogType.ConsoleAndLog:
|
|
{
|
|
Console.WriteLine( message );
|
|
log.WriteLine( "{0}: {1}", DateTime.Now.ToLongTimeString(), message );
|
|
break;
|
|
}
|
|
case LogType.ConsoleOnly:
|
|
{
|
|
Console.WriteLine( message );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
log.WriteLine( "{0}: {1}", DateTime.Now.ToLongTimeString(), message );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static string Serialize( object obj )
|
|
{
|
|
UTF8EncodedStringWriter stringWriter = new UTF8EncodedStringWriter();
|
|
|
|
try
|
|
{
|
|
XmlSerializer serializer = new XmlSerializer( obj.GetType() );
|
|
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
|
|
namespaces.Add( "", "urn:uddi-org:api_v2" );
|
|
|
|
serializer.Serialize( stringWriter, obj, namespaces );
|
|
}
|
|
finally
|
|
{
|
|
stringWriter.Close();
|
|
}
|
|
|
|
return stringWriter.ToString();
|
|
}
|
|
|
|
static void LogStartBusinessEntity( BusinessEntity businessEntity )
|
|
{
|
|
Log( "START Examining: " + businessEntity.BusinessKey );
|
|
Log( "\tOriginal DiscoveryUrls:" );
|
|
|
|
foreach( DiscoveryUrl discoveryUrl in businessEntity.DiscoveryUrls )
|
|
{
|
|
Log( "\t\t" + discoveryUrl.Value );
|
|
}
|
|
}
|
|
|
|
static void LogDoneBusinessEntity( BusinessEntity businessEntity )
|
|
{
|
|
Log( "DONE Examining: " + businessEntity.BusinessKey );
|
|
}
|
|
|
|
static void LogFixStart( DiscoveryUrlCollection filteredList )
|
|
{
|
|
Log( "\tSTART Fixing duplicates; new DiscoveryUrl list will be:" );
|
|
|
|
if( filteredList.Count == 0 )
|
|
{
|
|
Log( "\t\tNo Discovery Urls besides default." );
|
|
}
|
|
else
|
|
{
|
|
foreach( DiscoveryUrl discoveryUrl in filteredList )
|
|
{
|
|
Log( "\t\t" + discoveryUrl.Value );
|
|
}
|
|
}
|
|
}
|
|
|
|
static void LogFixEnd( BusinessEntity businessEntity )
|
|
{
|
|
Log( "\tDONE Fixing duplicates" );
|
|
}
|
|
|
|
static void LogChangeRecordCorrection( ChangeRecord changeRecord, ChangeRecord changeRecordCorrection )
|
|
{
|
|
Log( "\t\t\tCorrecting USN: " + changeRecord.ChangeID.OriginatingUSN );
|
|
}
|
|
}
|
|
}
|