AppType=StandardJava
Build1=Default,b4j.webapi
File1=index.html
File2=main.html
FileGroup1=Default Group
FileGroup2=Default Group
Group=Default Group
Library1=byteconverter
Library2=jcore
Library3=jserver
Library4=json
Library5=jsql
Library6=javaobject
Module1=CorsFilter
Module2=DataUtils
Module3=DefaultHandler
Module4=HomeHandler
Module5=HttpsFilter
Module6=ProductHandler
Module7=Utility
Module8=WebUtils
NumberOfFiles=2
NumberOfLibraries=6
NumberOfModules=8
Version=9.1
@EndOfDesignText@
' Name: 		Web API Lite
' Description: 	Non-UI application (console / server application)
' Version: 		1.08

#Region Project Attributes 
	#CommandLineArgs:
	#MergeLibraries: True 
#End Region

#Region AdditionalJar
' MySQL connector
'#AdditionalJar: mysql-connector-java-5.1.49-bin
' SQLite connector
#AdditionalJar: sqlite-jdbc-3.36.0.2
#End Region

Sub Process_Globals
	Public const VERSION As Float = 1.08
	Public srvr As Server
	Public ROOT_PATH As String
	Public ROOT_URL As String
	Public SERVER_PORT As Int
	Public SSL_PORT As Int
	Public config As Map
	Public queries As Map
	Public Conn As Conn
	Public Element As Element
	Type Conn (DbName As String, DbType As String, DriverClass As String, JdbcUrl As String, User As String, Password As String, MaxPoolSize As Int)
	Type Element (Root As Int, Parent As Int, Parent_Id As Int, Child As Int, Child_Id As Int, Max_Elements As Int)
End Sub

Sub AppStart (Args() As String)
	config = Utility.ReadMapFile(File.DirApp, "config.ini")
	If config.Get("DbType").As(String).EqualsIgnoreCase("mysql") Then
		queries = Utility.ReadMapFile(File.DirApp, "queries-mysql.ini")
	End If
	If config.Get("DbType").As(String).EqualsIgnoreCase("sqlite") Then
		queries = Utility.ReadMapFile(File.DirApp, "queries-sqlite.ini")
	End If
	
	ROOT_PATH = config.Get("ROOT_PATH")
	ROOT_URL = config.Get("ROOT_URL")
	SERVER_PORT = config.Get("ServerPort")
	SSL_PORT = config.Get("SSLPort") : If IsNumber(SSL_PORT) = False Then SSL_PORT = 0
	
	If SERVER_PORT = 0 Then
		Log($"Server Port is not set!"$)
		Log($"Application is terminated."$)
		ExitApplication
	End If
	ROOT_URL = ROOT_URL & ":" & SERVER_PORT
	
	srvr.Initialize("")
	srvr.Port = SERVER_PORT
	
	If SSL_PORT > 0 Then
		ConfigureSSL(SSL_PORT)
		ROOT_URL = config.Get("ROOT_URL") & ":" & SSL_PORT
	End If
	' Update ROOT URL
	config.Put("ROOT_URL", ROOT_URL)
	config.Put("VERSION", VERSION)
	
	Conn.Initialize
	Conn.DbName = config.Get("DbName")
	Conn.DbType = config.Get("DbType")
	Conn.DriverClass = config.Get("DriverClass")
	Conn.JdbcUrl = config.Get("JdbcUrl")
	If Conn.DbType.EqualsIgnoreCase("mysql") Then
		Conn.User = config.Get("User")
		Conn.Password = config.Get("Password")
		Conn.MaxPoolSize = config.Get("MaxPoolSize")
	End If	
	
	' Check if database exists
	DataUtils.CreateDatabaseIfNotExist

	Element.Initialize
	If ROOT_PATH <> "/" Then ' If webroot is using subdirectory
		srvr.AddHandler(ROOT_PATH, "HomeHandler", False)
		Element.Root = 1
		Element.Parent = 2
		Element.Parent_Id = 3
		Element.Child = 4
		Element.Child_Id = 5
		Element.Max_Elements = 6
	Else
		Element.Root = 0
		Element.Parent = 1
		Element.Parent_Id = 2
		Element.Child = 3
		Element.Child_Id = 4
		Element.Max_Elements = 5
	End If
	
	srvr.StaticFilesFolder = File.Combine(File.DirApp, "www")
	srvr.SetStaticFilesOptions(CreateMap("dirAllowed": False))
	
	' Add a home page
	srvr.AddHandler("", "HomeHandler", False)
	
	' Add more handlers here
	srvr.AddHandler(ROOT_PATH & "default/*", "DefaultHandler", False)
	srvr.AddHandler(ROOT_PATH & "category/*", "ProductHandler", False)
	
	' Add CrossOriginFilter
	'ConfigureCORS("/*", "*", "*", "*")
	'ConfigureCORS(ROOT_PATH & "category/*", "http://127.0.0.1:19800", "", "") ' test.html
	ConfigureCORS(ROOT_PATH & "category/*", "*", "", "")
	
	' Server starts
	srvr.Start
	
	Log($"Web API server (version = $1.2{VERSION}) is running on port ${srvr.Port}"$)
	Log($"Open the following URL from your web browser"$)
	Log(ROOT_URL & ROOT_PATH)
	' Open a web browser and navigate to: http://127.0.0.1:19800/v1/
	StartMessageLoop
