git-tfs-id: [http://tfs.userrendszerhaz.hu:8080/tfs/DefaultCollection]$/MediaCube...
authorVásáry Dániel <daniel.vasary@userrendszerhaz.hu>
Thu, 8 Feb 2018 10:00:18 +0000 (10:00 +0000)
committerVásáry Dániel <daniel.vasary@userrendszerhaz.hu>
Thu, 8 Feb 2018 10:00:18 +0000 (10:00 +0000)
29 files changed:
client/MCTool/MCTool.csproj.vspscc [new file with mode: 0644]
client/Maestro/Configuration/-configuration-studio.json [moved from client/Maestro/Configuration/configuration-studio.json with 100% similarity]
client/Maestro/Configuration/configuration-sxs.json [moved from client/Maestro/Configuration/-configuration-sxs.json with 100% similarity]
client/Maestro/Configuration/global.json
client/Maestro/Maestro.csproj
client/Maestro/MaestroForm.Metadata.cs
client/Maestro/Program.cs
client/Maestro/Properties/AssemblyInfo.cs
client/Maestro/Sources/CreatedFileMonitor.cs
client/Maestro/Sources/FileSystemSource.cs
client/Maestro/nlog.config
client/MaestroShared/Commons/PatternNameMaker.cs
client/MaestroShared/Configuration/ConfigurationInfo.cs
client/MaestroShared/Metadata/ArchiveMetadata.cs
client/MaestroShared/Targets/UNCTargetProcessor.cs
client/MetadataSelector/MetadataSelector.csproj.vspscc [new file with mode: 0644]
server/-configuration/scheduledjobs.json
server/user.jobengine.executors/jobtemplates/import-morpheus-missing-materials.xml [new file with mode: 0644]
server/user.jobengine.executors/src/user/jobengine/server/steps/ImportMORPHEUSMissingMaterialsStep.java [new file with mode: 0644]
server/user.jobengine.osgi.server/WEB-INF/zk.xml
server/user.jobengine.osgi.server/pages/index.zul
server/user.jobengine.osgi.server/pages/joblist.zul
server/user.jobengine.osgi.server/pages/missingmaterials.zul [new file with mode: 0644]
server/user.jobengine.osgi.server/src/user/jobengine/server/JobEngine.java
server/user.jobengine.osgi.server/src/user/jobengine/server/scheduler/ScheduledJob.java
server/user.jobengine.osgi.server/src/user/jobengine/server/steps/EscortFiles.java
server/user.jobengine.osgi.server/src/user/jobengine/zk/model/BasicDBObjectConverter.java [new file with mode: 0644]
server/user.jobengine.osgi.server/src/user/jobengine/zk/model/MissingMaterialsModel.java [new file with mode: 0644]
server/user.jobengine.osgi.server/src/user/jobengine/zk/util/LifeCycleListener.java [new file with mode: 0644]

diff --git a/client/MCTool/MCTool.csproj.vspscc b/client/MCTool/MCTool.csproj.vspscc
new file mode 100644 (file)
index 0000000..feffdec
--- /dev/null
@@ -0,0 +1,10 @@
+""\r
+{\r
+"FILE_VERSION" = "9237"\r
+"ENLISTMENT_CHOICE" = "NEVER"\r
+"PROJECT_FILE_RELATIVE_PATH" = ""\r
+"NUMBER_OF_EXCLUDED_FILES" = "0"\r
+"ORIGINAL_PROJECT_FILE_PATH" = ""\r
+"NUMBER_OF_NESTED_PROJECTS" = "0"\r
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"\r
+}\r
index 1188385979be7abb8e600a3e7119f7e9a0b773c8..69426439f258522f7bf6fa23dbcbac091758bac3 100644 (file)
@@ -2,7 +2,7 @@
   "minimizeToTray":  false,\r
   "userDomain": {\r
     "address": "10.10.254.11",\r
-    "userName": "echotest",\r
-    "password": "F3QcfkSEW7hq+FcEraq9xv4UdHHeVoOh7jBH1G1k9SzEayTXyiT4WQ7XKtBO/ygnCpRU97AXoKXKoqXIGP8QlVkFurRqwzo8mywEb1q2VW7dUjkJcLFtLDkqQjM39+N9"\r
+    "-userName": "echotest",\r
+    "-password": "F3QcfkSEW7hq+FcEraq9xv4UdHHeVoOh7jBH1G1k9SzEayTXyiT4WQ7XKtBO/ygnCpRU97AXoKXKoqXIGP8QlVkFurRqwzo8mywEb1q2VW7dUjkJcLFtLDkqQjM39+N9"\r
   }\r
 }\r
index 2ec0bc5a9d8f08e54cae7b0d216e90f34fc7f798..9a9b1fd7177ce215a92aa2d9cff45d85478fcd0a 100644 (file)
     <None Include="Resources\configuration-unc.json">\r
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
     </None>\r
-    <None Include="Configuration\-configuration-sxs.json">\r
+    <None Include="Configuration\configuration-sxs.json">\r
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>\r
     </None>\r
-    <None Include="Configuration\configuration-studio.json">\r
+    <None Include="Configuration\-configuration-studio.json">\r
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>\r
     </None>\r
   </ItemGroup>\r
index 338836322cce16509b9c2ee081f172d081ce681e..dec1fb4edf4363c7c581816cf6d64399b20abd33 100644 (file)
@@ -197,17 +197,41 @@ namespace Maestro {
                 case MetadataType.None:\r
                 case MetadataType.MediaCube:\r
                     result = GetMediaCubeMetadata();\r
+                    result.mediaType = "Generic";\r
                     break;\r
                 case MetadataType.OctopusStory:\r
                 case MetadataType.OctopusPlaceHolder:\r
                     result = GetOctopusMetadata(metadataType);\r
+                    result.mediaType = "Octopus nyersanyag";\r
                     break;\r
                 case MetadataType.TrafficMaterial:\r
+                    result = GetTrafficMetadata(metadataType);\r
+                    result.mediaType = "Műsor";\r
+                    break;\r
                 case MetadataType.TrafficPromo:\r
+                    result = GetTrafficMetadata(metadataType);\r
+                    result.mediaType = "Promo";\r
+                    break;\r
                 case MetadataType.TrafficAD:\r
                     result = GetTrafficMetadata(metadataType);\r
+                    result.mediaType = "Reklám";\r
                     break;\r
             }\r
