This commit is contained in:
Daniele Teti 2017-10-16 22:57:27 +02:00
parent 91e5e6585c
commit a8d57bb78b
26 changed files with 1247 additions and 53 deletions

Binary file not shown.

View File

@ -9,14 +9,12 @@ object dmMain: TdmMain
'Password=masterkey' 'Password=masterkey'
'DriverID=FB') 'DriverID=FB')
ConnectedStoredUsage = [] ConnectedStoredUsage = []
Connected = True
LoginPrompt = False LoginPrompt = False
BeforeConnect = ConnectionBeforeConnect BeforeConnect = ConnectionBeforeConnect
Left = 64 Left = 64
Top = 48 Top = 48
end end
object dsArticles: TFDQuery object dsArticles: TFDQuery
Active = True
Connection = Connection Connection = Connection
UpdateOptions.AssignedValues = [uvFetchGeneratorsPoint, uvGeneratorName] UpdateOptions.AssignedValues = [uvFetchGeneratorsPoint, uvGeneratorName]
UpdateOptions.FetchGeneratorsPoint = gpImmediate UpdateOptions.FetchGeneratorsPoint = gpImmediate

View File

@ -30,8 +30,8 @@ procedure TdmMain.ConnectionBeforeConnect(Sender: TObject);
begin begin
// currently, this demo uses firebird 2.5 // currently, this demo uses firebird 2.5
// if you want to use firebird 2.5, you can use the file ORDERSMANAGER_FB25.FDB // if you want to use firebird 2.5, you can use the file ORDERSMANAGER_FB25.FDB
// Connection.Params.Values['Database'] := '..\..\data\ORDERSMANAGER_FB30.FDB'; Connection.Params.Values['Database'] := '..\..\data\ORDERSMANAGER_FB30.FDB';
Connection.Params.Values['Database'] := '..\..\data\ORDERSMANAGER_FB25.FDB'; // Connection.Params.Values['Database'] := '..\..\data\ORDERSMANAGER_FB25.FDB';
end; end;
end. end.

View File

@ -22,7 +22,7 @@ implementation
{ %CLASSGROUP 'Vcl.Controls.TControl' } { %CLASSGROUP 'Vcl.Controls.TControl' }
uses Controllers.Articles, MVCFramework.Middleware.CORS; uses Controllers.Articles, MVCFramework.Middleware.CORS, MVCFramework.Middleware.Compression;
{$R *.dfm} {$R *.dfm}
@ -41,6 +41,8 @@ begin
FEngine := TMVCEngine.Create(self); FEngine := TMVCEngine.Create(self);
FEngine.AddController(TArticlesController); FEngine.AddController(TArticlesController);
FEngine.AddMiddleware(TCORSMiddleware.Create); FEngine.AddMiddleware(TCORSMiddleware.Create);
FEngine.AddMiddleware(TCompressionMiddleware.Create);
end; end;
end. end.

View File

@ -0,0 +1,40 @@
unit Controller1U;
interface
uses
MVCFramework, MVCFramework.Commons, ServicesInterfaceU, Spring.Container.Common;
type
[MVCPath('/controller1')]
TMyController1 = class(TMVCController)
protected
[Inject]
fUsersService: IUsersService;
[Inject]
fCustomersService: ICustomersService;
public
[MVCPath]
[MVCHTTPMethod([httpGET])]
procedure Index;
end;
implementation
uses
System.SysUtils, MVCFramework.Logger, System.StrUtils;
procedure TMyController1.Index;
begin
ContentType := BuildContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591);
ResponseStream.AppendLine('THIS IS A TEST FOR SPRING4D INTEGRATION');
ResponseStream.AppendLine('===============================================================');
ResponseStream.AppendLine('fUsersService.GetUserNameByID(1234) => ' +
fUsersService.GetUserNameByID(1234));
ResponseStream.AppendLine('fCustomersService.GetCustomerNameByID(1234) => ' +
fCustomersService.GetCustomerNameByID(1234));
RenderResponseStream;
end;
end.

View File

@ -0,0 +1,29 @@
unit Controller2U;
interface
uses
MVCFramework, MVCFramework.Commons;
type
[MVCPath('/controller2')]
TMyController2 = class(TMVCController)
public
[MVCPath]
[MVCHTTPMethod([httpGET])]
procedure Index;
end;
implementation
uses
System.SysUtils, MVCFramework.Logger, System.StrUtils;
procedure TMyController2.Index;
begin
// use Context property to access to the HTTP request and response
Render('Hello DelphiMVCFramework World');
end;
end.

View File

