455 lines
17 KiB
VB.net
455 lines
17 KiB
VB.net
Imports DigitalData.Modules.Database
|
|
Imports DigitalData.Modules.Logging
|
|
Imports DigitalData.Modules.Filesystem
|
|
Imports DigitalData.Modules
|
|
Imports System.IO
|
|
Imports System.ServiceModel
|
|
Imports System.Data.SqlClient
|
|
|
|
<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)>
|
|
Public Class EDMIService
|
|
Implements IEDMIService
|
|
|
|
Public Shared LogConfig As LogConfig
|
|
Public Shared MSSQL As MSSQLServer
|
|
Public Shared Firebird As Firebird
|
|
Public Shared AppConfig As AppConfig
|
|
Public Shared Filesystem As Filesystem.File
|
|
Public Shared EDMIArchive As EDMI.File.Archive
|
|
Public Shared GlobalState As GlobalState
|
|
|
|
Private ReadOnly _logger As Logger
|
|
|
|
Private _request As Request = Nothing
|
|
Private _debug As Boolean = False
|
|
Private _username As String
|
|
|
|
|
|
Public Sub New()
|
|
Dim oOperationContext As OperationContext = OperationContext.Current
|
|
Dim oInstanceContext As InstanceContext = oOperationContext.InstanceContext
|
|
Dim oUsername = StripDomainFromUsername(oOperationContext.ServiceSecurityContext.WindowsIdentity.Name)
|
|
|
|
_username = oUsername
|
|
_logger = LogConfig.GetLogger()
|
|
_logger.Debug("New Request by User [{0}]", _username)
|
|
|
|
|
|
End Sub
|
|
|
|
Public Function StripDomainFromUsername(UserName As String)
|
|
If UserName.Contains("\") Then
|
|
Return UserName.Split("\")(1)
|
|
ElseIf UserName.Contains("@") Then
|
|
Return UserName.Split("@")(0)
|
|
Else
|
|
Return UserName
|
|
End If
|
|
End Function
|
|
|
|
#Region "Auth"
|
|
Private Function TestUserAuth() As Boolean
|
|
Try
|
|
'Dim oSQL As String = $"SELECT FNIDB_AUTH_USER('{_username}') FROM RDB$DATABASE;"
|
|
'Dim oResult As Boolean = Database.GetScalarValue(oSQL)
|
|
'Return oResult
|
|
Return True
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
Return False
|
|
End Try
|
|
End Function
|
|
#End Region
|
|
#Region "Heartbeat"
|
|
Public Function Heartbeat() As Boolean Implements IEDMIService.Heartbeat
|
|
Return True
|
|
End Function
|
|
#End Region
|
|
#Region "Request"
|
|
Public Sub CreateRequest(Name As String, Optional Debug As Boolean = False)
|
|
_request = New Request(Name, _username, Firebird, Debug)
|
|
_debug = Debug
|
|
|
|
_logger.Info("Creating request {0}/{1}", _request.Name, _request.RequestId)
|
|
End Sub
|
|
|
|
Public Function CreateDatabaseRequest(Name As String, Optional Debug As Boolean = False) As String Implements IEDMIService.CreateDatabaseRequest
|
|
CreateRequest(Name, Debug)
|
|
|
|
Return _request.Name
|
|
End Function
|
|
|
|
Public Sub CloseDatabaseRequest() Implements IEDMIService.CloseDatabaseRequest
|
|
If IsNothing(_request) Then
|
|
Exit Sub
|
|
End If
|
|
|
|
_logger.Info("Closing request {0}", _request.ToString)
|
|
_request.Connection.Close()
|
|
_request = Nothing
|
|
End Sub
|
|
|
|
#End Region
|
|
#Region "Database"
|
|
Private Sub TestRequestCreated()
|
|
If IsNothing(_request) Then
|
|
Throw New Exceptions.NoRequestException()
|
|
End If
|
|
End Sub
|
|
|
|
Public Function ReturnDatatable(SQL As String) As TableResult Implements IEDMIService.ReturnDatatable
|
|
Try
|
|
TestRequestCreated()
|
|
|
|
_logger.Info($"ReturnDatatable, SQL: {SQL}")
|
|
_request.LogDebug($"ReturnDatatable, SQL: {SQL}")
|
|
|
|
Dim oResult As DataTable = Firebird.GetDatatableWithConnection(SQL, _request.Connection)
|
|
Return New TableResult(oResult)
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
_request.LogError(ex.Message)
|
|
Return New TableResult(ex.Message)
|
|
End Try
|
|
End Function
|
|
|
|
Public Function ReturnScalar(SQL As String) As ScalarResult Implements IEDMIService.ReturnScalar
|
|
Try
|
|
TestRequestCreated()
|
|
|
|
_logger.Info($"ReturnScalar, SQL: {SQL}")
|
|
_request.LogDebug($"ReturnScalar, SQL: {SQL}")
|
|
|
|
Dim oResult As Object = Firebird.GetScalarValueWithConnection(SQL, _request.Connection)
|
|
Return New ScalarResult(oResult)
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
_request.LogError(ex.Message)
|
|
Return New ScalarResult(ex.Message)
|
|
End Try
|
|
End Function
|
|
|
|
Public Function ExecuteNonQuery(SQL As String) As NonQueryResult Implements IEDMIService.ExecuteNonQuery
|
|
Try
|
|
TestRequestCreated()
|
|
|
|
_logger.Info($"ExecuteNonQuery, SQL: {SQL}")
|
|
_request.LogDebug($"ExecuteNonQuery, SQL: {SQL}")
|
|
|
|
Dim oResult As Boolean = Firebird.ExecuteNonQueryWithConnection(SQL, _request.Connection)
|
|
Return New NonQueryResult()
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
_request.LogError(ex.Message)
|
|
Return New NonQueryResult(ex.Message)
|
|
End Try
|
|
End Function
|
|
|
|
|
|
#End Region
|
|
#Region "Document (with FileContainer)"
|
|
Public Function NewFile(FileName As String, Contents() As Byte) As DocumentResultOld Implements IEDMIService.NewFile
|
|
Try
|
|
Dim oContainer As FileContainer
|
|
Dim oContainerId As String
|
|
|
|
If Not TestUserAuth() Then
|
|
Throw New Exception($"User {_username} not authorized.")
|
|
End If
|
|
|
|
oContainer = FileContainer.Create(LogConfig, AppConfig.ContainerPassword)
|
|
oContainerId = oContainer.ContainerId
|
|
_logger.Debug("Container created with id {0}", oContainerId)
|
|
|
|
Dim oExtension As String = Path.GetExtension(FileName).Substring(1)
|
|
_logger.Debug("File extension of file {0} is {1}", FileName, oExtension)
|
|
|
|
Dim oSQL = $"SELECT FNICM_NEW_DOC('010', '{oContainerId}', '{GetContainerName(oContainerId)}', '{FileName}', '{oExtension}', '{_username}') FROM RDB$DATABASE;"
|
|
Dim oDocId As Int64 = Firebird.GetScalarValue(oSQL)
|
|
|
|
If oDocId = -1 Then
|
|
_logger.Warn("Database returned -1 while creating Document Entry. File was not saved!")
|
|
Return Nothing
|
|
End If
|
|
|
|
_logger.Debug("Database Entry created with DocId {0}", oDocId)
|
|
|
|
oContainer.SetFile(Contents, FileName)
|
|
oContainer.SaveAs(GetContainerPath(oContainerId))
|
|
|
|
_logger.Debug("File saved in Container!", FileName)
|
|
|
|
Dim oDocument = New DocumentObject(oContainerId, oDocId, FileName)
|
|
Return New DocumentResultOld(oDocument)
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
Return New DocumentResultOld(ex.Message)
|
|
End Try
|
|
End Function
|
|
|
|
Public Function UpdateFile(DocObject As DocumentObject, Contents() As Byte) As DocumentResultOld Implements IEDMIService.UpdateFile
|
|
Try
|
|
TestFileExists(DocObject.ContainerId)
|
|
|
|
' TODO: update db
|
|
|
|
Dim oFilePath = GetContainerPath(DocObject.ContainerId)
|
|
Dim oFileContainer As FileContainer = FileContainer.Load(LogConfig, AppConfig.ContainerPassword, oFilePath)
|
|
|
|
oFileContainer.SetFile(Contents, oFileContainer.GetFile.FileName)
|
|
oFileContainer.Save()
|
|
|
|
|
|
Return New DocumentResultOld(DocObject)
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
Return Nothing
|
|
End Try
|
|
End Function
|
|
|
|
Public Function GetFile(DocObject As DocumentObject) As DocumentResultOld Implements IEDMIService.GetFile
|
|
Try
|
|
TestFileExists(DocObject.ContainerId)
|
|
|
|
Dim oContainerPath = GetContainerPath(DocObject.ContainerId)
|
|
Dim oContainer As FileContainer = FileContainer.Load(LogConfig, AppConfig.ContainerPassword, oContainerPath)
|
|
Dim oContents As Byte() = oContainer.GetFile().Contents
|
|
|
|
Return New DocumentResultOld(DocObject, oContents)
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
Return New DocumentResultOld(ex.Message)
|
|
End Try
|
|
End Function
|
|
|
|
Public Function DeleteFile(DocObject As DocumentObject) As Boolean Implements IEDMIService.DeleteFile
|
|
Try
|
|
TestFileExists(DocObject.ContainerId)
|
|
|
|
Dim oFilePath = GetContainerPath(DocObject.ContainerId)
|
|
IO.File.Delete(oFilePath)
|
|
|
|
'TODO: Delete doc from db
|
|
|
|
Return True
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
Return False
|
|
End Try
|
|
End Function
|
|
|
|
Private Function GetContainerPath(ContainerId As String) As String
|
|
Return Path.Combine(AppConfig.ContainerPath, GetContainerName(ContainerId))
|
|
End Function
|
|
|
|
Private Function GetContainerName(ContainerId As String) As String
|
|
Return ContainerId & ".enc"
|
|
End Function
|
|
|
|
Private Sub TestFileExists(ContainerId)
|
|
Dim oContainerPath = GetContainerPath(ContainerId)
|
|
|
|
If Not IO.File.Exists(oContainerPath) Then
|
|
Throw New FileNotFoundException("Container existiert nicht", oContainerPath)
|
|
End If
|
|
End Sub
|
|
|
|
Public Function GetDocumentByDocumentId(DocumentId As Long) As DocumentResultOld Implements IEDMIService.GetDocumentByDocumentId
|
|
Try
|
|
Dim oSQL = $"SELECT GUID, CONTAINER_ID, ORIGINAL_FILENAME FROM TBIDB_DOCUMENT WHERE GUID = {DocumentId}"
|
|
Dim oTable = Firebird.GetDatatable(oSQL)
|
|
|
|
If oTable.Rows.Count = 0 Then
|
|
Return New DocumentResultOld("Document not found")
|
|
End If
|
|
|
|
Dim oRow As DataRow = oTable.Rows.Item(0)
|
|
Dim oDocument As New DocumentObject(
|
|
oRow.Item("CONTAINER_ID"),
|
|
oRow.Item("GUID"),
|
|
oRow.Item("ORIGINAL_FILENAME")
|
|
)
|
|
|
|
TestFileExists(oDocument.ContainerId)
|
|
|
|
Dim oContainerPath = GetContainerPath(oDocument.ContainerId)
|
|
Dim oContainer As FileContainer = FileContainer.Load(LogConfig, AppConfig.ContainerPassword, oContainerPath)
|
|
Dim oContents As Byte() = oContainer.GetFile().Contents
|
|
|
|
Return New DocumentResultOld(oDocument, oContents)
|
|
Catch ex As Exception
|
|
Return New DocumentResultOld(ex.Message)
|
|
End Try
|
|
End Function
|
|
|
|
Public Function GetDocumentByContainerId(ContainerId As String) As DocumentResultOld Implements IEDMIService.GetDocumentByContainerId
|
|
Try
|
|
Dim oSQL = $"SELECT GUID, CONTAINER_ID, ORIGINAL_FILENAME FROM TBIDB_DOCUMENT WHERE CONTAINER_ID = '{ContainerId}'"
|
|
Dim oTable = Firebird.GetDatatable(oSQL)
|
|
|
|
If oTable.Rows.Count = 0 Then
|
|
Return New DocumentResultOld("Document not found")
|
|
End If
|
|
|
|
Dim oRow As DataRow = oTable.Rows.Item(0)
|
|
Dim oDocument As New DocumentObject(
|
|
oRow.Item("CONTAINER_ID"),
|
|
oRow.Item("GUID"),
|
|
oRow.Item("ORIGINAL_FILENAME")
|
|
)
|
|
|
|
TestFileExists(oDocument.ContainerId)
|
|
|
|
Dim oContainerPath = GetContainerPath(oDocument.ContainerId)
|
|
Dim oContainer As FileContainer = FileContainer.Load(LogConfig, AppConfig.ContainerPassword, oContainerPath)
|
|
Dim oContents As Byte() = oContainer.GetFile().Contents
|
|
|
|
Return New DocumentResultOld(oDocument, oContents)
|
|
Catch ex As Exception
|
|
Return New DocumentResultOld(ex.Message)
|
|
End Try
|
|
End Function
|
|
#End Region
|
|
|
|
#Region "Document"
|
|
''' <summary>
|
|
''' Imports a file according to ObjectStoreId
|
|
''' </summary>
|
|
''' <returns></returns>
|
|
Public Function ImportFile(Data As Messages.DocumentImportRequest) As Messages.DocumentImportResponse Implements IEDMIService.ImportFile
|
|
Dim oObjectStore = GlobalState.ObjectStores.
|
|
Where(Function(s) s.Id = Data.ObjectStoreId).
|
|
FirstOrDefault()
|
|
|
|
If oObjectStore Is Nothing Then
|
|
Throw New FaultException($"Object Store with Id [{Data.ObjectStoreId}] does not exist!")
|
|
End If
|
|
|
|
Dim EDMIPath = New EDMI.File.Path(LogConfig, oObjectStore.Path)
|
|
|
|
' TODO:
|
|
' - Get Object Store -> Object Catalog -> Catalog Path
|
|
' - If IS_ARCHIVE = True And RetentionDays <> Nothing:
|
|
' DoArchive!
|
|
' - Refactor EDMIPath to get ObjectStore at service start up
|
|
' and return ObjectStore Path from ObjectStoreId + RelativePath
|
|
' VWIDB_OBJECTSTORE
|
|
|
|
Dim oRelativePath As String = EDMIPath.GetRelativePath(Data.DocumentType, Data.FileName)
|
|
Dim oAbsolutePath As String = EDMIPath.GetFullPath(Data.DocumentType, Data.FileName)
|
|
Dim oDirectoryPath = EDMIPath.GetFullPath(Data.DocumentType)
|
|
|
|
Try
|
|
Directory.CreateDirectory(oDirectoryPath)
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
Throw New FaultException(ex.Message)
|
|
End Try
|
|
|
|
Try
|
|
Dim oVersionedFileName As String = Filesystem.GetVersionedFilename(oAbsolutePath)
|
|
|
|
_logger.Info("ImportFile: Saving file [{0}] to path [{1}]", Data.FileName, oVersionedFileName)
|
|
Using oStream = New FileStream(oVersionedFileName, FileMode.CreateNew)
|
|
oStream.Write(Data.Contents, 0, Data.Contents.Length)
|
|
oStream.Flush(True)
|
|
oStream.Close()
|
|
End Using
|
|
|
|
' insert into db
|
|
Dim oCommand As New SqlCommand("PRIDB_NEW_DOCUMENT")
|
|
oCommand.Parameters.AddWithValue("@OBJ_ST_ID", 1)
|
|
oCommand.Parameters.AddWithValue("@REL_PATH", oRelativePath)
|
|
oCommand.Parameters.AddWithValue("@WHO", _username)
|
|
oCommand.Parameters.AddWithValue("@REF_DOCID", 0)
|
|
oCommand.Parameters.Add(New SqlParameter("@IDB_OBJ_ID", SqlDbType.BigInt))
|
|
|
|
Dim oObjectId = MSSQL.GetScalarValue(oCommand, "@IDB_OBJ_ID")
|
|
|
|
Return New Messages.DocumentImportResponse() With {.ObjectId = oObjectId}
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
Throw New FaultException(ex.Message)
|
|
End Try
|
|
End Function
|
|
|
|
Public Function GetFileByObjectId(Data As Messages.DocumentStreamRequest) As Messages.DocumentStreamResponse Implements IEDMIService.GetFileByObjectId
|
|
Try
|
|
Dim oSQL As String = $"SELECT ObjectStoreId FROM VWIDB_DOC_DATA WHERE IDB_OBJ_ID = {Data.ObjectId}"
|
|
Dim oObjectStoreId = MSSQL.GetScalarValue(oSQL)
|
|
|
|
Dim oObjectStore = GlobalState.ObjectStores.
|
|
Where(Function(s) s.Id = oObjectStoreId).
|
|
FirstOrDefault()
|
|
|
|
Dim oSQL2 As String = $"SELECT DocRelativePath FROM VWIDB_DOC_DATA WHERE IDB_OBJ_ID = {Data.ObjectId}"
|
|
Dim oPath As String = MSSQL.GetScalarValue(oSQL2)
|
|
|
|
|
|
If IsNothing(oPath) Then
|
|
Throw New FaultException($"Object [{Data.ObjectId}] does not exist in database!")
|
|
End If
|
|
|
|
Dim EDMIPath As New EDMI.File.Path(LogConfig, oObjectStore.Path)
|
|
Dim oFullPath = EDMIPath.GetFullPathFromRelativePath(oPath)
|
|
|
|
_logger.Debug("GetFileByObjectId: Loading file [{0}]", oFullPath)
|
|
|
|
Dim oFileInfo As New FileInfo(oFullPath)
|
|
|
|
If Not oFileInfo.Exists Then
|
|
Throw New FaultException($"Object [{Data.ObjectId}] does not exist on filesystem!")
|
|
End If
|
|
|
|
Dim oDestination As New MemoryStream()
|
|
Using oSource As FileStream = IO.File.OpenRead(oFullPath)
|
|
oSource.CopyTo(oDestination)
|
|
End Using
|
|
|
|
oDestination.Seek(0, SeekOrigin.Begin)
|
|
Dim oMessage As New Messages.DocumentStreamResponse() With {
|
|
.FileName = oFileInfo.Name,
|
|
.FileContents = oDestination
|
|
}
|
|
|
|
Return oMessage
|
|
Catch ex As IOException
|
|
_logger.Error(ex)
|
|
Throw New FaultException($"Object [{Data.ObjectId}] could not be streamed!")
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
Throw New FaultException(ex.Message)
|
|
End Try
|
|
End Function
|
|
|
|
Public Function ListFilesForUser() As Messages.DocumentListResponse Implements IEDMIService.ListFilesForUser
|
|
Try
|
|
Dim oSQL = $"SELECT * FROM VWIDB_DOC_DATA"
|
|
Dim oDatatable As DataTable = MSSQL.GetDatatable(oSQL)
|
|
oDatatable.TableName = "DocumentList"
|
|
|
|
Return New Messages.DocumentListResponse() With {
|
|
.Datatable = oDatatable
|
|
}
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
Throw New FaultException(ex.Message)
|
|
End Try
|
|
End Function
|
|
|
|
#End Region
|
|
|
|
#Region "Index"
|
|
Public Function NewFileIndex(DocObject As DocumentObject, Syskey As String, LanguageCode As String, Value As String) As IndexResult Implements IEDMIService.NewFileIndex
|
|
Try
|
|
Dim oSQL = $"SELECT FNIDB_NEW_DOC_VALUE({DocObject.DocumentId},'{Syskey}','{LanguageCode}','{Value}','{_username}') FROM RDB$DATABASE;"
|
|
Dim oIndexId As Int64 = Firebird.GetScalarValue(oSQL)
|
|
|
|
Return New IndexResult(oIndexId)
|
|
Catch ex As Exception
|
|
_logger.Error(ex)
|
|
Return New IndexResult(ex.Message)
|
|
End Try
|
|
End Function
|
|
#End Region
|
|
End Class |