+\r
+            if (!String.IsNullOrWhiteSpace(SelectedSource.Prefix) && "Generic".Equals(result.mediaType)) {\r
+                metadataType = MetadataTypeUtil.Guess(SelectedSource.Prefix);\r
+                switch (metadataType) {\r
+                    case MetadataType.TrafficMaterial:\r
+                        result.mediaType = "Műsor nyersanyag";\r
+                        break;\r
+                    case MetadataType.TrafficPromo:\r
+                        result.mediaType = "Promo nyersanyag";\r
+                        break;\r
+                    case MetadataType.TrafficAD:\r
+                        result.mediaType = "Reklám nyersanyag";\r
+                        break;\r
+                }\r
+            }\r
             Cursor.Current = Cursors.Default;\r
             return result;\r
         }\r
index b1913c4c9399ebfcb49e68696cb41a659b8b620f..a8e673062b781de15190c59a06fdb1fcc1a87ed5 100644 (file)
@@ -12,6 +12,7 @@ using System.Linq;
 using System.Reflection;\r
 using System.Runtime.InteropServices;\r
 using System.Security.AccessControl;\r
+using System.Security.Permissions;\r
 using System.Security.Principal;\r
 using System.Threading;\r
 using System.Threading.Tasks;\r
@@ -26,6 +27,7 @@ namespace Maestro {
         /// The main entry point for the application.\r
         /// </summary>\r
         [STAThread]\r
+        [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]\r
         static void Main() {\r
             string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();\r
             string userName = WindowsIdentity.GetCurrent().Name;\r
@@ -53,6 +55,14 @@ namespace Maestro {
                     if (hasHandle || enableInstance) {\r
                         TrayApplicationContext context = null;\r
                         try {\r
+                            Application.ThreadException += (s,e) => {\r
+                                logger.Error(e);\r
+                                MessageBox.Show(new Form() { TopMost = true }, e.Exception?.Message);\r
+                            };\r
+                            AppDomain.CurrentDomain.UnhandledException += (s, e) => {\r
+                                logger.Error(e);\r
+                                MessageBox.Show(new Form() { TopMost = true }, ((Exception)e.ExceptionObject).Message);\r
+                            };\r
                             Application.EnableVisualStyles();\r
                             Application.SetCompatibleTextRenderingDefault(false);\r
                             context = new TrayApplicationContext();\r
@@ -73,6 +83,10 @@ namespace Maestro {
                 }\r
             }\r
         }\r
+\r
+        private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {\r
+            throw new NotImplementedException();\r
+        }\r
     }\r
 \r
     public class TrayApplicationContext : ApplicationContext {\r
index 6f5109cc49d2180ca5849104057fb5b97b5e4a81..77b1304dc8fd45210c5371986075344af94e3d7d 100644 (file)
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
 // You can specify all the values or you can default the Build and Revision Numbers\r
 // by using the '*' as shown below:\r
 // [assembly: AssemblyVersion("1.0.*")]\r
-[assembly: AssemblyVersion("2.0.7.0")]\r
-[assembly: AssemblyFileVersion("2.0.7.0")]\r
+[assembly: AssemblyVersion("2.0.7.3")]\r
+[assembly: AssemblyFileVersion("2.0.7.3")]\r
index d74f371d3c19f8da0d31f492925f3b5617415059..c37f02c67a796f6f8d8285b151ceba1829d89e5e 100644 (file)
@@ -1,4 +1,5 @@
 using NLog;\r
+using System;\r
 using System.ComponentModel;\r
 using System.IO;\r
 using System.Threading;\r
@@ -19,8 +20,17 @@ namespace Maestro.Sources {
                     return true;\r
                 }\r
             }\r
-            catch (IOException) {\r
-                return false;\r
+            catch (Exception e) {\r
+                logger.Error(e);\r
+                try {\r
+                    using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None)) {\r
+                        return true;\r
+                    }\r
+                }\r
+                catch (Exception e1) {\r
+                    logger.Error(e1);\r
+                    return false;\r
+                }\r
             }\r
         }\r
 \r