@ -0,0 +1,81 @@
unit DIConfiguration;
interface
uses
Spring, Spring.Container;
procedure BuildContainer;
function Container: TContainer;
implementation
uses Spring.Container.Common, Controller1U, Service1U, Service2U,
ServicesInterfaceU, Controller2U, Service3U;
var
GContainer: TContainer = nil;
function Container: TContainer;
begin
Result := GContainer;
end;
procedure BuildContainer;
begin
Assert(not Assigned(GContainer), 'Container already built');
GContainer := TContainer.Create;
// Registering controllers
GContainer.RegisterType<TMyController1>;
GContainer.RegisterType<TMyController2>;
// Registering Services
GContainer.RegisterType<TUsersService>.Implements<IUsersService>;
GContainer.RegisterType<TCustomersService>.Implements<ICustomersService>;
// Maybe that the common service must be register as singleton or as singleton per thread
// because must be the same instances between the first and the second service (e.g. DB transaction)
// Transient registration (default)
// GContainer.RegisterType<TCommonService>.Implements<ICommonService>;
// Singleton registration for all thread. WARNING!!! It is shared between HTTP calls.
// GContainer.RegisterType<TCommonService>.Implements<ICommonService>.AsSingleton(TRefCounting.True);
// Singleton per thread registration. WARNING!!! (read below) Shared by all services within the same HTTP call.
// GContainer.RegisterType<TCommonService>.Implements<ICommonService>.AsSingletonPerThread(TRefCounting.True);
{
About "AsSingletonPerThread" Stefan Glienke said:
It might be confusing as people are assuming that the container magically
knows when a thread ends to destroy a singleton per thread. But that is not the case.
In fact it gets created once per threadid. That means even if your thread has
ended and a new one starts later using the same threadid you get the
same object as before.
If you don't use a threadpool where you have the same threads running all the
time performing tasks it is not a good idea to use singleton per thread.
You might use transient then to always create a new instance or - and this
is imo the better solution - use a threadpool which limits the objects
created (and also reduce the creation of thread objects).
Nevertheless singleton per thread instances will always be destroyed
when the container is getting destroyed, not earlier.
This is also not a strange behavior of our container but also Castle Windsor
or Unity. However there is also advice against using it there.
If you are looking more for something like singleton per request I suggest
using transient and making sure that at the start of the request it gets
resolved from the container and then passed around where ever needed (think
about implementing refcounting to your data module!) and dropping it at the
end of the request which makes it getting destroyed due to ref counting.
}
// Build the container
GContainer.Build;
end;
initialization
finalization
GContainer.Free;
end.

View File

@ -0,0 +1,28 @@
unit Service1U;
interface
uses ServicesInterfaceU, Spring.Container.Common;
type
TUsersService = class(TInterfacedObject, IUsersService)
protected
[Inject]
fCommonService: ICommonService;
public
function GetUserNameByID(const ID: Integer): string;
end;
implementation
uses
System.SysUtils;
{ TUsersService }
function TUsersService.GetUserNameByID(const ID: Integer): string;
begin
Result := Format('User #%d (CommonServiceID = %s)', [ID, fCommonService.GetID]);
end;
end.

View File

@ -0,0 +1,29 @@
unit Service2U;
interface
uses
ServicesInterfaceU, Spring.Container.Common;
type
TCustomersService = class(TInterfacedObject, ICustomersService)
protected
[Inject]
fCommonService: ICommonService;
public
function GetCustomerNameByID(const ID: Integer): string;
end;
implementation
uses
System.SysUtils;
{ TCustomersService }
function TCustomersService.GetCustomerNameByID(const ID: Integer): string;
begin
Result := Format('Customer #%d (CommonServiceID = %s)', [ID, fCommonService.GetID]);
end;
end.

View File

@ -0,0 +1,43 @@
unit Service3U;
interface
uses
ServicesInterfaceU;
type
TCommonService = class(TInterfacedObject, ICommonService)
private
FID: string;
public
constructor Create;
destructor Destroy; override;
function GetID: string;
end;
implementation
uses
System.SysUtils, MVCFramework.Logger;
{ TService3 }
constructor TCommonService.Create;
begin
inherited;
LogI('creating ' + ClassName);
FID := Random(1000).ToString;
end;
destructor TCommonService.Destroy;
begin
LogI('destroing ' + ClassName);
inherited;
end;
function TCommonService.GetID: string;
begin
Result := FID;
end;
end.

View File

@ -0,0 +1,23 @@
unit ServicesInterfaceU;
interface
type
IUsersService = interface
['{D54AF728-7688-40DE-B10C-E6D63949531E}']
function GetUserNameByID(const ID: Integer): String;
end;
ICustomersService = interface
['{DC94C34E-13A2-4406-8961-6A407B792DD3}']
function GetCustomerNameByID(const ID: Integer): String;
end;
ICommonService = interface
['{EAA26199-4142-4698-9C17-5D241D9984AA}']
function GetID: String;
end;
implementation
end.

View File

@ -0,0 +1,8 @@
object MyWebModule: TMyWebModule
OldCreateOrder = False
OnCreate = WebModuleCreate
OnDestroy = WebModuleDestroy
Actions = <>
Height = 230
Width = 415
end

View File