End Sub

Public Sub OpenConnection (pool As ConnectionPool) As ConnectionPool
	Try
		pool.Initialize(Conn.DriverClass, Conn.JdbcUrl, Conn.User, Conn.Password)
		
		Dim jo As JavaObject = pool
		jo.RunMethod("setMaxPoolSize", Array(Conn.MaxPoolSize))
	Catch
		LogDebug(LastException)
	End Try
	Return pool
End Sub

Public Sub OpenSQLiteDB As SQL
	Dim DB As SQL
	DB.InitializeSQLite(File.DirApp, Conn.DbName, False)
	Return DB
End Sub

#Region ConfigureSSL
Private Sub ConfigureSSL (SslPort As Int)
	Dim KeyStoreDir As String = config.Get("SSL_KEYSTORE_DIR")
	Dim KeyStoreFile As String = config.Get("SSL_KEYSTORE_FILE")
	Dim KeyStorePassword As String = config.Get("SSL_KEYSTORE_PASSWORD")
	Dim ssl As SslConfiguration
	ssl.Initialize
	ssl.SetKeyStorePath(KeyStoreDir, KeyStoreFile)
	ssl.KeyStorePassword = KeyStorePassword
	'ssl.KeyManagerPassword = ""
	srvr.SetSslConfiguration(ssl, SslPort)
	'add filter to redirect all traffic from http to https (optional)
	srvr.AddFilter("/*", "HttpsFilter", False)
End Sub
#End Region

#Region ConfigureCORS
	' allowedOrigins = "*" or "http://google.com"
	' allowedMethods = "*" or "GET,POST,HEAD"
	' allowedHeaders = "*" or "X-Requested-With,Content-Type,Accept,Origin"
Private Sub ConfigureCORS (Path As String, allowedOrigins As String, allowedMethods As String, allowedHeaders As String)
	' Reference: https://www.b4x.com/android/forum/threads/jetty-cross-origin-filter-to-be-added-to-jserver-library.85641/
	Dim cors As CorsFilter
	cors.Initialize(Path, CreateMap("allowedOrigins": allowedOrigins, _
	"allowedMethods": allowedMethods, _
	"allowedHeaders": allowedHeaders, _
	"allowCredentials": "true", _
	"preflightMaxAge": 1800, _
	"chainPreflight": "false"))
	cors.AddToServer(srvr)
End Sub
#End Region