diff --git a/build.json b/build.json index d294bfee..a3273984 100644 --- a/build.json +++ b/build.json @@ -17,6 +17,7 @@ ], "MainProjects": [ "Microsoft.SqlTools.ServiceLayer", - "Microsoft.SqlTools.Credentials" + "Microsoft.SqlTools.Credentials", + "Microsoft.Sqltools.Serialization" ] } diff --git a/sqltoolsservice.sln b/sqltoolsservice.sln index 62f9c42c..6dca984b 100644 --- a/sqltoolsservice.sln +++ b/sqltoolsservice.sln @@ -70,6 +70,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ServiceL EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ServiceLayer.TestEnvConfig", "test\Microsoft.SqlTools.ServiceLayer.TestEnvConfig\Microsoft.SqlTools.ServiceLayer.TestEnvConfig.csproj", "{2C290C58-C98D-46B2-BCED-44D9B67F6D31}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Serialization", "src\Microsoft.SqlTools.Serialization\Microsoft.SqlTools.Serialization.csproj", "{75E1A89F-9DF6-4DA3-9EF1-5FD966331E06}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -137,6 +139,12 @@ Global {2C290C58-C98D-46B2-BCED-44D9B67F6D31}.Integration|Any CPU.Build.0 = Debug|Any CPU {2C290C58-C98D-46B2-BCED-44D9B67F6D31}.Release|Any CPU.ActiveCfg = Release|Any CPU {2C290C58-C98D-46B2-BCED-44D9B67F6D31}.Release|Any CPU.Build.0 = Release|Any CPU + {75E1A89F-9DF6-4DA3-9EF1-5FD966331E06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75E1A89F-9DF6-4DA3-9EF1-5FD966331E06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75E1A89F-9DF6-4DA3-9EF1-5FD966331E06}.Integration|Any CPU.ActiveCfg = Debug|Any CPU + {75E1A89F-9DF6-4DA3-9EF1-5FD966331E06}.Integration|Any CPU.Build.0 = Debug|Any CPU + {75E1A89F-9DF6-4DA3-9EF1-5FD966331E06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75E1A89F-9DF6-4DA3-9EF1-5FD966331E06}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -154,5 +162,9 @@ Global {E985A5AA-63E4-48DC-A6D8-D3953A50D7E3} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {501DB3B2-AF92-41CF-82F6-780F9C37C219} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {2C290C58-C98D-46B2-BCED-44D9B67F6D31} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} + {75E1A89F-9DF6-4DA3-9EF1-5FD966331E06} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B31CDF4B-2851-45E5-8C5F-BE97125D9DD8} EndGlobalSection EndGlobal diff --git a/src/Microsoft.SqlTools.Credentials/HostLoader.cs b/src/Microsoft.SqlTools.Credentials/HostLoader.cs index 4d35a823..592dde10 100644 --- a/src/Microsoft.SqlTools.Credentials/HostLoader.cs +++ b/src/Microsoft.SqlTools.Credentials/HostLoader.cs @@ -6,8 +6,9 @@ using Microsoft.SqlTools.Extensibility; using Microsoft.SqlTools.Hosting; using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Microsoft.SqlTools.Utility; -namespace Microsoft.SqlTools.Credentials +namespace Microsoft.SqlTools.Credentials.Utility { /// /// Provides support for starting up a service host. This is a common responsibility @@ -18,9 +19,9 @@ namespace Microsoft.SqlTools.Credentials private static object lockObject = new object(); private static bool isLoaded; - internal static CredentialsServiceHost CreateAndStartServiceHost(SqlToolsContext sqlToolsContext) + internal static UtilityServiceHost CreateAndStartServiceHost(SqlToolsContext sqlToolsContext) { - CredentialsServiceHost serviceHost = CredentialsServiceHost.Instance; + UtilityServiceHost serviceHost = UtilityServiceHost.Instance; lock (lockObject) { if (!isLoaded) @@ -40,7 +41,7 @@ namespace Microsoft.SqlTools.Credentials return serviceHost; } - private static void InitializeRequestHandlersAndServices(CredentialsServiceHost serviceHost, SqlToolsContext sqlToolsContext) + private static void InitializeRequestHandlersAndServices(UtilityServiceHost serviceHost, SqlToolsContext sqlToolsContext) { // Load extension provider, which currently finds all exports in current DLL. Can be changed to find based // on directory or assembly list quite easily in the future diff --git a/src/Microsoft.SqlTools.Credentials/Microsoft.SqlTools.Credentials.csproj b/src/Microsoft.SqlTools.Credentials/Microsoft.SqlTools.Credentials.csproj index 63839945..88bd1037 100644 --- a/src/Microsoft.SqlTools.Credentials/Microsoft.SqlTools.Credentials.csproj +++ b/src/Microsoft.SqlTools.Credentials/Microsoft.SqlTools.Credentials.csproj @@ -35,4 +35,7 @@ + + + diff --git a/src/Microsoft.SqlTools.Credentials/Program.cs b/src/Microsoft.SqlTools.Credentials/Program.cs index 93db0404..a7ee1a02 100644 --- a/src/Microsoft.SqlTools.Credentials/Program.cs +++ b/src/Microsoft.SqlTools.Credentials/Program.cs @@ -5,6 +5,7 @@ using System; using System.IO; using Microsoft.SqlTools.Credentials.Utility; +using Microsoft.SqlTools.Hosting.Utility; using Microsoft.SqlTools.ServiceLayer.SqlContext; using Microsoft.SqlTools.Utility; @@ -15,6 +16,8 @@ namespace Microsoft.SqlTools.Credentials /// internal class Program { + private const string ServiceName = "MicrosoftSqlToolsCredentials.exe"; + /// /// Main entry point into the Credentials Service Host /// @@ -23,7 +26,7 @@ namespace Microsoft.SqlTools.Credentials try { // read command-line arguments - CommandOptions commandOptions = new CommandOptions(args); + CommandOptions commandOptions = new CommandOptions(args, ServiceName); if (commandOptions.ShouldExit) { return; @@ -37,7 +40,7 @@ namespace Microsoft.SqlTools.Credentials // turn on Verbose logging during early development // we need to switch to Normal when preparing for public preview - Logger.Initialize(logFilePath, minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging); + Logger.Initialize(logFilePath: logFilePath, minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging); Logger.Write(LogLevel.Normal, "Starting SqlTools Credentials Provider"); // set up the host details and profile paths @@ -47,7 +50,7 @@ namespace Microsoft.SqlTools.Credentials version: new Version(1, 0)); SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails); - CredentialsServiceHost serviceHost = HostLoader.CreateAndStartServiceHost(sqlToolsContext); + UtilityServiceHost serviceHost = HostLoader.CreateAndStartServiceHost(sqlToolsContext); serviceHost.WaitForExit(); } diff --git a/src/Microsoft.SqlTools.Credentials/Utility/CommandOptions.cs b/src/Microsoft.SqlTools.Credentials/Utility/CommandOptions.cs deleted file mode 100644 index cae292f7..00000000 --- a/src/Microsoft.SqlTools.Credentials/Utility/CommandOptions.cs +++ /dev/null @@ -1,113 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -using System; -using System.IO; - -namespace Microsoft.SqlTools.Credentials.Utility -{ - /// - /// The command-line options helper class. - /// - internal class CommandOptions - { - /// - /// Construct and parse command line options from the arguments array - /// - public CommandOptions(string[] args) - { - ErrorMessage = string.Empty; - - try - { - for (int i = 0; i < args.Length; ++i) - { - string arg = args[i]; - if (arg.StartsWith("--") || arg.StartsWith("-")) - { - if (arg.StartsWith("--")) - { - // Extracting arguments and properties - arg = arg.Substring(1).ToLowerInvariant(); - } - switch (arg) - { - case "-enable-logging": - EnableLogging = true; - break; - case "-log-dir": - SetLoggingDirectory(args[++i]); - break; - case "h": - case "-help": - ShouldExit = true; - return; - default: - ErrorMessage += String.Format("Unknown argument \"{0}\"" + Environment.NewLine, arg); - break; - } - } - } - } - catch (Exception ex) - { - ErrorMessage += ex.ToString(); - return; - } - finally - { - if (!string.IsNullOrEmpty(ErrorMessage) || ShouldExit) - { - Console.WriteLine(Usage); - ShouldExit = true; - } - } - } - - internal string ErrorMessage { get; private set; } - - /// - /// Whether diagnostic logging is enabled - /// - public bool EnableLogging { get; private set; } - - /// - /// Gets the directory where log files are output. - /// - public string LoggingDirectory { get; private set; } - - /// - /// Whether the program should exit immediately. Set to true when the usage is printed. - /// - public bool ShouldExit { get; private set; } - - private void SetLoggingDirectory(string loggingDirectory) - { - if (string.IsNullOrWhiteSpace(loggingDirectory)) - { - return; - } - - this.LoggingDirectory = Path.GetFullPath(loggingDirectory); - } - - /// - /// Get the usage string describing command-line arguments for the program - /// - public string Usage - { - get - { - var str = string.Format("{0}" + Environment.NewLine + - "Microsoft.SqlTools.Credentials " + Environment.NewLine + - " Options:" + Environment.NewLine + - " [--enable-logging]" + Environment.NewLine + - " [--help]" + Environment.NewLine, - ErrorMessage); - return str; - } - } - } -} diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/CommandOptions.cs b/src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs similarity index 77% rename from src/Microsoft.SqlTools.ServiceLayer/Utility/CommandOptions.cs rename to src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs index 59888389..7967b07c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/CommandOptions.cs +++ b/src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs @@ -7,18 +7,19 @@ using System; using System.Globalization; using System.IO; -namespace Microsoft.SqlTools.ServiceLayer.Utility +namespace Microsoft.SqlTools.Hosting.Utility { /// /// The command-line options helper class. /// - internal class CommandOptions + public class CommandOptions { /// /// Construct and parse command line options from the arguments array /// - public CommandOptions(string[] args) + public CommandOptions(string[] args, string serviceName) { + ServiceName = serviceName; ErrorMessage = string.Empty; Locale = string.Empty; @@ -70,7 +71,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility } } - internal string ErrorMessage { get; private set; } + /// + /// Contains any error messages during execution + /// + public string ErrorMessage { get; private set; } /// @@ -93,6 +97,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility /// public string Locale { get; private set; } + /// + /// Name of service that is receiving command options + /// + public string ServiceName { get; private set; } + /// /// Get the usage string describing command-line arguments for the program /// @@ -101,7 +110,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility get { var str = string.Format("{0}" + Environment.NewLine + - "Microsoft.SqlTools.ServiceLayer.exe " + Environment.NewLine + + ServiceName + " " + Environment.NewLine + " Options:" + Environment.NewLine + " [--enable-logging]" + Environment.NewLine + " [--log-dir **] (default: current directory)" + Environment.NewLine + @@ -122,20 +131,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility this.LoggingDirectory = Path.GetFullPath(loggingDirectory); } - private void SetLocale(string locale) + public virtual void SetLocale(string locale) { try { - // Creating cultureInfo from our given locale - CultureInfo language = new CultureInfo(locale); - Locale = locale; - - // Setting our language globally - CultureInfo.CurrentCulture = language; - CultureInfo.CurrentUICulture = language; - - // Setting our internal SR culture to our global culture - SR.Culture = CultureInfo.CurrentCulture; + LocaleSetter(locale); } catch (CultureNotFoundException) { @@ -144,5 +144,21 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility // into the CultureInfo constructor. } } + + /// + /// Sets the Locale field used for testing and also sets the global CultureInfo used for + /// culture-specific messages + /// + /// + internal void LocaleSetter(string locale) + { + // Creating cultureInfo from our given locale + CultureInfo language = new CultureInfo(locale); + Locale = locale; + + // Setting our language globally + CultureInfo.CurrentCulture = language; + CultureInfo.CurrentUICulture = language; + } } } diff --git a/src/Microsoft.SqlTools.Credentials/CredentialsServiceHost.cs b/src/Microsoft.SqlTools.Hosting/Utility/UtilityServiceHost.cs similarity index 91% rename from src/Microsoft.SqlTools.Credentials/CredentialsServiceHost.cs rename to src/Microsoft.SqlTools.Hosting/Utility/UtilityServiceHost.cs index 9ec96b31..e9e3a482 100644 --- a/src/Microsoft.SqlTools.Credentials/CredentialsServiceHost.cs +++ b/src/Microsoft.SqlTools.Hosting/Utility/UtilityServiceHost.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // @@ -12,34 +12,33 @@ using Microsoft.SqlTools.Hosting; using Microsoft.SqlTools.Hosting.Contracts; using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.Hosting.Protocol.Channel; -using Microsoft.SqlTools.Utility; -namespace Microsoft.SqlTools.Credentials +namespace Microsoft.SqlTools.Utility { /// - /// SQL Tools Credentials Service request handler. Provides the entire JSON RPC + /// SQL Tools Service request handler for any utility services. Provides the entire JSON RPC /// implementation for sending/receiving JSON requests and dispatching the requests to /// handlers that are registered prior to startup. /// - public sealed class CredentialsServiceHost : ServiceHostBase + public sealed class UtilityServiceHost : ServiceHostBase { /// /// This timeout limits the amount of time that shutdown tasks can take to complete /// prior to the process shutting down. /// - private const int ShutdownTimeoutInSeconds = 120; + private const int ShutdownTimeoutInSeconds = 120; #region Singleton Instance Code /// /// Singleton instance of the service host for internal storage /// - private static readonly Lazy instance = new Lazy(() => new CredentialsServiceHost()); + private static readonly Lazy instance = new Lazy(() => new UtilityServiceHost()); /// /// Current instance of the ServiceHost /// - public static CredentialsServiceHost Instance + public static UtilityServiceHost Instance { get { return instance.Value; } } @@ -48,7 +47,7 @@ namespace Microsoft.SqlTools.Credentials /// Constructs new instance of ServiceHost using the host and profile details provided. /// Access is private to ensure only one instance exists at a time. /// - private CredentialsServiceHost() : base(new StdioServerChannel()) + private UtilityServiceHost() : base(new StdioServerChannel()) { // Initialize the shutdown activities shutdownCallbacks = new List(); diff --git a/src/Microsoft.SqlTools.Serialization/HostLoader.cs b/src/Microsoft.SqlTools.Serialization/HostLoader.cs new file mode 100644 index 00000000..0e2d713a --- /dev/null +++ b/src/Microsoft.SqlTools.Serialization/HostLoader.cs @@ -0,0 +1,83 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.SqlTools.Extensibility; +using Microsoft.SqlTools.Hosting; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.Serialization +{ + /// + /// Provides support for starting up a service host. This is a common responsibility + /// for both the main service program and test driver that interacts with it + /// + public static class HostLoader + { + private static object lockObject = new object(); + private static bool isLoaded; + + internal static UtilityServiceHost CreateAndStartServiceHost(SqlToolsContext sqlToolsContext) + { + UtilityServiceHost serviceHost = UtilityServiceHost.Instance; + lock (lockObject) + { + if (!isLoaded) + { + // Grab the instance of the service host + serviceHost.Initialize(); + + InitializeRequestHandlersAndServices(serviceHost, sqlToolsContext); + + // Start the service only after all request handlers are setup. This is vital + // as otherwise the Initialize event can be lost - it's processed and discarded before the handler + // is hooked up to receive the message + serviceHost.Start().Wait(); + isLoaded = true; + } + } + return serviceHost; + } + + private static void InitializeRequestHandlersAndServices(UtilityServiceHost serviceHost, SqlToolsContext sqlToolsContext) + { + // Load extension provider, which currently finds all exports in current DLL. Can be changed to find based + // on directory or assembly list quite easily in the future + ExtensionServiceProvider serviceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider(); + serviceProvider.RegisterSingleService(sqlToolsContext); + serviceProvider.RegisterSingleService(serviceHost); + + SerializationService serializationService = serviceProvider.GetService(); + serializationService.InitializeService(serviceHost); + serviceProvider.RegisterSingleService(serializationService); + + InitializeHostedServices(serviceProvider, serviceHost); + + serviceHost.InitializeRequestHandlers(); + } + + /// + /// Internal to support testing. Initializes instances in the service, + /// and registers them for their preferred service type + /// + internal static void InitializeHostedServices(RegisteredServiceProvider provider, IProtocolEndpoint host) + { + // Pre-register all services before initializing. This ensures that if one service wishes to reference + // another one during initialization, it will be able to safely do so + foreach (IHostedService service in provider.GetServices()) + { + provider.RegisterSingleService(service.ServiceType, service); + } + + foreach (IHostedService service in provider.GetServices()) + { + // Initialize all hosted services, and register them in the service provider for their requested + // service type. This ensures that when searching for the ConnectionService you can get it without + // searching for an IHostedService of type ConnectionService + service.InitializeService(host); + } + } + } +} diff --git a/src/Microsoft.SqlTools.Serialization/Microsoft.SqlTools.Serialization.csproj b/src/Microsoft.SqlTools.Serialization/Microsoft.SqlTools.Serialization.csproj new file mode 100644 index 00000000..018b31d4 --- /dev/null +++ b/src/Microsoft.SqlTools.Serialization/Microsoft.SqlTools.Serialization.csproj @@ -0,0 +1,23 @@ + + + + Exe + netcoreapp2.0 + SqlSerializationService + SqlSerializationService + Microsoft + Sql Tools Serialization Service + Provides serialization functionality. + � Microsoft Corporation. All rights reserved. + + + + TRACE;DEBUG;NETCOREAPP1_0;NETCOREAPP2_0 + + + + + + + + diff --git a/src/Microsoft.SqlTools.Serialization/Program.cs b/src/Microsoft.SqlTools.Serialization/Program.cs new file mode 100644 index 00000000..42e2c425 --- /dev/null +++ b/src/Microsoft.SqlTools.Serialization/Program.cs @@ -0,0 +1,63 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.IO; +using Microsoft.SqlTools.Hosting.Utility; +using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.Serialization +{ + /// + /// Main application class for Serialization Service Host executable + /// + internal class Program + { + private const string ServiceName = "SqlSerializationService.exe"; + + /// + /// Main entry point into the Serialization Service Host + /// + internal static void Main(string[] args) + { + try + { + // read command-line arguments + CommandOptions commandOptions = new CommandOptions(args, ServiceName); + if (commandOptions.ShouldExit) + { + return; + } + + string logFilePath = "serialization"; + if (!string.IsNullOrWhiteSpace(commandOptions.LoggingDirectory)) + { + logFilePath = Path.Combine(commandOptions.LoggingDirectory, logFilePath); + } + + // turn on Verbose logging during early development + // we need to switch to Normal when preparing for public preview + Logger.Initialize(logFilePath: logFilePath, minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging); + Logger.Write(LogLevel.Normal, "Starting SqlTools Serialization Provider"); + + // set up the host details and profile paths + var hostDetails = new HostDetails( + name: "SqlTools Serialization Provider", + profileId: "Microsoft.SqlTools.Serialization", + version: new Version(1, 0)); + + SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails); + UtilityServiceHost serviceHost = HostLoader.CreateAndStartServiceHost(sqlToolsContext); + + serviceHost.WaitForExit(); + } + catch (Exception e) + { + Logger.Write(LogLevel.Error, string.Format("An unhandled exception occurred: {0}", e)); + Environment.Exit(1); + } + } + } +} diff --git a/src/Microsoft.SqlTools.Serialization/SerializationService.cs b/src/Microsoft.SqlTools.Serialization/SerializationService.cs new file mode 100644 index 00000000..00cca946 --- /dev/null +++ b/src/Microsoft.SqlTools.Serialization/SerializationService.cs @@ -0,0 +1,78 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Composition; +using System.Threading.Tasks; +using Microsoft.SqlTools.Extensibility; +using Microsoft.SqlTools.Hosting; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.Serialization +{ + /// + /// Service responsible for securing credentials in a platform-neutral manner. This provides + /// a generic API for read, save and delete credentials + /// + + [Export(typeof(IHostedService))] + public class SerializationService : HostedService, IComposableService + { + public override void InitializeService(IProtocolEndpoint serviceHost) + { + Logger.Write(LogLevel.Verbose, "Serialization initialized"); + // Register request and event handlers with the Service Host + serviceHost.SetRequestHandler(SaveAsRequest.Type, HandleSaveAsRequest); + } + + public async Task HandleSaveAsRequest(SaveResultsInfo resultsInfo, RequestContext requestContext) + { + Func> doSave = () => + { + return SaveAsAsync(resultsInfo, requestContext); + }; + + await HandleRequest(doSave, requestContext, "HandleSaveAsRequest"); + } + + public async Task SaveAsAsync(SaveResultsInfo resultsInfo, RequestContext requestContext) + { + // TODO: Refactor currently available serialization code in sqltools to be utilized here + // Issue here: https://github.com/Microsoft/carbon/issues/1789 + switch (resultsInfo.SaveFormat) { + case "json": + throw new NotImplementedException("Converting to " + resultsInfo.SaveFormat + " is not implemented."); + break; + case "csv": + throw new NotImplementedException("Converting to " + resultsInfo.SaveFormat + " is not implemented."); + break; + case "excel": + throw new NotImplementedException("Converting to " + resultsInfo.SaveFormat + " is not implemented."); + break; + default: + throw new NotImplementedException("Converting to " + resultsInfo.SaveFormat + " is not implemented."); + + } + } + + private async Task HandleRequest(Func> handler, RequestContext requestContext, string requestType) + { + Logger.Write(LogLevel.Verbose, requestType); + + try + { + T result = await handler(); + await requestContext.SendResult(result); + } + catch (Exception ex) + { + await requestContext.SendError(ex.ToString()); + } + } + + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOptionsHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOptionsHelper.cs index e684ac6d..1f3e6a9f 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOptionsHelper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOptionsHelper.cs @@ -3,9 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using System; using System.Collections.Generic; -using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.Hosting.Contracts; using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts; using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation; diff --git a/src/Microsoft.SqlTools.ServiceLayer/Program.cs b/src/Microsoft.SqlTools.ServiceLayer/Program.cs index 15d5e3ae..6d89dc95 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Program.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Program.cs @@ -23,7 +23,7 @@ namespace Microsoft.SqlTools.ServiceLayer try { // read command-line arguments - CommandOptions commandOptions = new CommandOptions(args); + ServiceLayerCommandOptions commandOptions = new ServiceLayerCommandOptions(args); if (commandOptions.ShouldExit) { return; diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/SaveResultsRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/SaveResultsRequest.cs index 4939a353..de407728 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/SaveResultsRequest.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/SaveResultsRequest.cs @@ -3,7 +3,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using System; using Microsoft.SqlTools.Hosting.Protocol.Contracts; namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/Serialization.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/Serialization.cs new file mode 100644 index 00000000..e1b42774 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/Serialization.cs @@ -0,0 +1,57 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Protocol.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts +{ + /// + /// Class used for storing results and how the results are to be serialized + /// + public class SaveResultsInfo + { + /// + /// String representation of the type that service is supposed to serialize to + /// E.g. "json" or "csv" + /// + public string SaveFormat { get; set; } + + /// + /// Path to file that the serialized results will be stored in + /// + public string SavePath { get; set; } + + /// + /// Results that are to be serialized into 'SaveFormat' format + /// + public DbCellValue[][] Rows { get; set; } + + /// + /// Whether the current set of Rows passed in is the last for this file + // + public bool IsLast { get; set; } + + /// + /// Constructor + /// + public SaveResultsInfo(string saveFormat, + string savePath, + DbCellValue[][] rows, + bool isLast) + { + this.SaveFormat = saveFormat; + this.SavePath = savePath; + this.Rows = Rows; + this.IsLast = isLast; + } + } + + public class SaveAsRequest + { + public static readonly + RequestType Type = + RequestType.Create("query/saveAs"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsExcelFileStreamWriter.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsExcelFileStreamWriter.cs index f6ac59e5..1381e91e 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsExcelFileStreamWriter.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsExcelFileStreamWriter.cs @@ -3,11 +3,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsExcelFileStreamWriterHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsExcelFileStreamWriterHelper.cs index e276f559..c91a44d6 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsExcelFileStreamWriterHelper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/SaveAsExcelFileStreamWriterHelper.cs @@ -3,12 +3,12 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Xml; +using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage { diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs index c8f52119..29d3ad98 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs @@ -4,8 +4,6 @@ // using System; using System.Collections.Concurrent; -using System.Data.Common; -using System.Data.SqlClient; using System.IO; using System.Threading.Tasks; using Microsoft.SqlTools.ServiceLayer.Connection; diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/ServiceLayerCommandOptions.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/ServiceLayerCommandOptions.cs new file mode 100644 index 00000000..43c5f6b3 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/ServiceLayerCommandOptions.cs @@ -0,0 +1,36 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Globalization; +using Microsoft.SqlTools.Hosting.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.Utility +{ + class ServiceLayerCommandOptions : CommandOptions + { + private const string ServiceLayerServiceName = "MicrosoftSqlToolsServiceLayer.exe"; + + public ServiceLayerCommandOptions(string[] args) : base(args, ServiceLayerServiceName) + { + } + + public override void SetLocale(string locale) + { + try + { + LocaleSetter(locale); + + // Setting our internal SR culture to our global culture + SR.Culture = CultureInfo.CurrentCulture; + } + catch (CultureNotFoundException) + { + // Ignore CultureNotFoundException since it only is thrown before Windows 10. Windows 10, + // along with macOS and Linux, pick up the default culture if an invalid locale is passed + // into the CultureInfo constructor. + } + } + + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TaskServices/RequstParamStub.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TaskServices/RequstParamStub.cs index 82f0c6d4..48010758 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TaskServices/RequstParamStub.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TaskServices/RequstParamStub.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.SqlTools.ServiceLayer.TaskServices; +using Microsoft.SqlTools.ServiceLayer.TaskServices; using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TaskServices diff --git a/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Tests/QueryExecutionTests.cs b/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Tests/QueryExecutionTests.cs index fe2d5a00..7254ec75 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Tests/QueryExecutionTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Tests/QueryExecutionTests.cs @@ -6,7 +6,6 @@ using System; using System.Linq; using System.Threading.Tasks; -using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts.ExecuteRequests; using Microsoft.SqlTools.ServiceLayer.Test.Common; using Xunit; diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/DataStorage/SaveAsExcelFileStreamWriterHelperTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/DataStorage/SaveAsExcelFileStreamWriterHelperTests.cs index c1e28fcc..43bf029d 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/DataStorage/SaveAsExcelFileStreamWriterHelperTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/DataStorage/SaveAsExcelFileStreamWriterHelperTests.cs @@ -3,7 +3,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage; using Microsoft.SqlTools.ServiceLayer.Test.Common; using Moq; @@ -12,6 +11,7 @@ using System.IO; using System.IO.Compression; using System.Text.RegularExpressions; using System.Xml; +using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; using Xunit; namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs index 41129101..c60c0add 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/SrTests.cs @@ -213,7 +213,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost { string locale = "en"; var args = new string[] { "--locale", locale }; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); Assert.Equal(SR.Culture.Name, options.Locale); Assert.Equal(options.Locale, locale); @@ -226,7 +226,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost { string locale = "es"; var args = new string[] { "--locale", locale }; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); Assert.Equal(SR.Culture.Name, options.Locale); Assert.Equal(options.Locale, locale); @@ -242,7 +242,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost { SR.Culture = null; var args = new string[] { "" }; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); Assert.Null(SR.Culture); Assert.Equal(options.Locale, ""); diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs index 3771c05a..c0a2a3f0 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs @@ -3,8 +3,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.ServiceLayer.Utility; using System.IO; +using Microsoft.SqlTools.ServiceLayer.Utility; using Xunit; namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility @@ -18,7 +18,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility public void LoggingEnabledWhenFlagProvided() { var args = new string[] {"--enable-logging"}; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); Assert.NotNull(options); Assert.True(options.EnableLogging); @@ -30,7 +30,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility public void LoggingDisabledWhenFlagNotProvided() { var args = new string[] {}; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); Assert.NotNull(options); Assert.False(options.EnableLogging); @@ -42,7 +42,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility public void UsageIsShownWhenHelpFlagProvided() { var args = new string[] {"--help"}; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); Assert.NotNull(options); Assert.True(options.ShouldExit); @@ -53,7 +53,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility public void UsageIsShownWhenBadArgumentsProvided() { var args = new string[] {"--unknown-argument", "/bad-argument"}; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); Assert.NotNull(options); Assert.True(options.ShouldExit); @@ -64,7 +64,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility public void DefaultValuesAreUsedWhenNoArgumentsAreProvided() { var args = new string[] {}; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); Assert.NotNull(options); Assert.False(options.EnableLogging); @@ -79,7 +79,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility public void LocaleSetWhenProvided(string locale) { var args = new string[] {"--locale", locale}; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); ; // Asserting all options were properly set Assert.NotNull(options); @@ -92,7 +92,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility { string locale = "invalid"; var args = new string[] { "--locale", locale }; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); // Asserting all options were properly set Assert.NotNull(options); @@ -103,7 +103,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility public void LocaleNotSetWhenNotProvided() { var args = new string[] {}; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); // Asserting all options were properly set Assert.NotNull(options); @@ -117,7 +117,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility { string logDir = Directory.GetCurrentDirectory(); var args = new string[] { "--log-dir", logDir }; - CommandOptions options = new CommandOptions(args); + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); // Asserting all options were properly set Assert.NotNull(options); diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/SqlScriptFormatterTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/SqlScriptFormatterTests.cs index f077d9bb..582c5590 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/SqlScriptFormatterTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/SqlScriptFormatterTests.cs @@ -7,8 +7,6 @@ using System; using System.Collections.Generic; using System.Data.Common; using System.Text.RegularExpressions; -using Microsoft.SqlServer.Management.Smo; -using Microsoft.SqlServer.Management.SqlParser.SqlCodeDom; using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; using Microsoft.SqlTools.ServiceLayer.Utility; using Xunit;