@ -0,0 +1,73 @@
unit WebModuleU;
interface
uses System.SysUtils,
System.Classes,
Web.HTTPApp,
MVCFramework;
type
TMyWebModule = class(TWebModule)
procedure WebModuleCreate(Sender: TObject);
procedure WebModuleDestroy(Sender: TObject);
private
FMVC: TMVCEngine;
public
{ Public declarations }
end;
var
WebModuleClass: TComponentClass = TMyWebModule;
implementation
{$R *.dfm}
uses System.IOUtils, MVCFramework.Commons, DIConfiguration, Controller1U,
Controller2U;
procedure TMyWebModule.WebModuleCreate(Sender: TObject);
begin
FMVC := TMVCEngine.Create(Self,
procedure(Config: TMVCConfig)
begin
// enable static files
Config[TMVCConfigKey.DocumentRoot] := TPath.Combine(ExtractFilePath(GetModuleName(HInstance)), 'www');
// session timeout (0 means session cookie)
Config[TMVCConfigKey.SessionTimeout] := '0';
// default content-type
Config[TMVCConfigKey.DefaultContentType] := TMVCConstants.DEFAULT_CONTENT_TYPE;
// default content charset
Config[TMVCConfigKey.DefaultContentCharset] := TMVCConstants.DEFAULT_CONTENT_CHARSET;
// unhandled actions are permitted?
Config[TMVCConfigKey.AllowUnhandledAction] := 'false';
// default view file extension
Config[TMVCConfigKey.DefaultViewFileExtension] := 'html';
// view path
Config[TMVCConfigKey.ViewPath] := 'templates';
// Enable Server Signature in response
Config[TMVCConfigKey.ExposeServerSignature] := 'true';
// Define a default URL for requests that don't map to a route or a file (useful for client side web app)
Config[TMVCConfigKey.FallbackResource] := 'index.html';
end);
FMVC.AddController(TMyController1,
function: TMVCController
begin
Result := Container.Resolve<TMyController1>;
end);
FMVC.AddController(TMyController2,
function: TMVCController
begin
Result := Container.Resolve<TMyController2>;
end);
end;
procedure TMyWebModule.WebModuleDestroy(Sender: TObject);
begin
FMVC.Free;
end;
end.

View File

@ -0,0 +1,117 @@
program spring4dintegration;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
MVCFramework.Logger,
MVCFramework.Commons,
MVCFramework.REPLCommandsHandlerU,
Web.ReqMulti,
Web.WebReq,
Web.WebBroker,
IdHTTPWebBrokerBridge,
Controller1U in 'Controller1U.pas',
WebModuleU in 'WebModuleU.pas' {MyWebModule: TWebModule},
DIConfiguration in 'DIConfiguration.pas',
Controller2U in 'Controller2U.pas',
Service1U in 'Service1U.pas',
Service2U in 'Service2U.pas',
ServicesInterfaceU in 'ServicesInterfaceU.pas',
Service3U in 'Service3U.pas';
{$R *.res}
procedure RunServer(APort: Integer);
var
lServer: TIdHTTPWebBrokerBridge;
lCustomHandler: TMVCCustomREPLCommandsHandler;
lCmd: string;
begin
Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION);
if ParamCount >= 1 then
lCmd := ParamStr(1)
else
lCmd := 'start';
lCustomHandler := function(const Value: string; const Server: TIdHTTPWebBrokerBridge; out Handled: Boolean): THandleCommandResult
begin
Handled := False;
Result := THandleCommandResult.Unknown;
// Write here your custom command for the REPL using the following form...
// ***
// Handled := False;
// if (Value = 'apiversion') then
// begin
// REPLEmit('Print my API version number');
// Result := THandleCommandResult.Continue;
// Handled := True;
// end
// else if (Value = 'datetime') then
// begin
// REPLEmit(DateTimeToStr(Now));
// Result := THandleCommandResult.Continue;
// Handled := True;
// end;
end;
LServer := TIdHTTPWebBrokerBridge.Create(nil);
try
LServer.DefaultPort := APort;
{ more info about MaxConnections
http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdCustomTCPServer_MaxConnections.html }
LServer.MaxConnections := 0;
{ more info about ListenQueue
http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdCustomTCPServer_ListenQueue.html }
LServer.ListenQueue := 200;
WriteLn('Write "quit" or "exit" to shutdown the server');
repeat
if lCmd.IsEmpty then
begin
write('-> ');
ReadLn(lCmd)
end;
try
case HandleCommand(lCmd.ToLower, LServer, lCustomHandler) of
THandleCommandResult.Continue:
begin
Continue;
end;
THandleCommandResult.Break:
begin
Break;
end;
THandleCommandResult.Unknown:
begin
REPLEmit('Unknown command: ' + lCmd);
end;
end;
finally
lCmd := '';
end;
until false;
finally
LServer.Free;
end;
end;
begin
ReportMemoryLeaksOnShutdown := True;
IsMultiThread := True;
try
if WebRequestHandler <> nil then
WebRequestHandler.WebModuleClass := WebModuleClass;
WebRequestHandlerProc.MaxConnections := 1024;
BuildContainer;
RunServer(8080);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

View File

