@@ -21,47 +21,100 @@ package com.secdec.codepulse.input.project
2121
2222import scala .concurrent .ExecutionContext .Implicits .global
2323
24- import akka .actor .{ Actor , Stash }
24+ import akka .actor .{ Actor , ActorRef , Stash }
25+ import scala .collection .mutable .{ Map => MutableMap }
2526import com .secdec .codepulse .data .model .{ ProjectData , ProjectId }
2627import com .secdec .codepulse .events .GeneralEventBus
28+ import com .secdec .codepulse .input .LanguageProcessor
2729import com .secdec .codepulse .processing .ProcessEnvelope
2830import com .secdec .codepulse .processing .ProcessStatus ._
29- import com .secdec .codepulse .tracer .{ generalEventBus , projectDataProvider , projectManager }
31+ import com .secdec .codepulse .tracer .{ BootVar , generalEventBus , projectDataProvider , projectManager }
3032
3133trait ProjectLoader {
32- def createAndLoadProjectData ( doLoad : ( ProjectData , GeneralEventBus ) => Unit ) : ProjectData
34+ protected def createProject : ProjectData
3335}
3436
35- case class CreateProject (load : (ProjectData , GeneralEventBus ) => Unit )
37+ case class CreateProject (processors : List [ BootVar [ ActorRef ]], load : (ProjectData , GeneralEventBus ) => Unit )
3638
3739class ProjectInputActor extends Actor with Stash with ProjectLoader {
3840
41+ val projectCreationProcessors = MutableMap .empty[String , List [BootVar [ActorRef ]]]
42+
43+ val projectProcessingSuccesses = MutableMap .empty[String , Integer ]
44+
45+ val projectProcessingFailures = MutableMap .empty[String , Integer ]
46+
3947 // TODO: handle data input by creating a project and broadcasting with 'DataInputAvailable' with project payload
4048 // TODO: capture failed state to cause a failed message and redirect (as necessary) for the user
4149
4250 def receive = {
43- case CreateProject (load) => {
44- val projectData = createAndLoadProjectData(load)
51+ case CreateProject (processors, load) => {
52+ val projectData = createProject
53+ addProjectCreators(projectData, processors)
54+
55+ load(projectData, generalEventBus)
56+
4557 sender ! projectData
4658 }
4759 case ProcessEnvelope (_, ProcessDataAvailable (identifier, file, treeNodeData)) => {
48- for (target <- projectManager getProject ProjectId (identifier.toInt)) {
49- target.notifyLoadingFinished()
60+ val numberOfProcessors = projectCreationProcessors.get(identifier).get.length
61+ val succeeded = projectProcessorSucceeded(identifier)
62+ val failed = projectProcessingFailures.get(identifier).get
63+
64+ val remaining = numberOfProcessors - (succeeded + failed)
65+
66+ if (remaining == 0 && succeeded >= 1 ) {
67+ projectManager getProject ProjectId (identifier.toInt) foreach(_.notifyLoadingFinished())
68+ clearProjectCreators(identifier)
5069 }
5170 }
5271 case ProcessEnvelope (_, Failed (identifier, action, Some (exception))) if action != " Dependency Check" => {
53- for (target <- projectManager.removeUnloadedProject(ProjectId (identifier.toInt), exception.getMessage)) {
54- // target.notifyLoadingFailed(exception.getMessage)
72+ val numberOfProcessors = projectCreationProcessors.get(identifier).get.length
73+ val succeeded = projectProcessingSuccesses.get(identifier).get
74+ val failed = projectProcessorFailed(identifier)
75+
76+ val remaining = numberOfProcessors - (succeeded + failed)
77+
78+ if (remaining == 0 && failed == numberOfProcessors) {
79+ projectManager.removeUnloadedProject(ProjectId (identifier.toInt), exception.getMessage)
80+ clearProjectCreators(identifier)
5581 }
5682 }
5783 }
5884
59- def createAndLoadProjectData ( doLoad : ( ProjectData , GeneralEventBus ) => Unit ) : ProjectData = {
85+ protected def createProject : ProjectData = {
6086 val projectId = projectManager.createProject
6187 val projectData = projectDataProvider getProject projectId
6288
63- doLoad(projectData, generalEventBus)
64-
6589 projectData
6690 }
91+
92+ protected def addProjectCreators (projectData : ProjectData , processors : List [BootVar [ActorRef ]]): Integer = {
93+ val id = projectData.id.num.toString
94+ projectCreationProcessors.put(id, processors)
95+ projectProcessingSuccesses.put(id, 0 )
96+ projectProcessingFailures.put(id, 0 )
97+ processors.length
98+ }
99+
100+ protected def clearProjectCreators (projectId : String ) = {
101+ projectCreationProcessors.remove(projectId)
102+ projectProcessingSuccesses.remove(projectId)
103+ projectProcessingFailures.remove(projectId)
104+ }
105+
106+ protected def projectProcessorSucceeded (projectId : String ): Integer = {
107+ incrementProcessor(projectId, projectProcessingSuccesses)
108+ }
109+
110+ protected def projectProcessorFailed (projectId : String ) = {
111+ incrementProcessor(projectId, projectProcessingFailures)
112+ }
113+
114+ private def incrementProcessor (key : String , map : MutableMap [String , Integer ]): Integer = {
115+ val count = map.get(key).get + 1
116+ map.update(key, count)
117+
118+ count
119+ }
67120}
0 commit comments