index 3a380fba87b38d53546e4b4eb80f028722bebea6..5f95d306f95cb055fe77e239f92f29326eccf617 100644 (file)
@@ -23,7 +23,8 @@ namespace Maestro.Sources {
         private List<FileSourceItem> cache;\r
         private BackgroundWorker pathWatcherWorker = new BackgroundWorker();\r
         private string rootPath;\r
-        FileSystemWatcher watcher;\r
+        private FileSystemWatcher watcher;\r
+        private Object lck = new Object();\r
 \r
         public DataGridViewColumn[] Columns {\r
             get {\r
@@ -143,11 +144,15 @@ namespace Maestro.Sources {
             if (Path.Equals(path))\r
                 return false;\r
             Path = path == null ? rootPath : path;\r
+            Reset();\r
+            logger.Trace("Exit");\r
+            return true;\r
+        }\r
+\r
+        private void Reset() {\r
             Clear();\r
             cache = null;\r
             Shutdown();\r
-            logger.Trace("Exit");\r
-            return true;\r
         }\r
 \r
         public FileSystemSource(Control parent, IMessageBus messageBus, bool playerEnabled, string fileExtensionFilter) {\r
@@ -269,7 +274,22 @@ namespace Maestro.Sources {
         }\r
 \r
         public void OnError(object sender, ErrorEventArgs e) {\r
-            logger.Error(e.GetException());\r
+            logger.Error(e);\r
+            parent.SafeCall(() => Reset());\r
+        }\r
+\r
+        private FileSourceItem getItemByName(string name) {\r
+            if (name == null)\r
+                return null;\r
+            FileSourceItem result = null;\r
+            try {\r
+                lock (lck) {\r
+                    result = this.Where(x => name.Equals(x.Name)).FirstOrDefault();\r
+                }\r
+            } catch (Exception e) {\r
+                logger.Error(e);\r
+            }\r
+            return result;\r
         }\r
 \r
         public void OnRenamed(object sender, RenamedEventArgs e) {\r
@@ -281,7 +301,7 @@ namespace Maestro.Sources {
             FileInfo fiNew = new FileInfo(e.FullPath);\r
             if (fiOld.Extension.Equals(fiNew.Extension)) {\r
                 logger.Debug("File rename");\r
-                var item = this.Where(x => x.Name == e.OldName).FirstOrDefault();\r
+                var item = getItemByName(e.OldName);\r
                 if (item == null || !item.CanHandle(acceptableExtensions))\r
                     return;\r
                 parent.SafeCall(() => {\r
@@ -298,7 +318,9 @@ namespace Maestro.Sources {
                 if (newItem.CanHandle(acceptableExtensions))\r
                     SafeCreateItem(newItem);\r
 \r
-                var item = this.Where(x => x.Name == e.OldName).FirstOrDefault();\r
+                var item = getItemByName(e.OldName);\r
+                if (item == null)\r
+                    return;\r
                 SafeDeleteItem(item);\r
             }\r
             logger.Trace("Exit");\r
@@ -309,7 +331,7 @@ namespace Maestro.Sources {
                 return;\r
             logger.Trace("Entry");\r
             //logger.Debug("{0} {1}", e.ChangeType, e.Name);\r
-            var item = this.Where(x => x.Name == e.Name).FirstOrDefault();\r
+            var item = getItemByName(e.Name);\r
             if (item == null || !item.CanHandle(acceptableExtensions))\r
                 return;\r
             logger.Debug("File change");\r
@@ -324,6 +346,8 @@ namespace Maestro.Sources {
             logger.Trace("Exit");\r
         }\r
 \r
+\r
+\r
         private void OnCreated(object sender, FileSystemEventArgs e) {\r
             if (!String.IsNullOrEmpty(filter))\r
                 return;\r
@@ -349,7 +373,7 @@ namespace Maestro.Sources {
                 return;\r
             logger.Trace("Entry");\r
             logger.Debug("{0} {1}", e.ChangeType, e.Name);\r
-            FileSourceItem item = this.Where(i => i.Name.Equals(e.Name)).FirstOrDefault();\r
+            var item = getItemByName(e.Name);\r
             if (item == null || !item.CanHandle(acceptableExtensions))\r
                 return;\r
             SafeDeleteItem(item);\r
index d5a005aac17a1b8cf10c2249b569c126aa31575d..70d5e79862c2a1d06edb0ae960d5428a5b06d9c0 100644 (file)
@@ -5,8 +5,12 @@
   <targets>\r
     <target name="t1" xsi:type="Debugger" layout="${date:format=HH\:mm\:ss} ${level:uppercase=true} ${callsite:includeNamespace=false:includeSourcePath=false} | ${message} ${callsite:fileName=true:className=false:includeSourcePath=false:methodName=false:includeNamespace=false}" />\r
     <target name="t2" xsi:type="Debugger" layout="ERROR stack: ${stacktrace:format=Raw}" />\r
-    <target name="file" xsi:type="File" layout="${date:format=yyyy.MM.dd HH\:mm\:ss} ${level:uppercase=true} ${logger:shortName=true} | ${message}" fileName="${basedir}/logs/maestro.log" keepFileOpen="false" encoding="utf-8" archiveEvery="Day" archiveNumbering="Rolling" maxArchiveFiles="7" />\r
-    <target name="errorfile" xsi:type="File" layout="${date:format=yyyy.MM.dd HH\:mm\:ss} ${level:uppercase=true} ${logger:shortName=true} | ${message} ${stacktrace:format=Raw}" fileName="${basedir}/logs/maestro-err.log" keepFileOpen="false" encoding="utf-8" archiveEvery="Day" archiveNumbering="Rolling" maxArchiveFiles="7" />\r
+    <target name="file" xsi:type="File" \r
+            layout="${date:format=yyyy.MM.dd HH\:mm\:ss} ${level:uppercase=true} ${logger:shortName=true} | ${message}" \r
+            fileName="${basedir}/logs/${machinename}-maestro.log" keepFileOpen="false" encoding="utf-8" archiveEvery="Day" archiveNumbering="Rolling" maxArchiveFiles="7" />\r
+    <target name="errorfile" xsi:type="File" \r
+            layout="${date:format=yyyy.MM.dd HH\:mm\:ss} ${level:uppercase=true} ${logger:shortName=true} | ${message} ${stacktrace:format=Raw}" \r
+            fileName="${basedir}/logs/maestro-err.log" keepFileOpen="false" encoding="utf-8" archiveEvery="Day" archiveNumbering="Rolling" maxArchiveFiles="7" />\r
   </targets>\r
   <!--Naplózási szint-->\r
   <rules>\r
index bd17c626b752e05129aed1b31ad0af5e844d5f37..859e1b45bf7020de02c9108fac051c1bb13200c6 100644 (file)
@@ -10,6 +10,7 @@ namespace MaestroShared.Commons {
         private const string SOURCESTARTID_PATTERN = "[^0-9]";\r
         private const string PATTERN_TARGETNAME = "%TARGETNAME%";\r
         private const string PATTERN_USERNAME = "%USERNAME%";\r
+        private const string PATTERN_COMPUTERNAME = "%COMPUTERNAME%";\r
         private const string PATTERN_ID = "%ID%";\r
         private const string PATTERN_IDROOT = "%IDROOT%";\r
         private const string PATTERN_SOURCENAME = "%SOURCENAME%";\r
@@ -65,6 +66,9 @@ namespace MaestroShared.Commons {
             if (!String.IsNullOrEmpty(userName))\r
                 result = result.Replace(PATTERN_USERNAME, userName);\r
 \r
+            if (!String.IsNullOrEmpty(Environment.MachineName))\r
+                result = result.Replace(PATTERN_COMPUTERNAME, Environment.MachineName);\r
+\r
             if (!String.IsNullOrEmpty(text))\r
                 result = result.Replace(PATTERN_TEXT, Normalize(text));\r
             return result; \r
index 5092c81be65d52738848610ba24a97480fa5a8bc..f273ac687453750c14e112d9a5a7b30f3da25c63 100644 (file)
@@ -115,6 +115,7 @@ namespace MaestroShared.Configuration {
         public bool NexioServer { get; set; }\r
         public string NexioFileExistsMessage { get; set; }\r
         public string Agency { get; set; }\r
+        public string PopupMessage { get; set; }\r
     }\r
 \r
     public class Connection {\r
index fb4585e46502978123b22cd1a68bc64a66ca2663..097165b954e53f0136fe17445911a12b49412bac 100644 (file)
@@ -15,8 +15,10 @@ namespace MaestroShared.Metadata {
         public string mediaHouseId { get; set; }\r
         public string mediaTitle { get; set; }\r
         public string mediaDescription { get; set; }\r
+        [JsonIgnore]\r
         public bool ok { get; set; }\r
         public string userName { get; set; }\r
+        public string mediaType { get; set; }\r
 \r
         public override string ToString() {\r
             return JsonConvert.SerializeObject(this, Formatting.Indented);\r
index db2a191d4343b633ec501e7983a1b3196e8f03e2..4692c005a171fedbe8a6136bb3a1dabab27e5ea8 100644 (file)
@@ -59,6 +59,9 @@ namespace MaestroShared.Targets {
                 userName = parameters.UserName\r
             };\r
             Label = parameters.TargetConfig.Label;\r
+            string popupMessage = parameters.TargetConfig?.PopupMessage;\r
+            if (popupMessage != null && popupMessage.Length > 0)\r
+                MsgBox.Info(popupMessage);\r
         }\r
 \r
         protected virtual void BeforeExecute() {\r
diff --git a/client/MetadataSelector/MetadataSelector.csproj.vspscc b/client/MetadataSelector/MetadataSelector.csproj.vspscc
new file mode 100644 (file)
index 0000000..feffdec
--- /dev/null
@@ -0,0 +1,10 @@
+""\r
+{\r
+"FILE_VERSION" = "9237"\r
+"ENLISTMENT_CHOICE" = "NEVER"\r
+"PROJECT_FILE_RELATIVE_PATH" = ""\r
+"NUMBER_OF_EXCLUDED_FILES" = "0"\r
+"ORIGINAL_PROJECT_FILE_PATH" = ""\r
+"NUMBER_OF_NESTED_PROJECTS" = "0"\r
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"\r
+}\r
index bda37e10ad3fd2102679d87746336af562392395..953a3db7d1ef73f7da64afd06dc7dab843a61fd4 100644 (file)
@@ -1,5 +1,17 @@
 {"joblist":[\r
        {\r
+      "active": false,\r
+         "name" : "MORPHEUS 'missing materials' importálása",\r
+      "template": "import-morpheus-missing-materials.xml",\r
+      "executeimmediate": false,\r
+      "cronexpression": "0 0 0/1 1/1 * ? *",\r
+      "parameters": [ \r
+       {"name": "csvFilePath", "value": "c:/temp/morpheus", "type": "java.lang.String"},\r
+       {"name": "processedFolder", "value": "DONE", "type": "java.lang.String"},\r
+       {"name": "targetPath", "value": "\\\\10.10.1.100\\BRAAVOS\\ARCHIVE_RESTORE", "type": "java.lang.String"}\r
+      ]\r
+       },\r
+       {\r
       "active": false,\r
          "name" : "Felhasználói archiválás",\r
       "template": "archive-ondemand.xml",\r
diff --git a/server/user.jobengine.executors/jobtemplates/import-morpheus-missing-materials.xml b/server/user.jobengine.executors/jobtemplates/import-morpheus-missing-materials.xml
new file mode 100644 (file)
index 0000000..c339f06
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<jobtemplate name="MORPHEUS 'missing materials' importálása">\r
+       <declarations>\r
+               <parameters>\r
+                       <parameter name="csvFilePath" type="java.lang.String" />\r
+                       <parameter name="processedFolder" type="java.lang.String" />\r
+                       <parameter name="targetPath" type="java.lang.String" />\r
+               </parameters>\r
+       </declarations>\r
+       <commands>\r
+               <calljobstep type="user.jobengine.server.steps.ImportMORPHEUSMissingMaterialsStep" weight="1">\r
+                       <inputs>\r
+                               <input>\r
+                                       <parameter name="csvFilePath" />\r
+                               </input>\r
+                               <input>\r
+                                       <parameter name="processedFolder" />\r
+                               </input>\r
+                               <input>\r
+                                       <parameter name="targetPath" />\r
+                               </input>\r
+                       </inputs>\r
+               </calljobstep>\r
+       </commands>\r
+</jobtemplate>
\ No newline at end of file
diff --git a/server/user.jobengine.executors/src/user/jobengine/server/steps/ImportMORPHEUSMissingMaterialsStep.java b/server/user.jobengine.executors/src/user/jobengine/server/steps/ImportMORPHEUSMissingMaterialsStep.java
new file mode 100644 (file)
index 0000000..17c1249
--- /dev/null
@@ -0,0 +1,248 @@
+package user.jobengine.server.steps;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.nio.charset.Charset;\r
+import java.nio.file.DirectoryStream;\r
+import java.nio.file.Files;\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+\r
+import com.ibm.nosql.json.api.BasicDBObject;\r
+import com.ibm.nosql.json.api.DB;\r
+import com.ibm.nosql.json.api.DBCollection;\r
+import com.ibm.nosql.json.api.DBObject;\r
+import com.ibm.nosql.json.api.QueryBuilder;\r
+\r
+import user.commons.IEntityBase;\r
+import user.commons.nosql.NoSQLUtils;\r
+import user.jobengine.db.IItemManager;\r
+import user.jobengine.db.MediaFile;\r
+import user.jobengine.db.MediaFileDAO;\r
+import user.jobengine.server.IJobEngine;\r
+import user.jobengine.server.IJobRuntime;\r
+\r
+public class ImportMORPHEUSMissingMaterialsStep extends JobStep {\r
+       private static final String STATUS = "Status";\r
+       private static final String IMPORTED = "Imported";\r
+       private static final Logger logger = LogManager.getLogger();\r
+       private static final String MATERIAL_ID = "Material ID";\r
+       private static final String CHANNEL = "Channel";\r
+       private static final String TIME_TO_AIR = "Time to Air";\r
+       private static final String DURATION = "Duration";\r
+       private static final String TITLE = "Title";\r
+       private static final String DEVICE_ID = "Device ID";\r
+       private static final String REASON = "Reason";\r
+       private static final String COLLECTION_NAME = "missing_materials";\r
+\r
+       private static final String CSV_EXT = ".csv";\r
+       private static final String MXF_EXT = ".MXF";\r
+       private MediaFileDAO dao;\r
+       private String processedFolder;\r
+       private DB db;\r
+       private String targetPath;\r
+       private IJobRuntime jobRuntime;\r
+       private int overall;\r
+       private int current;\r
+\r
+       private Map<String, Integer> buildMetadataMap(Path csvFilePath, String[] data) throws Exception {\r
+               Map<String, Integer> result = new HashMap<>();\r
+               List<String> dataList = Arrays.asList(data);\r
+               storeMetadataPosition(csvFilePath, dataList, MATERIAL_ID, result);\r
+               storeMetadataPosition(csvFilePath, dataList, CHANNEL, result);\r
+               storeMetadataPosition(csvFilePath, dataList, TIME_TO_AIR, result);\r
+               storeMetadataPosition(csvFilePath, dataList, DURATION, result);\r
+               storeMetadataPosition(csvFilePath, dataList, TITLE, result);\r
+               storeMetadataPosition(csvFilePath, dataList, DEVICE_ID, result);\r
+               storeMetadataPosition(csvFilePath, dataList, REASON, result);\r
+               return result;\r
+       }\r
+\r
+       @StepEntry\r
+       public Object[] execute(String sourceCSVPath, String processedFolder, String targetPath, IJobEngine jobEngine, IJobRuntime jobRuntime) throws Exception {\r
+               this.jobRuntime = jobRuntime;\r
+               setAndCheck(sourceCSVPath, processedFolder, targetPath, jobEngine);\r
+\r
+               List<Path> filePaths = new ArrayList<>();\r
+               try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(sourceCSVPath))) {\r
+                       for (Path path : directoryStream) {\r
+                               filePaths.add(path);\r
+                       }\r
+\r
+                       processPathItems(filePaths);\r
+               } catch (Exception e) {\r
+                       logger.catching(e);\r
+                       logger.error(jobRuntime.getMarker(), "Hiba a végrehajtás során. A rendszer üzenete: {}", e.getMessage());\r
+               }\r
+               return null;\r
+       }\r
+\r
+       private void moveProcessedCSV(Path csvFilePath) throws IOException {\r
+               EscortFiles.ensureUNCFolder(csvFilePath.getParent().toString(), processedFolder);\r
+               String fileName = csvFilePath.getFileName() + "." + EscortFiles.composeKillDate(0);\r
+               Path targetPath = Paths.get(csvFilePath.getParent().toString(), processedFolder, fileName);\r
+               Files.move(csvFilePath, targetPath);\r
+       }\r
+\r
+       private void processLine(String[] data, Map<String, Integer> metadatas) throws Exception {\r
+               String channel = data[metadatas.get(CHANNEL)];\r
+               String timeToAir = data[metadatas.get(TIME_TO_AIR)];\r
+               String duration = data[metadatas.get(DURATION)];\r
+               String materialID = data[metadatas.get(MATERIAL_ID)];\r
+               String title = data[metadatas.get(TITLE)];\r
+               String deviceID = data[metadatas.get(DEVICE_ID)];\r
+               String reason = data[metadatas.get(REASON)];\r
+\r
+               DBObject query = QueryBuilder.start().and(QueryBuilder.start(MATERIAL_ID).is(materialID).get(), QueryBuilder.start(TIME_TO_AIR).is(timeToAir).get())\r
+                               .get();\r
+               DBCollection collection = db.getCollection(COLLECTION_NAME);\r
+               BasicDBObject existingObject = (BasicDBObject) collection.findOne(query);\r
+               if (existingObject != null) {\r
+                       logger.warn(jobRuntime.getMarker(), "Az '{}' anyag már feldolgozásra került az {} időpontban.", materialID, existingObject.getDate(IMPORTED));\r
+                       return;\r
+               }\r
+\r
+               BasicDBObject dbObject = new BasicDBObject(IMPORTED, new Date());\r
+               dbObject.put(CHANNEL, channel);\r
+               dbObject.put(TIME_TO_AIR.replace(" ", ""), timeToAir);\r
+               dbObject.put(DURATION, duration);\r
+               dbObject.put(MATERIAL_ID.replace(" ", ""), materialID);\r
+               dbObject.put(TITLE, title);\r
+               dbObject.put(DEVICE_ID.replace(" ", ""), deviceID);\r
+               dbObject.put(REASON, reason);\r
+\r
+               String fileName = materialID + MXF_EXT;\r
+               if (Files.exists(Paths.get(targetPath, fileName))) {\r
+                       logger.warn(jobRuntime.getMarker(), "Az '{}' anyag már be van töltve.", materialID);\r
+                       dbObject.put(STATUS, "SKIPPED");\r
+               } else {\r
+                       List<IEntityBase> medias = dao.getByHouseId(fileName);\r
+                       if (medias == null || medias.size() == 0) {\r
+                               logger.warn(jobRuntime.getMarker(), "Az '{}' anyag nem található az archívumban.", materialID);\r
+                               dbObject.put(STATUS, "UNAVAILABLE");\r
+                       } else if (medias.size() > 1) {\r
+                               logger.warn(jobRuntime.getMarker(), "Az '{}' anyagból egynél több található az archívumban.", materialID);\r
+                               dbObject.put(STATUS, "MULTIPLE");\r
+                       } else {\r
+                               logger.info(jobRuntime.getMarker(), "Az '{}' anyag megtalálható az archívumban.", materialID);\r
+                               dbObject.put(STATUS, "RESTORABLE");\r
+                       }\r
+\r
+               }\r
+\r
+               collection.insert(dbObject);\r
+       }\r
+\r
+       //      Channel,Time to Air,Duration,Material ID,Title,Device ID,Reason,\r
+       //      TX02,10-JAN-2018 13:25:21:08,00:05:00:00,M009572A,Tiéd a pálya/26. - 1. seg - Eredeti ** mc ,ICELE-02,On Domain (ISILON, ICELE-01, ICELE-05) ,\r
+       private void processMissingMaterialCSV(Path csvFilePath, List<String> lines) throws Exception {\r
+               if (lines == null | lines.size() == 0) {\r
+                       return;\r
+               }\r
+\r
+               Map<String, Integer> metadatas = null;\r
+               for (int i = 0; i < lines.size(); i++) {\r
+                       String line = lines.get(i);\r
+                       if (line == null)\r
+                               continue;\r
+                       String[] data = line.split(",");\r
+                       if (i == 0)\r
+                               metadatas = buildMetadataMap(csvFilePath, data);\r
+                       else\r
+                               processLine(data, metadatas);\r
+\r
+                       current++;\r
+                       setProgress(current * 100 / overall);\r
+               }\r
+\r
+       }\r
+\r
+       private void processPathItem(Path csvFilePath, List<String> lines) {\r
+               File csvFile = csvFilePath.toFile();\r
+\r
+               try {\r
+                       processMissingMaterialCSV(csvFilePath, lines);\r
+                       moveProcessedCSV(csvFilePath);\r
+               } catch (Exception e) {\r
+                       logger.catching(e);\r
+                       logger.error(jobRuntime.getMarker(), "A {} MORPHEUS állomány mozgatásakor hiba történt. A rendszer hibaüzenete: {}.", csvFile.getName(),\r
+                                       e.getMessage());\r
+               }\r
+       }\r
+\r
+       private void processPathItems(List<Path> filePaths) throws IOException {\r
+               overall = 0;\r
+               Map<Path, List<String>> contents = new HashMap<>();\r
+               for (Path filePath : filePaths) {\r
+                       File csvFile = filePath.toFile();\r
+                       if (csvFile.isDirectory() || !csvFile.getName().toLowerCase().endsWith(CSV_EXT.toLowerCase()))\r
+                               continue;\r
+                       List<String> lines = Files.readAllLines(filePath, Charset.forName("UTF-8"));\r
+                       overall += lines.size();\r
+                       contents.put(filePath, lines);\r
+               }\r
+\r
+               Set<Path> csvPaths = contents.keySet();\r
+               for (Path csvPath : csvPaths) {\r
+                       processPathItem(csvPath, contents.get(csvPath));\r
+               }\r
+       }\r
+\r
+       private void setAndCheck(String sourcePath, String processedFolder, String targetPath, IJobEngine jobEngine) {\r
+               if (jobEngine == null) {\r
+                       logger.error(jobRuntime.getMarker(), "Az folyamatkezelő réteg nem elérhető.");\r
+                       throw new NullPointerException("Internal error, missing JobEngine reference.");\r
+               }\r
+\r
+               IItemManager manager = jobEngine.getItemManager();\r
+               if (manager == null) {\r
+                       logger.error(jobRuntime.getMarker(), "Az adatbáziskezelő réteg nem elérhető.");\r
+                       throw new NullPointerException("Internal error, missing ItemManager reference.");\r
+               }\r
+               dao = (MediaFileDAO) manager.getBaseDAO(MediaFile.class);\r
+               if (dao == null) {\r
+                       logger.error(jobRuntime.getMarker(), "Az adatbáziskezelő réteg MediaFile kezelöje nem elérhető.");\r
+                       throw new NullPointerException("Internal error, missing MediaFile DAO reference.");\r
+               }\r
+               if (sourcePath == null) {\r
+                       logger.error(jobRuntime.getMarker(), "A folyamat 'sourcePath' bemeneti paramétere üres.");\r
+                       throw new NullPointerException("System is not configured properly, 'sourcePath' input parameter missing.");\r
+               }\r
+               if (processedFolder == null) {\r
+                       logger.error(jobRuntime.getMarker(), "A folyamat 'processedFolder' bemeneti paramétere üres.");\r
+                       throw new NullPointerException("System is not configured properly, 'processedFolder' input parameter missing.");\r
+               }\r
+               this.processedFolder = processedFolder;\r
+\r
+               if (targetPath == null) {\r
+                       logger.error(jobRuntime.getMarker(), "A folyamat 'targetPath' bemeneti paramétere üres.");\r
+                       throw new NullPointerException("System is not configured properly, 'targetPath' input parameter missing.");\r
+               }\r
+               this.targetPath = targetPath;\r
+\r
+               db = NoSQLUtils.getNoSQLDB();\r
+               if (db == null) {\r
+                       logger.error(jobRuntime.getMarker(), "Sikertelen kapcsolódás a NoSQL adatbázishoz.");\r
+                       throw new NullPointerException("Can not connect to NoSQL database.");\r
+               }\r
+\r
+       }\r
+\r
+       private void storeMetadataPosition(Path csvFilePath, List<String> dataList, String name, Map<String, Integer> metadatas) throws Exception {\r
+               int pos = dataList.indexOf(name);\r
+               if (pos < 0)\r
+                       throw new Exception(String.format("A '%s' MORPHEUS állományban nem található a '%s' mező.", csvFilePath.getFileName(), MATERIAL_ID));\r
+               metadatas.put(name, pos);\r
+       }\r
+\r
+}\r
index f2bcef4317f391567f8d70b9c230503b6bb9a17a..1e4646e60dec8f9173495f5b2da72ed04f9f9443 100644 (file)
@@ -25,5 +25,8 @@
        <description>ZK performance monitor</description>\r
        <listener-class>org.zkoss.performance.monitor.PerformanceMeter</listener-class>\r
     </listener>\r
+       <listener>\r
+               <listener-class>user.jobengine.zk.util.LifeCycleListener</listener-class>\r
+       </listener>\r
        \r
 </zk>
\ No newline at end of file
index 7f68e6687ff725b78e2281064f6e01cd4ddeeaa0..3859e8bdaa81a2fd845248b5db1e1061371ee113 100644 (file)
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
+\r
 <?init class="user.jobengine.zk.util.AuthInitiator"?>\r
 <zk xmlns:w="http://www.zkoss.org/2005/zk/client">\r
        <style src="/css/archivum.css" />\r
index 765a5bf3e18da5df2bcc430d514971ff11368a10..1b7bdb4b5a38ddeb501ec7bbaa5ceaa3112bd29d 100644 (file)
@@ -35,7 +35,7 @@
                <div height="100%" width="100%" style="background: #e3e3e3" align="left">\r
                        <groupbox height="94%" closable="false">\r
                                <caption sclass="boldfont" label="Aktív folyamatok" />\r
-                               <listbox id="lbJobList" sizedByContent="false" model="@load(jlm.jobList)" multiple="true" pagingPosition="top" mold="paging" autopaging="false" vflex="true" checkmark="true" \r
+                               <listbox id="lbJobList" sizedByContent="false" model="@load(jlm.jobList)" multiple="true" pagingPosition="top" mold="paging" autopaging="true" vflex="true" checkmark="true" \r
                                        onSelect="@command('selectJob')" style="border: none; background: #e3e3e3 !important;" oddRowSclass="listbox-odd-style" sclass="listbox-normal-style" \r
                                        emptyMessage="Nincs futó folyamat.">\r
                                       <listhead sizable="true">\r
diff --git a/server/user.jobengine.osgi.server/pages/missingmaterials.zul b/server/user.jobengine.osgi.server/pages/missingmaterials.zul
new file mode 100644 (file)
index 0000000..5163b09
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" ?>\r
+<?init class="user.jobengine.zk.util.AdminAuthInitiator"?>\r
+<zk xmlns:w="http://www.zkoss.org/2005/zk/client" xmlns:ca="client/attribute">\r
+       <custom-attributes org.zkoss.zul.listbox.rod="true" />\r
+       <custom-attributes org.zkoss.zul.listbox.initRodSize="50" />\r
+       <custom-attributes org.zkoss.zul.listbox.preloadSize="50" />\r
+       <div id="scdiv" width="100%" height="100%" apply="org.zkoss.bind.BindComposer"\r
+               viewModel="@id('jlm') @init('user.jobengine.zk.model.MissingMaterialsModel')">\r
+\r
+               <space bar="false" />\r
+\r
+               <div align="left" width="100%">\r
+                       <space bar="false" />\r
+                       <button label="Importálás" onClick="@command('executeJob')" autodisable="self" />\r
+               </div>\r
+\r
+               <div height="100%" width="100%" style="background: #e3e3e3" align="left">\r
+                       <groupbox height="94%" closable="false">\r
+                               <caption sclass="boldfont" label="Hiányzó adásanyagok" />\r
+                               <listbox id="lbJobList" sizedByContent="false" model="@load(jlm.jobList)" multiple="true" pagingPosition="top" mold="paging" autopaging="true"\r
+                                       vflex="true" checkmark="true" onSelect="@command('selectJob')" style="border: none; background: #e3e3e3 !important;" oddRowSclass="listbox-odd-style"\r
+                                       sclass="listbox-normal-style" emptyMessage="Nincs hiányzó anyag.">\r
+                                       <listhead sizable="true">\r
+                                               <listheader label="Adásbakerülés" hflex="min" align="left" sort="auto" />\r
+                                               <listheader label="Adásanyag" hflex="min" align="left" sort="auto" />\r
+                                               <listheader label="Importálva" hflex="min" align="left" sort="auto" />\r
+                                               <listheader label="Elérhetőség" hflex="min" align="left" sort="auto" />\r
+                                       </listhead>\r
+\r
+                                       <template name="model">\r
+                                               <listitem>\r
+                                                       <listcell label="@load(each.TimetoAir)" />\r
+                                                       <listcell label="@load(each.MaterialID)" />\r
+                                                       <listcell label="@load(each.Imported)" />\r
+                                                       <listcell label="@load(each.Status)" />\r
+                                               </listitem>\r
+                                       </template>\r
+                               </listbox>\r
+                       </groupbox>\r
+               </div>\r
+\r
+       </div>\r
+\r
+</zk>
\ No newline at end of file
index 7a0f80800b89f4a81e945788ca81a25dde9c5ab7..481f07203fb05f7b0d4193dc37e2d42f36ef88c9 100644 (file)
@@ -238,7 +238,7 @@ public class JobEngine implements IJobEngine {
                try {
                        logger.debug("{} adding to run queue", jobRuntime);
                        if (jobRuntime.getIp() == 0 && !jobRuntime.isService() && jobRuntime.getParentJobId() == 0)
-                               logger.info(jobRuntime.getMarker(), "A '{}' folyamat elindult", jobRuntime.getName());
+                               logger.info(jobRuntime.getMarker(), "A '{}' folyamat elindult.", jobRuntime.getName());
                        runQueue.put(jobRuntime);
                } catch (Exception e) {
                        logger.error(e.getMessage(), e);
@@ -683,9 +683,9 @@ public class JobEngine implements IJobEngine {
                        logger.info("--- {} removed from VM", jobRuntime);
                        if (!jobRuntime.isService() && jobRuntime.getParentJobId() == 0) {
                                if (JobStatus.FINISHED.equals(jobRuntime.getStatus()))
-                                       logger.info(jobRuntime.getFinishMarker(), "A '{}' folyamat futása sikeresen véget ért", jobRuntime.getName());
+                                       logger.info(jobRuntime.getFinishMarker(), "A '{}' folyamat futása sikeresen véget ért.", jobRuntime.getName());
                                else
-                                       logger.error(jobRuntime.getFinishMarker(), "A '{}' folyamat futása megszakadt", jobRuntime.getName());
+                                       logger.error(jobRuntime.getFinishMarker(), "A '{}' folyamat futása megszakadt.", jobRuntime.getName());
                        }
                }
 
@@ -835,7 +835,8 @@ public class JobEngine implements IJobEngine {
                        result.setName(name);
                        result.setParameters(parameters);
                        result.setService(program.getTemplate().isService());
-                       result.setParentJobId(parent.getId());
+                       if (parent != null)
+                               result.setParentJobId(parent.getId());
                        if (statusListener != null)
                                result.addEventListener(statusListener);
                        submit(result);
index b47e93d72baf4937e6a47100448a8614b624c69f..af53871935ffff00b9fa23b1a569684e083899f1 100644 (file)
@@ -13,6 +13,8 @@ import org.quartz.jobs.NativeJob;
 \r
 import user.jobengine.server.IJobEngine;\r
 import user.jobengine.server.IJobRuntime;\r
+import user.jobengine.server.IJobStatusChangedListener;\r
+import user.jobengine.server.JobEngineException;\r
 \r
 /**\r
  * JobRuntime-ot reprezental, template nev alapjan kulonbozteti meg oket a quartz.\r
@@ -40,6 +42,10 @@ public class ScheduledJob extends NativeJob { //implements InterruptableJob{
                }\r
        }\r
 \r
+       public IJobRuntime doJob(IJobStatusChangedListener statusListener) throws JobEngineException {\r
+               return jobEngine.submit(null, statusListener, templateName, jobName, jobParameters);\r
+       }\r
+\r
        @Override\r
        public void execute(JobExecutionContext context) throws JobExecutionException {\r
                JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();\r
index fb73bd9a621682d2d058e686b5bc314ac6457e90..fb66fee7a91093b1b6ec4e46bbb85387c1ca0749 100644 (file)
@@ -107,7 +107,13 @@ public class EscortFiles {
                if (!statusFolder.exists() || !statusFolder.isDirectory()) {\r
                        Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxrwxrwx");\r
                        FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);\r
-                       Files.createDirectories(statusPath, attr);\r
+\r
+                       try {\r
+                               Files.createDirectories(statusPath, attr);\r
+                       } catch (Exception e) {\r
+                               logger.catching(e);\r
+                               Files.createDirectories(statusPath);\r
+                       }\r
                }\r
        }\r
 }\r
diff --git a/server/user.jobengine.osgi.server/src/user/jobengine/zk/model/BasicDBObjectConverter.java b/server/user.jobengine.osgi.server/src/user/jobengine/zk/model/BasicDBObjectConverter.java
new file mode 100644 (file)
index 0000000..38e4468
--- /dev/null
@@ -0,0 +1,29 @@
+package user.jobengine.zk.model;\r
+\r
+import org.zkoss.bind.BindContext;\r
+import org.zkoss.bind.Converter;\r
+import org.zkoss.zk.ui.Component;\r
+\r
+import com.ibm.nosql.json.api.BasicDBObject;\r
+\r
+class BasicDBObjectConverter implements Converter {\r
+\r
+       @Override\r
+       public Object coerceToBean(Object data, Component component, BindContext ctx) {\r
+               return null;\r
+       }\r
+\r
+       @Override\r
+       public Object coerceToUi(Object data, Component component, BindContext ctx) {\r
+               String string = "";\r
+               try {\r
+                       System.out.println("Current data: " + data);\r
+                       String field = (String) ctx.getConverterArg("field");\r
+                       BasicDBObject dbObject = (BasicDBObject) data;\r
+                       string = dbObject.getString(field);\r
+               } catch (Exception e) {\r
+               }\r
+               return string;\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/server/user.jobengine.osgi.server/src/user/jobengine/zk/model/MissingMaterialsModel.java b/server/user.jobengine.osgi.server/src/user/jobengine/zk/model/MissingMaterialsModel.java
new file mode 100644 (file)
index 0000000..e32ae11
--- /dev/null
@@ -0,0 +1,118 @@
+package user.jobengine.zk.model;\r
+\r
+import java.util.List;\r
+import java.util.concurrent.CountDownLatch;\r
+\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+import org.zkoss.bind.annotation.Command;\r
+import org.zkoss.bind.annotation.Init;\r
+import org.zkoss.zul.ListModelList;\r
+import org.zkoss.zul.Messagebox;\r
+\r
+import com.ibm.nosql.json.api.BasicDBObject;\r
+import com.ibm.nosql.json.api.DB;\r
+import com.ibm.nosql.json.api.DBCollection;\r
+import com.ibm.nosql.json.api.DBCursor;\r
+\r
+import user.commons.JobStatus;\r
+import user.commons.nosql.NoSQLUtils;\r
+import user.jobengine.server.IJobEngine;\r
+import user.jobengine.server.IJobStatusChangedListener;\r
+import user.jobengine.server.JobEngine;\r
+import user.jobengine.server.JobStatusChangedEvent;\r
+import user.jobengine.server.scheduler.ScheduledJob;\r
+import user.jobengine.server.scheduler.SchedulerService;\r
+\r
+public class MissingMaterialsModel extends BaseModel implements IJobStatusChangedListener {\r
+       private static final Logger logger = LogManager.getLogger();\r
+\r
+       private static final String TEMPLATE = "template";\r
+       private static final String IMPORT_TEMPLATE = "import-morpheus-missing-materials.xml";\r
+       private static final String COLLECTION_NAME = "missing_materials";\r
+       private ListModelList<BasicDBObject> jobList = new ListModelList<BasicDBObject>();\r
+       private BasicDBObject selectedJob = null;\r
+       private IJobEngine jobEngine = null;\r
+       private CountDownLatch latch;\r
+\r
+       @Command\r
+       public void executeJob() {\r
+               try {\r
+                       SchedulerService scheduler = jobEngine.getScheduler();\r
+                       List<BasicDBObject> jobs = NoSQLUtils.asList(scheduler.getScheduleJobs());\r
+                       BasicDBObject importJob = null;\r
+                       for (BasicDBObject job : jobs) {\r
+                               if (IMPORT_TEMPLATE.equals(job.getString(TEMPLATE))) {\r
+                                       importJob = job;\r
+                                       //logger.info(job.toString());\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       latch = new CountDownLatch(1);\r
+                       ScheduledJob scheduledJob = scheduler.createScheduledJob(importJob);\r
+                       scheduledJob.setJobEngine(jobEngine);\r
+                       scheduledJob.doJob(this);\r
+                       latch.await();\r
+\r
+                       initializeList();\r
+\r
+               } catch (Exception e) {\r
+                       logger.catching(e);\r
+                       Messagebox.show(e.getMessage());\r
+               }\r
+       }\r
+\r
+       public ListModelList<BasicDBObject> getJobList() {\r
+               return jobList;\r
+       }\r
+\r
+       public BasicDBObject getSelectedJob() {\r
+               return this.selectedJob;\r
+       }\r
+\r
+       @Init\r
+       public void init() {\r
+               try {\r
+                       jobList.setMultiple(true);\r
+                       this.jobEngine = JobEngine.getInstance();\r
+\r
+                       if (jobEngine == null)\r
+                               throw new Exception("Internal error! JobEngine instance unavailable.");\r
+                       initializeList();\r
+\r
+               } catch (Exception e) {\r
+                       logger.catching(e);\r
+               }\r
+       }\r
+\r
+       private void initializeList() {\r
+               DB db = NoSQLUtils.getNoSQLDB();\r
+               DBCollection collection = db.getCollection(COLLECTION_NAME);\r
+               DBCursor cursor = collection.find().sort(new BasicDBObject("TimeToAir", -1)).limit(1000);\r
+\r
+               jobList.clear();\r
+               while (cursor.hasNext())\r
+                       jobList.add((BasicDBObject) cursor.next());\r
+\r
+       }\r
+\r
+       @Command\r
+       public void selectJob() {\r
+               //only for notification\r
+       }\r
+\r
+       public void setJobList(ListModelList<BasicDBObject> jobList) {\r
+               this.jobList = jobList;\r
+       }\r
+\r
+       public void setSelectedJob(BasicDBObject selectedJob) {\r
+               this.selectedJob = selectedJob;\r
+       }\r
+\r
+       @Override\r
+       public void statusChanged(JobStatusChangedEvent event) {\r
+               if (JobStatus.FINISHED.equals(event.getStatus()) || JobStatus.SUSPENDED.equals(event.getStatus()))\r
+                       latch.countDown();\r
+       }\r
+}\r
diff --git a/server/user.jobengine.osgi.server/src/user/jobengine/zk/util/LifeCycleListener.java b/server/user.jobengine.osgi.server/src/user/jobengine/zk/util/LifeCycleListener.java
new file mode 100644 (file)
index 0000000..1464e89
--- /dev/null
@@ -0,0 +1,54 @@
+package user.jobengine.zk.util;\r
+\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+import org.zkoss.zk.ui.Component;\r
+import org.zkoss.zk.ui.Desktop;\r
+import org.zkoss.zk.ui.Page;\r
+import org.zkoss.zk.ui.ShadowElement;\r
+import org.zkoss.zk.ui.util.UiLifeCycle;\r
+\r
+public class LifeCycleListener implements UiLifeCycle {\r
+       private static final Logger logger = LogManager.getLogger();\r
+\r
+       @Override\r
+       public void afterComponentAttached(Component component, Page page) {\r
+               //logger.info("afterComponentAttached {} {}", component.getClass(), page);\r
+       }\r
+\r
+       @Override\r
+       public void afterComponentDetached(Component component, Page page) {\r
+               //logger.info("afterComponentDetached {} {}", component.getClass(), page);\r
+       }\r
+\r
+       @Override\r
+       public void afterComponentMoved(Component arg0, Component arg1, Component arg2) {\r
+               // TODO Auto-generated method stub\r
+\r
+       }\r
+\r
+       @Override\r
+       public void afterPageAttached(Page arg0, Desktop arg1) {\r
+               // TODO Auto-generated method stub\r
+\r
+       }\r
+\r
+       @Override\r
+       public void afterPageDetached(Page arg0, Desktop arg1) {\r
+               // TODO Auto-generated method stub\r
+\r
+       }\r
+\r
+       @Override\r
+       public void afterShadowAttached(ShadowElement arg0, Component arg1) {\r
+               // TODO Auto-generated method stub\r
+\r
+       }\r
+\r
+       @Override\r
+       public void afterShadowDetached(ShadowElement arg0, Component arg1) {\r
+               // TODO Auto-generated method stub\r
+\r
+       }\r
+\r
+}\r