@ -0,0 +1,582 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{6F8DDB74-BFCE-4A2F-AB59-93DF9153A05A}</ProjectGuid>
<ProjectVersion>18.2</ProjectVersion>
<FrameworkType>None</FrameworkType>
<MainSource>spring4dintegration.dpr</MainSource>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Console</AppType>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''">
<Base_Android>true</Base_Android>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='iOSDevice32' and '$(Base)'=='true') or '$(Base_iOSDevice32)'!=''">
<Base_iOSDevice32>true</Base_iOSDevice32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Base)'=='true') or '$(Base_iOSDevice64)'!=''">
<Base_iOSDevice64>true</Base_iOSDevice64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='iOSSimulator' and '$(Base)'=='true') or '$(Base_iOSSimulator)'!=''">
<Base_iOSSimulator>true</Base_iOSSimulator>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Linux64' and '$(Base)'=='true') or '$(Base_Linux64)'!=''">
<Base_Linux64>true</Base_Linux64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='OSX32' and '$(Base)'=='true') or '$(Base_OSX32)'!=''">
<Base_OSX32>true</Base_OSX32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
<Base_Win32>true</Base_Win32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
<Base_Win64>true</Base_Win64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
<Cfg_1_Win32>true</Cfg_1_Win32>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
<DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
<DCC_E>false</DCC_E>
<DCC_N>false</DCC_N>
<DCC_S>false</DCC_S>
<DCC_F>false</DCC_F>
<DCC_K>false</DCC_K>
<DCC_UsePackage>RESTComponents;emsclientfiredac;DataSnapFireDAC;FireDACIBDriver;emsclient;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
<UsingDelphiRTL>true</UsingDelphiRTL>
<Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
<Icns_MainIcns>$(BDS)\bin\delphi_PROJECTICNS.icns</Icns_MainIcns>
<DCC_UnitSearchPath>$(DMVC);$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
<DCC_Framework>VCL;$(DCC_Framework)</DCC_Framework>
<SanitizedProjectName>spring4dintegration</SanitizedProjectName>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Android)'!=''">
<DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
<EnabledSysJars>android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar</EnabledSysJars>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_iOSDevice32)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_iOSDevice64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_iOSSimulator)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Linux64)'!=''">
<DCC_UsePackage>FireDACADSDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;Spring.Data;inetdb;emsedge;dbexpress;IndyCore;dsnap;DataSnapCommon;DataSnapConnectors;bindengine;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;DataSnapClient;IndySystem;FireDACDb2Driver;FireDACInfxDriver;emshosting;FireDACPgDriver;FireDACASADriver;FireDACTDataDriver;DbxCommonDriver;DataSnapServer;xmlrtl;DataSnapNativeClient;rtl;DbxClientDriver;CustomIPTransport;bindcomp;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;dbrtl;IndyProtocols;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_OSX32)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;FireDACMSSQLDriver;bindcompfmx;DBXOracleDriver;Spring.Data;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;bindcomp;DBXInformixDriver;IndyIPClient;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;svnui;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;Spring.Data;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;FixInsight_10_2;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;TelegaPiBot;dsnapcon;DMVC_IDE_Expert_D102Tokyo;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;JSPack_Tokyo;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;Spring.Data;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
<DCC_DebugDCUs>true</DCC_DebugDCUs>
<DCC_Optimize>false</DCC_Optimize>
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<DCC_RemoteDebug>true</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<DCC_RemoteDebug>false</DCC_RemoteDebug>
<DCC_ExeOutput>.\bin</DCC_ExeOutput>
<VerInfo_Locale>1033</VerInfo_Locale>
<Manifest_File>(None)</Manifest_File>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
<DCC_DebugInformation>0</DCC_DebugInformation>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
<MainSource>MainSource</MainSource>
</DelphiCompile>
<DCCReference Include="Controller1U.pas"/>
<DCCReference Include="WebModuleU.pas">
<Form>MyWebModule</Form>
<FormType>dfm</FormType>
<DesignClass>TWebModule</DesignClass>
</DCCReference>
<DCCReference Include="DIConfiguration.pas"/>
<DCCReference Include="Controller2U.pas"/>
<DCCReference Include="Service1U.pas"/>
<DCCReference Include="Service2U.pas"/>
<DCCReference Include="ServicesInterfaceU.pas"/>
<DCCReference Include="Service3U.pas"/>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
</ItemGroup>
<ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
<Borland.ProjectType>Console</Borland.ProjectType>
<BorlandProject>
<Delphi.Personality>
<Source>
<Source Name="MainSource">spring4dintegration.dpr</Source>
</Source>
<Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcboffice2k250.bpl">Embarcadero C++Builder Office 2000 Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\bcbofficexp250.bpl">Embarcadero C++Builder Office XP Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k250.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp250.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
<Platform Name="OSX32">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule">
<Platform Name="OSX32">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="bin\spring4dintegration.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>spring4dintegration.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidClassesDexFile">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeMipsFile">
<Platform Name="Android">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashImageDef">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon144">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage426">
<Platform Name="Android">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage470">
<Platform Name="Android">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage640">
<Platform Name="Android">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage960">
<Platform Name="Android">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyFramework">
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyModule">
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="DependencyPackage">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Name="File">
<Platform Name="Android">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>0</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>0</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1024">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1536">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640x1136">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceResourceRules"/>
<DeployClass Name="ProjectiOSEntitlements"/>
<DeployClass Name="ProjectiOSInfoPList"/>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXEntitlements"/>
<DeployClass Name="ProjectOSXInfoPList"/>
<DeployClass Name="ProjectOSXResource">
<Platform Name="OSX32">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="ProjectOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo150">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo44">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
</Deployment>
<Platforms>
<Platform value="Android">False</Platform>
<Platform value="iOSDevice32">False</Platform>
<Platform value="iOSDevice64">False</Platform>
<Platform value="iOSSimulator">False</Platform>
<Platform value="Linux64">False</Platform>
<Platform value="OSX32">False</Platform>
<Platform value="Win32">True</Platform>
<Platform value="Win64">False</Platform>
</Platforms>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
<Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
</Project>

View File

@ -0,0 +1,130 @@
unit MVCFramework.Console;
interface
type
TConsoleMode = (Normal, Bright);
TConsoleColor = (
Black = 30,
Red = 31,
Green = 32,
Yellow = 33,
Blue = 34,
Magenta = 35,
Cyan = 36,
White = 37);
procedure ResetConsole;
procedure TextColor(const Color: TConsoleColor);
procedure TextBackground(const Color: TConsoleColor);
procedure SetMode(const ConsoleMode: TConsoleMode);
implementation
uses
{$IFDEF MSWINDOWS}
WinApi.Windows,
{$ENDIF}
System.SysUtils;
const
ESC = Chr(27);
var
GForeGround: TConsoleColor;
GBackGround: TConsoleColor;
GMode: TConsoleMode = TConsolemode.Normal;
function ToBackGround(const ForeGround: Byte): Byte;
begin
if (GMode = TConsoleMode.Bright) and (ForeGround <> Byte(TConsoleColor.Black)) then
begin
Result := ForeGround + 10 + 60;
end
else
begin
Result := ForeGround + 10;
end;
end;
{$IFDEF LINUX}
procedure EnableVirtualTerminalProcessing; inline;
begin
// do nothing
end;
{$ELSE}
procedure EnableVirtualTerminalProcessing; inline;
const
ENABLE_VIRTUAL_TERMINAL_PROCESSING = $0004;
var
hOut: THandle;
dwMode: UInt32;
begin
hOut := GetStdHandle(STD_OUTPUT_HANDLE);
if hOut = INVALID_HANDLE_VALUE then
raise Exception.CreateFmt('GetLastError() = %d', [GetLastError]);
dwMode := 0;
if (not GetConsoleMode(hOut, &dwMode)) then
raise Exception.CreateFmt('GetLastError() = %d', [GetLastError]);
dwMode := dwMode or ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (not SetConsoleMode(hOut, dwMode)) then
raise Exception.CreateFmt('GetLastError() = %d', [GetLastError]);
end;
{$ENDIF}
procedure ResetConsole;
begin
write(ESC + '[0m');
end;
function GetColorString: string;
begin
if GMode = TConsoleMode.Bright then
Result := Format('[%d;1;%dm', [Byte(GForeGround), ToBackGround(Byte(GBackGround))])
else
Result := Format('[%d;%dm', [Byte(GForeGround), ToBackGround(Byte(GBackGround))]);
end;
procedure TextColor(const Color: TConsoleColor);
begin
GForeGround := Color;
write(ESC + GetColorString);
end;
procedure TextBackground(const Color: TConsoleColor);
begin
GBackGround := Color;
write(ESC + GetColorString);
end;
procedure SetMode(const ConsoleMode: TConsoleMode);
begin
GMode := ConsoleMode;
end;
procedure InitDefault;
begin
GForeGround := TConsoleColor.White;
GBackGround := TConsoleColor.Black;
end;
initialization
EnableVirtualTerminalProcessing;
InitDefault;
finalization
end.

View File

@ -610,6 +610,8 @@ var
lIsRegistered: Boolean; lIsRegistered: Boolean;
lValue: string; lValue: string;
begin begin
lJHeader := nil;
lJPayload := nil;
Result := IsValidToken(Token, lJHeader, lJPayload, Error); Result := IsValidToken(Token, lJHeader, lJPayload, Error);
try try
if not Result then if not Result then

View File

@ -27,9 +27,26 @@ procedure TCompressionMiddleware.OnAfterControllerAction(Context: TWebContext;
var var
lMemStream: TMemoryStream; lMemStream: TMemoryStream;
lContentStream: TStream; lContentStream: TStream;
lAcceptEncoding: string;
lEncodings: TArray<string>;
lItem: string;
lFound: Boolean;
begin begin
{ TODO -oDaniele -cGeneral : It doesn0t work! } lAcceptEncoding := Context.Request.Headers['Accept-Encoding'].ToLower.Trim;
if Context.Request.Headers['Accept-Encoding'].Trim.ToLower <> 'deflate' then if lAcceptEncoding.IsEmpty then
Exit;
lFound := False;
lEncodings := lAcceptEncoding.Split([',']);
for lItem in lEncodings do
begin
if lItem.Trim = 'deflate' then
begin
lFound := True;
Break;
end;
end;
if not lFound then
Exit; Exit;
lContentStream := Context.Response.RawWebResponse.ContentStream; lContentStream := Context.Response.RawWebResponse.ContentStream;

View File

@ -10,26 +10,26 @@ type
{$SCOPEDENUMS ON} {$SCOPEDENUMS ON}
THandleCommandResult = (Continue, Break, Unknown); THandleCommandResult = (Continue, Break, Unknown);
TMVCCustomREPLCommandsHandler = reference to function(const Value: String; const Server: TIdHTTPWebBrokerBridge; out Handled: Boolean): THandleCommandResult; TMVCCustomREPLCommandsHandler = reference to function(const Value: string; const Server: TIdHTTPWebBrokerBridge; out Handled: Boolean): THandleCommandResult;
function HandleCommand(const Value: String; const Server: TIdHTTPWebBrokerBridge; const CustomCommandsHandler: TMVCCustomREPLCommandsHandler = nil): THandleCommandResult; function HandleCommand(const Value: string; const Server: TIdHTTPWebBrokerBridge; const CustomCommandsHandler: TMVCCustomREPLCommandsHandler = nil): THandleCommandResult;
procedure REPLEmit(const Value: String); procedure REPLEmit(const Value: string);
implementation implementation
uses uses
System.SysUtils, MVCFramework.Commons; System.SysUtils, MVCFramework.Commons, MVCFramework.Logger;
procedure REPLEmit(const Value: String); procedure REPLEmit(const Value: string);
begin begin
// TextColor(LightGreen); // TextColor(LightGreen);
Write('#> '); write('#> ');
// TextColor(White); // TextColor(White);
WriteLn(Value); WriteLn(Value);
// TextColor(White); // TextColor(White);
end; end;
function HandleCommand(const Value: String; const Server: TIdHTTPWebBrokerBridge; const CustomCommandsHandler: TMVCCustomREPLCommandsHandler): THandleCommandResult; function HandleCommand(const Value: string; const Server: TIdHTTPWebBrokerBridge; const CustomCommandsHandler: TMVCCustomREPLCommandsHandler): THandleCommandResult;
var var
lTempCommandResult: THandleCommandResult; lTempCommandResult: THandleCommandResult;
lHandled: Boolean; lHandled: Boolean;
@ -77,6 +77,7 @@ begin
begin begin
REPLEmit(Format('Starting server on port %d...', [Server.Bindings.DefaultPort])); REPLEmit(Format('Starting server on port %d...', [Server.Bindings.DefaultPort]));
Server.Active := True; Server.Active := True;
LogI('Server started on port ' + Server.Bindings.DefaultPort.ToString);
REPLEmit('done!'); REPLEmit('done!');
end; end;
Result := THandleCommandResult.Continue; Result := THandleCommandResult.Continue;

View File

@ -63,7 +63,7 @@ uses
{$ENDIF} {$ENDIF}
// Delphi XE4 (all update) and XE5 (with no update) dont contains this unit. Look for the bug in QC // Delphi XE4 (all update) and XE5 (with no update) don't contains this unit. Look for the bug in QC
// https://quality.embarcadero.com/browse/RSP-17216 // https://quality.embarcadero.com/browse/RSP-17216
{$IFNDEF VER320} {$IFNDEF VER320}
@ -716,8 +716,6 @@ type
property Output: string read FOutput; property Output: string read FOutput;
end; end;
function IsShuttingDown: Boolean; function IsShuttingDown: Boolean;
procedure EnterInShutdownState; procedure EnterInShutdownState;
@ -1610,6 +1608,7 @@ constructor TMVCEngine.Create(
begin begin
inherited Create(AWebModule); inherited Create(AWebModule);
FWebModule := AWebModule; FWebModule := AWebModule;
FixUpWebModule;
FConfig := TMVCConfig.Create; FConfig := TMVCConfig.Create;
FSerializers := TDictionary<string, IMVCSerializer>.Create; FSerializers := TDictionary<string, IMVCSerializer>.Create;
FMiddlewares := TList<IMVCMiddleware>.Create; FMiddlewares := TList<IMVCMiddleware>.Create;
@ -1621,7 +1620,6 @@ begin
WebRequestHandler.CacheConnections := True; WebRequestHandler.CacheConnections := True;
WebRequestHandler.MaxConnections := 4096; WebRequestHandler.MaxConnections := 4096;
FixUpWebModule;
MVCFramework.Logger.SetDefaultLogger(ACustomLogger); MVCFramework.Logger.SetDefaultLogger(ACustomLogger);
ConfigDefaultValues; ConfigDefaultValues;
@ -2041,8 +2039,12 @@ end;
procedure TMVCEngine.OnBeforeDispatch(ASender: TObject; ARequest: TWebRequest; AResponse: TWebResponse; var AHandled: Boolean); procedure TMVCEngine.OnBeforeDispatch(ASender: TObject; ARequest: TWebRequest; AResponse: TWebResponse; var AHandled: Boolean);
begin begin
AHandled := False; AHandled := False;
if Assigned(FSavedOnBeforeDispatch) then { there is a bug in WebBroker Linux on 10.2.1 tokyo }
FSavedOnBeforeDispatch(ASender, ARequest, AResponse, AHandled); // if Assigned(FSavedOnBeforeDispatch) then
// begin
// FSavedOnBeforeDispatch(ASender, ARequest, AResponse, AHandled);
// end;
if not AHandled then if not AHandled then
begin begin
try try

View File

@ -4,7 +4,7 @@
<ProjectVersion>18.2</ProjectVersion> <ProjectVersion>18.2</ProjectVersion>
<FrameworkType>VCL</FrameworkType> <FrameworkType>VCL</FrameworkType>
<Base>True</Base> <Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config> <Config Condition="'$(Config)'==''">SERVER_ON_LINUX</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform> <Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms> <TargetedPlatforms>1</TargetedPlatforms>
<AppType>Console</AppType> <AppType>Console</AppType>
@ -637,6 +637,7 @@
<TestProjectName/> <TestProjectName/>
<SourceProjectName/> <SourceProjectName/>
</UnitTesting> </UnitTesting>
<ModelSupport>False</ModelSupport>
</BorlandProject> </BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion> <ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions> </ProjectExtensions>

View File

@ -75,8 +75,8 @@ begin
lReq.Method := 'subtract'; lReq.Method := 'subtract';
lReq.Params.Add(42); lReq.Params.Add(42);
lReq.Params.Add(23); lReq.Params.Add(23);
lReq.ID := 1; lReq.RequestID := 1;
Assert.AreEqual(1, lReq.ID.AsInteger); Assert.AreEqual(1, lReq.RequestID.AsInteger);
Assert.AreEqual(42, lReq.Params[0].AsInteger); Assert.AreEqual(42, lReq.Params[0].AsInteger);
Assert.AreEqual(23, lReq.Params[1].AsInteger); Assert.AreEqual(23, lReq.Params[1].AsInteger);
Assert.AreEqual('subtract', lReq.Method); Assert.AreEqual('subtract', lReq.Method);
@ -109,7 +109,7 @@ begin
lReq := TJSONRPCRequest.Create; lReq := TJSONRPCRequest.Create;
try try
lReq.AsJSONString := '{"jsonrpc": "2.0", "method": "subtract", "id": 1}'; lReq.AsJSONString := '{"jsonrpc": "2.0", "method": "subtract", "id": 1}';
Assert.AreEqual(1, lReq.ID.AsInteger); Assert.AreEqual(1, lReq.RequestID.AsInteger);
Assert.AreEqual(0, lReq.Params.Count); Assert.AreEqual(0, lReq.Params.Count);
Assert.AreEqual('subtract', lReq.Method); Assert.AreEqual('subtract', lReq.Method);
Assert.AreEqual(TJSONRPCRequestType.Request, lReq.RequestType); Assert.AreEqual(TJSONRPCRequestType.Request, lReq.RequestType);

View File

@ -35,7 +35,7 @@ const
{$IFDEF LINUX_SERVER} {$IFDEF LINUX_SERVER}
TEST_SERVER_ADDRESS = '192.168.3.88'; TEST_SERVER_ADDRESS = '192.168.1.8';
{$ELSE} {$ELSE}
@ -891,7 +891,7 @@ var
begin begin
res := RESTClient res := RESTClient
.Accept(TMVCMediaType.TEXT_PLAIN) .Accept(TMVCMediaType.TEXT_PLAIN)
.ContentType(CreateContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591)) .ContentType(BuildContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591))
.doPOST('/testconsumes/textiso8859_1', [], .doPOST('/testconsumes/textiso8859_1', [],
'àèéìòù'); 'àèéìòù');
Assert.areEqual<Integer>(HTTP_STATUS.OK, res.ResponseCode); Assert.areEqual<Integer>(HTTP_STATUS.OK, res.ResponseCode);
@ -901,7 +901,7 @@ begin
res := RESTClient res := RESTClient
.Accept(TMVCMediaType.TEXT_PLAIN) .Accept(TMVCMediaType.TEXT_PLAIN)
.ContentType(CreateContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591)) .ContentType(BuildContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591))
.doPOST('/testconsumes/textiso8859_1', [], .doPOST('/testconsumes/textiso8859_1', [],
'this is an iso8859-1 text'); 'this is an iso8859-1 text');
Assert.areEqual<Integer>(HTTP_STATUS.OK, res.ResponseCode); Assert.areEqual<Integer>(HTTP_STATUS.OK, res.ResponseCode);
@ -1246,7 +1246,7 @@ var
begin begin
lReq := TJSONRPCRequest.Create; lReq := TJSONRPCRequest.Create;
try try
lReq.ID := 1234; lReq.RequestID := 1234;
lReq.Method := 'subtract'; lReq.Method := 'subtract';
lReq.Params.Add(18); lReq.Params.Add(18);
lReq.Params.Add(8); lReq.Params.Add(8);
@ -1260,7 +1260,7 @@ begin
try try
lResp.AsJSONString := lHttpResp.BodyAsString; lResp.AsJSONString := lHttpResp.BodyAsString;
Assert.AreEqual(10, lResp.Result.AsInteger); Assert.AreEqual(10, lResp.Result.AsInteger);
Assert.AreEqual(1234, lResp.ID.AsInteger); Assert.AreEqual(1234, lResp.RequestID.AsInteger);
finally finally
lResp.Free; lResp.Free;
end; end;

View File

@ -7,11 +7,16 @@ uses
System.SysUtils, System.SysUtils,
IdHTTPWebBrokerBridge, IdHTTPWebBrokerBridge,
Web.WebReq, Web.WebReq,
{$IFNDEF LINUX} {$IFNDEF LINUX}
Winapi.Windows, Winapi.Windows,
{$ENDIF } {$ENDIF }
Web.WebBroker, Web.WebBroker,
MVCFramework.Commons, MVCFramework.Commons,
MVCFramework.Console,
WebModuleUnit in 'WebModuleUnit.pas' {bas: TWebModule} , WebModuleUnit in 'WebModuleUnit.pas' {bas: TWebModule} ,
TestServerControllerU in 'TestServerControllerU.pas', TestServerControllerU in 'TestServerControllerU.pas',
TestServerControllerExceptionU in 'TestServerControllerExceptionU.pas', TestServerControllerExceptionU in 'TestServerControllerExceptionU.pas',
@ -28,13 +33,9 @@ uses
procedure Logo; procedure Logo;
begin begin
SetMode(TConsoleMode.Bright);
{$IFNDEF LINUX} TextBackground(TConsoleColor.Black);
TextColor(TConsoleColor.Red);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED or FOREGROUND_INTENSITY);
{$ENDIF}
WriteLn(' ██████╗ ███╗ ███╗██╗ ██╗ ██████╗ ███████╗███████╗██████╗ ██╗ ██╗███████╗██████╗'); WriteLn(' ██████╗ ███╗ ███╗██╗ ██╗ ██████╗ ███████╗███████╗██████╗ ██╗ ██╗███████╗██████╗');
WriteLn(' ██╔══██╗████╗ ████║██║ ██║██╔════╝ ██╔════╝██╔════╝██╔══██╗██║ ██║██╔════╝██╔══██╗'); WriteLn(' ██╔══██╗████╗ ████║██║ ██║██╔════╝ ██╔════╝██╔════╝██╔══██╗██║ ██║██╔════╝██╔══██╗');
WriteLn(' ██║ ██║██╔████╔██║██║ ██║██║ ███████╗█████╗ ██████╔╝██║ ██║█████╗ ██████╔╝'); WriteLn(' ██║ ██║██╔████╔██║██║ ██║██║ ███████╗█████╗ ██████╔╝██║ ██║█████╗ ██████╔╝');
@ -42,22 +43,9 @@ begin
WriteLn(' ██████╔╝██║ ╚═╝ ██║ ╚████╔╝ ╚██████╗ ███████║███████╗██║ ██║ ╚████╔╝ ███████╗██║ ██║'); WriteLn(' ██████╔╝██║ ╚═╝ ██║ ╚████╔╝ ╚██████╗ ███████║███████╗██║ ██║ ╚████╔╝ ███████╗██║ ██║');
WriteLn(' ╚═════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝'); WriteLn(' ╚═════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝');
WriteLn(' '); WriteLn(' ');
TextColor(TConsoleColor.Yellow);
{$IFNDEF LINUX}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY);
{$ENDIF}
WriteLn('DMVCFRAMEWORK VERSION: ', DMVCFRAMEWORK_VERSION); WriteLn('DMVCFRAMEWORK VERSION: ', DMVCFRAMEWORK_VERSION);
TextColor(TConsoleColor.White);
{$IFNDEF LINUX}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE or FOREGROUND_GREEN or
FOREGROUND_RED);
{$ENDIF}
end; end;
procedure RunServer(APort: Integer); procedure RunServer(APort: Integer);

View File

@ -344,7 +344,7 @@ procedure TTestServerController.TestCharset(ctx: TWebContext);
var var
Obj: TJSONObject; Obj: TJSONObject;
begin begin
ContentType := CreateContentType(TMVCMediaType.APPLICATION_JSON, TMVCCharset.UTF_8); ContentType := BuildContentType(TMVCMediaType.APPLICATION_JSON, TMVCCharset.UTF_8);
Obj := TJSONObject.Create; Obj := TJSONObject.Create;
Obj.AddPair('name1', 'jørn'); Obj.AddPair('name1', 'jørn');
Obj.AddPair('name2', 'Što je Unicode?'); Obj.AddPair('name2', 'Što je Unicode?');