git-tfs-id: [http://tfs.userrendszerhaz.hu:8080/tfs/DefaultCollection]$/MediaCube...
authorvasary.daniel <TFS\vasary.daniel>
Thu, 29 Jul 2021 18:59:14 +0000 (18:59 +0000)
committervasary.daniel <TFS\vasary.daniel>
Thu, 29 Jul 2021 18:59:14 +0000 (18:59 +0000)
19 files changed:
server/-product/production/AMC/jobs/templates/PB-archive-checker.xml [moved from server/-product/production/AMC/jobs/templates/PBARCHIVE-archive-checker.xml with 100% similarity]
server/-product/production/MEDIAVIVANTIS/jobs/steps/DeleteFile.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/IntegrationTestStep.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/PrepareRemoteTranscodeStep.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/SaveMediaProxy.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/TransferStep.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/EscortFiles.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalCommand.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalCommandExecutor.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalProfile.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalProfilesConfig.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/IExternalCallback.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ItemManagerExtensions.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/MediaCubeClient.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/MetadataType.java [new file with mode: 0644]
server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/MetadataTypeDetector.java [new file with mode: 0644]
server/user.jobengine.executors/src/user/jobengine/server/steps/EscortFileUpdaterStep.java [new file with mode: 0644]
server/user.jobengine.executors/src/user/jobengine/server/steps/PBARCHIVETransferFromStep.java
server/user.jobengine.executors/src/user/jobengine/server/steps/PBArchiveCheckerStep.java

diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/DeleteFile.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/DeleteFile.java
new file mode 100644 (file)
index 0000000..539faf7
--- /dev/null
@@ -0,0 +1,22 @@
+package user.jobengine.server.steps;\r
+\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+\r
+import user.commons.RemoteFile;\r
+import user.commons.StoreUri;\r
+\r
+public class DeleteFile extends JobStep {\r
+       private static final Logger logger = LogManager.getLogger();\r
+\r
+       @StepEntry\r
+       public Object[] execute(String fileName, StoreUri tempStoreUri) throws Exception {\r
+               try {\r
+                       RemoteFile remoteFile = tempStoreUri.getRemoteFile(fileName);\r
+                       tempStoreUri.delete(remoteFile);\r
+               } catch (Exception e) {\r
+                       logger.warn(getJobRuntime().getSessionMarker(), e.getMessage());\r
+               }\r
+               return null;\r
+       }\r
+}\r
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/IntegrationTestStep.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/IntegrationTestStep.java
new file mode 100644 (file)
index 0000000..317edfe
--- /dev/null
@@ -0,0 +1,128 @@
+package user.jobengine.server.steps;\r
+\r
+import java.nio.file.Files;\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\r
+import java.util.concurrent.CountDownLatch;\r
+\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+\r
+import user.commons.ListUtils;\r
+import user.jobengine.db.ArchivedMedia;\r
+import user.jobengine.db.Item;\r
+import user.jobengine.db.Media;\r
+import user.jobengine.server.steps.shared.ItemManagerExtensions;\r
+\r
+public class IntegrationTestStep extends JobStep {\r
+       private static final Logger logger = LogManager.getLogger();\r
+       private ArchivedMedia archivedMedia;\r
+\r
+       private void _00_test_cancelable() throws Exception {\r
+               CountDownLatch finishLatch = new CountDownLatch(1);\r
+               getEngine().submit(null, e -> {\r
+                       if (e.isRuntimeTerminated())\r
+                               finishLatch.countDown();\r
+               }, "cancelable.xml", "Test cancelable", ListUtils.asMap("param", 1));\r
+               finishLatch.await();\r
+               logger.info("_00_test_cancelable SUCCESS");\r
+       }\r
+\r
+       private void _01_test_retrieve_ondemand() throws Exception {\r
+               archivedMedia = new ArchivedMedia();\r
+               Media media = getManager().getMedia(15285);\r
+               Item item = getManager().getItem(media.getItemId());\r
+               archivedMedia.setItem(item);\r
+               archivedMedia.setMedia(media);\r
+\r
+               CountDownLatch finishLatch = new CountDownLatch(1);\r
+               getEngine().submit(null, e -> {\r
+                       if (e.isRuntimeTerminated())\r
+                               finishLatch.countDown();\r
+\r
+               }, "retrieve-ondemand.xml", "Test retrieve-ondemand",\r
+                               ListUtils.asMap("globalRetrievePath", "file://10.11.1.100", "localRetrievePath", "/mediacube/data", "materialOutputFolder", "/",\r
+                                               "promoOutputFolder", "/", "advertisementOutputFolder", "/", "octopusOutputFolder", "/", "genericOutputFolder", "/",\r
+                                               "onlineOutputFolder", "/", "killDateDays", -1, "nexioAgency", "ARCHIVE_RESTORE", "nexioPort", 2098, "nexioUserName", "administrator",\r
+                                               "nexioPassword", "system", "archivedMedia", archivedMedia, "successRecipient", "vasary@elgekko.net", "houseId",\r
+                                               archivedMedia.getMedia().getHouseId(), "targetPathType", "0"));\r
+\r
+               finishLatch.await();\r
+               Path output = Paths.get("/mediacube/data", archivedMedia.getMedia().getHouseId(),\r
+                               archivedMedia.getMedia().getHouseId() + "-ARCH-" + archivedMedia.getMedia().getMediaFileRealName());\r
+               if (!output.toFile().exists())\r
+                       throw new Exception("File not exists: " + output);\r
+\r
+               logger.info("_01_test_retrieve_ondemand SUCCESS");\r
+       }\r
+\r
+       private void _02_test_archive_material() throws Exception {\r
+               Path input = Paths.get("/mediacube/data", archivedMedia.getMedia().getHouseId(),\r
+                               archivedMedia.getMedia().getHouseId() + "-ARCH-" + archivedMedia.getMedia().getMediaFileRealName());\r
+\r
+               String outputName = "IntegrationTest_" + System.currentTimeMillis() + ".mxf";\r
+               Path ouptput = Paths.get(input.getParent().toString(), outputName);\r
+               Files.copy(input, ouptput);\r
+               if (!ouptput.toFile().exists())\r
+                       throw new Exception("File not exists: " + ouptput);\r
+\r
+               ArchiveItem archiveItem = new ArchiveItem();\r
+               archiveItem.setMediaFile(ouptput.toString());\r
+               archiveItem.setItemHouseId(outputName);\r
+               archiveItem.setItemTitle(outputName);\r
+               archiveItem.setMediaHouseId(outputName);\r
+               archiveItem.setMediaTitle(outputName);\r
+               archiveItem.setMediaType("Generic");\r
+\r
+               CountDownLatch finishLatch = new CountDownLatch(1);\r
+               getEngine().submit(null, e -> {\r
+                       if (e.isRuntimeTerminated())\r
+                               finishLatch.countDown();\r
+               }, "archive-material.xml", "Test archive-material", ListUtils.asMap("archiveItem", archiveItem, "killDateDays", 0));\r
+               finishLatch.await();\r
+\r
+               if (!ItemManagerExtensions.isArchived(getManager(), ouptput))\r
+                       throw new Exception("File not archived: " + ouptput);\r
+\r
+               Files.delete(ouptput);\r
+\r
+               logger.info("_02_test_archive_material SUCCESS");\r
+       }\r
+\r
+       private void _03_test_delete_materials() throws Exception {\r
+               Path output = Paths.get("/mediacube/data", archivedMedia.getMedia().getHouseId(),\r
+                               archivedMedia.getMedia().getHouseId() + "-ARCH-" + archivedMedia.getMedia().getMediaFileRealName());\r
+               String source = output.getParent().toString();\r
+\r
+               CountDownLatch finishLatch = new CountDownLatch(1);\r
+               getEngine().submit(null, e -> {\r
+                       if (e.isRuntimeTerminated())\r
+                               finishLatch.countDown();\r
+               }, "delete-materials.xml", "Test delete-materials", ListUtils.asMap("sourcePath", source, "skipArchiveCheck", true));\r
+               finishLatch.await();\r
+\r
+               if (output.toFile().exists())\r
+                       throw new Exception("File exists: " + output);\r
+       }\r
+\r
+       @StepEntry\r
+       public Object[] execute() throws Exception {\r
+               getJobRuntime().setDescription("_00_test_cancelable");\r
+               _00_test_cancelable();\r
+               setProgress(25);\r
+\r
+               getJobRuntime().setDescription("_01_test_retrieve_ondemand");\r
+               _01_test_retrieve_ondemand();\r
+               setProgress(50);\r
+\r
+               getJobRuntime().setDescription("_02_test_archive_material");\r
+               _02_test_archive_material();\r
+               setProgress(75);\r
+\r
+               getJobRuntime().setDescription("_03_test_delete_materials");\r
+               _03_test_delete_materials();\r
+               setProgress(100);\r
+               return null;\r
+       }\r
+\r
+}\r
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/PrepareRemoteTranscodeStep.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/PrepareRemoteTranscodeStep.java
new file mode 100644 (file)
index 0000000..5116b1e
--- /dev/null
@@ -0,0 +1,48 @@
+package user.jobengine.server.steps;\r
+\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\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
+\r
+import user.commons.configuration.SystemConfiguration;\r
+\r
+public class PrepareRemoteTranscodeStep extends JobStep {\r
+       static private final Logger logger = LogManager.getLogger();\r
+       private static boolean RANDOMIZE_ARCHIVES = SystemConfiguration.getInstance().value("tsm.randomize-archives",\r
+                       false);\r
+\r
+       @StepEntry\r
+       public Object[] execute(String profileName, String fileName) throws Exception {\r
+               String hiResRoot = "m:/";\r
+               String lowResRoot = "m:/lowres";\r
+\r
+               Path inputPath = Paths.get(hiResRoot, fileName);\r
+\r
+               String realFileName = fileName;\r
+\r
+               if (RANDOMIZE_ARCHIVES)\r
+                       realFileName = realFileName.substring(9);\r
+\r
+               String outFileName = realFileName.substring(0, realFileName.lastIndexOf(".")) + ".mp4";\r
+\r
+               Path relativeOutputPath = null;\r
+               if (realFileName.length() > 2)\r
+                       relativeOutputPath = Paths.get(realFileName.substring(0, 1), realFileName.substring(1, 2),\r
+                                       realFileName.substring(2, 3), outFileName);\r
+               else\r
+                       relativeOutputPath = Paths.get("0", outFileName);\r
+\r
+               BasicDBObject parameters = new BasicDBObject();\r
+               parameters.put("profile", profileName);\r
+               parameters.put("input", inputPath.toString());\r
+               parameters.put("output", Paths.get(lowResRoot, relativeOutputPath.toString()).toString());\r
+\r
+               logger.info("Prepared for remote transode {}", parameters);\r
+               return new Object[] { parameters, relativeOutputPath.toString() };\r
+       }\r
+\r
+}\r
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/SaveMediaProxy.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/SaveMediaProxy.java
new file mode 100644 (file)
index 0000000..3f0f667
--- /dev/null
@@ -0,0 +1,22 @@
+package user.jobengine.server.steps;\r
+\r
+import user.jobengine.db.IItemManager;\r
+import user.jobengine.db.Media;\r
+import user.jobengine.db.MediaFile;\r
+import user.jobengine.db.Store;\r
+\r
+public class SaveMediaProxy extends JobStep {\r
+\r
+       @StepEntry\r
+       public Object[] execute(Media media, String proxyRelativePath) throws Exception {\r
+               IItemManager manager = getManager();\r
+               Store store = manager.getCurrentLowresStore();\r
+               MediaFile mediaFile = new MediaFile();\r
+               mediaFile.setMedia(media);\r
+               mediaFile.setStore(store);\r
+               mediaFile.setFileType(manager.getFileType("Low-res"));\r
+               mediaFile.setRelativePath(proxyRelativePath);\r
+               manager.add(mediaFile);\r
+               return null;\r
+       }\r
+}\r
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/TransferStep.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/TransferStep.java
new file mode 100644 (file)
index 0000000..c10084f
--- /dev/null
@@ -0,0 +1,110 @@
+package user.jobengine.server.steps;\r
+\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\r
+\r
+import org.apache.commons.net.ftp.FTPClient;\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+\r
+import user.commons.RemoteFile;\r
+import user.commons.StoreUri;\r
+import user.commons.remotestore.FtpDirectoryLister;\r
+import user.commons.remotestore.RemoteStoreProtocol;\r
+import user.jobengine.db.Store;\r
+\r
+public class TransferStep extends JobStep {\r
+       private static final String DOT_PART = ".part";\r
+       private static final Logger logger = LogManager.getLogger();\r
+\r
+       private void copy(StoreUri sourceStoreUri, String sourceFileName, StoreUri targetStoreUri, String targetFileName) throws Exception {\r
+               String currentTargetFileName = targetFileName;\r
+\r
+               boolean renameAfterCopy = false;\r
+               boolean renameAfterFTP = false;\r
+               if (getTmpExtension() != null) {\r
+                       if (RemoteStoreProtocol.LOCAL.equals(targetStoreUri.getProtocol())) {\r
+                               currentTargetFileName += getTmpExtension();\r
+                               renameAfterCopy = true;\r
+                       }\r
+                       Store targetStore = getManager().getStore(targetStoreUri.getStoreId());\r
+\r
+                       if (RemoteStoreProtocol.FTP.equals(targetStoreUri.getProtocol()) && !"NEXIO1".equals(targetStore.getName())\r
+                                       && !"NEXIO2".equals(targetStore.getName())) {\r
+                               currentTargetFileName += getTmpExtension();\r
+                               renameAfterFTP = true;\r
+                       }\r
+               }\r
+\r
+               sourceStoreUri.transferFrom(targetStoreUri, sourceFileName, currentTargetFileName);\r
+\r
+               logger.info(getMarker(), "Transfer of {} completed from {} to {}", sourceFileName, sourceStoreUri, currentTargetFileName);\r
+\r
+               if (renameAfterCopy) {\r
+                       Path tmpTargetFile = Paths.get(targetStoreUri.toString(true), currentTargetFileName);\r
+                       Path targetFile = Paths.get(targetStoreUri.toString(true), targetFileName);\r
+                       try {\r
+                               logger.info(getMarker(), "Renaming LOCAL file from {} to {} on {}", currentTargetFileName, targetFileName, sourceStoreUri);\r
+                               tmpTargetFile.toFile().renameTo(targetFile.toFile());\r
+                       } catch (Exception e) {\r
+                               logger.error(getMarker(), e.getMessage());\r
+                       }\r
+               }\r
+               if (renameAfterFTP) {\r
+                       try {\r
+                               FtpDirectoryLister lister = (FtpDirectoryLister) targetStoreUri.getLister();\r
+                               FTPClient client = lister.connect();\r
+                               logger.info(getMarker(), "Renaming FTP file from {} to {} on {}", currentTargetFileName, targetFileName, sourceStoreUri);\r
+                               client.rename(currentTargetFileName, targetFileName);\r
+                       } catch (Exception e) {\r
+                               logger.error(getMarker(), e.getMessage());\r
+                       } finally {\r
+                               targetStoreUri.cleanUp();\r
+                       }\r
+               }\r
+       }\r
+\r
+       @StepEntry\r
+       public Object[] execute(StoreUri sourceStoreUri, String sourceFileName, StoreUri targetStoreUri, String targetFileName) throws Exception {\r
+               try {\r
+                       getJobRuntime().setCancelable(false);\r
+\r
+                       Store sourceStore = getManager().getStore(sourceStoreUri.getStoreId());\r
+                       Store targetStore = getManager().getStore(targetStoreUri.getStoreId());\r
+\r
+                       setDescription("{} -> {} : {}", sourceStore.getName(), targetStore.getName(), sourceFileName);\r
+\r
+                       sourceStoreUri.addProgressListener(e -> setProgress(e.getProgress()));\r
+\r
+                       StoreUri currentTargetStoreUri = getTargetStoreUri(targetStoreUri);\r
+\r
+                       try {\r
+                               RemoteFile remoteFile = currentTargetStoreUri.getRemoteFile(targetFileName);\r
+                               if (remoteFile != null) {\r
+                                       logger.info("File {} already exists on target {}, skipping transfer", targetFileName, targetStore.getName());\r
+                               }\r
+                       } catch (Exception e) {\r
+                       }\r
+\r
+                       copy(sourceStoreUri, sourceFileName, currentTargetStoreUri, targetFileName);\r
+               } catch (Exception e) {\r
+                       logger.error(getMarker(), "Error in transfer of {} when copying from {} to {}.", sourceFileName, sourceStoreUri, targetStoreUri);\r
+                       throw e;\r
+               } finally {\r
+                       getJobRuntime().setDescription(null);\r
+                       if (sourceStoreUri != null)\r
+                               sourceStoreUri.cleanUp();\r
+                       if (targetStoreUri != null)\r
+                               targetStoreUri.cleanUp();\r
+               }\r
+               return null;\r
+       }\r
+\r
+       protected StoreUri getTargetStoreUri(StoreUri targetStoreUri) {\r
+               return targetStoreUri;\r
+       }\r
+\r
+       protected String getTmpExtension() {\r
+               return DOT_PART;\r
+       }\r
+}\r
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/EscortFiles.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/EscortFiles.java
new file mode 100644 (file)
index 0000000..e504099
--- /dev/null
@@ -0,0 +1,348 @@
+package user.jobengine.server.steps.shared;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.io.StringWriter;\r
+import java.io.UnsupportedEncodingException;\r
+import java.nio.file.Files;\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\r
+import java.nio.file.attribute.FileAttribute;\r
+import java.nio.file.attribute.PosixFilePermission;\r
+import java.nio.file.attribute.PosixFilePermissions;\r
+import java.text.SimpleDateFormat;\r
+import java.util.Calendar;\r
+import java.util.Date;\r
+import java.util.Set;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.transform.OutputKeys;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerConfigurationException;\r
+import javax.xml.transform.TransformerException;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.TransformerFactoryConfigurationError;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
+\r
+import org.apache.commons.lang.StringUtils;\r
+import org.apache.commons.net.ftp.FTPClient;\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+import org.apache.logging.log4j.Marker;\r
+import org.apache.logging.log4j.message.Message;\r
+import org.w3c.dom.DOMImplementation;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+import com.ibm.nosql.json.api.BasicDBObject;\r
+import com.ibm.nosql.json.util.JSON;\r
+\r
+import user.commons.CalendarUtils;\r
+import user.commons.MediaCubeMarker;\r
+import user.commons.StoreUri;\r
+import user.commons.remotestore.FtpDirectoryLister;\r
+\r
+public class EscortFiles {\r
+       private static final String RECORDTIMESTAMP = "RecordTimeStamp";\r
+       private static final String MODIFIEDTIMESTAMP = "ModifiedTimeStamp";\r
+       public static final String DOT_CATCHED = ".catched";\r
+       public static final String DOT_JSON = ".json";\r
+       private static final Logger logger = LogManager.getLogger();\r
+       private static final String EXTENDEDAGENCY = "ExtendedAgency";\r
+       private static final String EXTENDEDDESCRIPTION = "ExtendedDescription";\r
+       private static final String KILLDATE = "KillDate";\r
+       private static final String FORMAT_KILLDATE = "MM-dd-yyyy";\r
+       private static final String EXTENDEDID = "extendedId";\r
+       private static final String ID = "ID";\r
+       private static final String KILLDATE_FILENAME = "%s.%s.killdate";\r
+       private static final String FORMAT_KILLDATENAME = "yyyyMMdd";\r
+       public static final String STATUSFOLDER = ".STATUS";\r
+       public static final String CONFLICTFOLDER = ".CONFLICT";\r
+\r
+       public static String composeKillDate(int days) {\r
+               Calendar killDate = Calendar.getInstance();\r
+               killDate.add(Calendar.DAY_OF_YEAR, days);\r
+               SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT_KILLDATENAME);\r
+               return dateFormat.format(killDate.getTime());\r
+       }\r
+       /*\r
+        * <?xml version="1.0" encoding="UTF-16"?> <ID extendedId="aaaaaaa">\r
+        * <KillDate>02-02-2018</KillDate> <ExtendedDescription>TEST\r
+        * TEST</ExtendedDescription> <ExtendedAgency>AGENT AGENT</ExtendedAgency> </ID>\r
+        */\r
+\r
+       private static String composeKillDateFileName(String fileName, int days) {\r
+               return String.format(KILLDATE_FILENAME, fileName, composeKillDate(days));\r
+       }\r
+\r
+       public static void createCatchedFile(Path escortFile) throws IOException {\r
+               Path catchedFilePath = Paths.get(escortFile.toString() + DOT_CATCHED);\r
+               Files.createFile(catchedFilePath);\r
+       }\r
+\r
+       public static void createFellow(String escortFile, String extension) throws IOException {\r
+               Files.copy(Paths.get(escortFile), Paths.get(escortFile + "." + extension));\r
+       }\r
+\r
+       /***\r
+        * A media eleresi utjan alapjan a .STATUS almappaban letrehozza a .catch fajlt.\r
+        *\r
+        * @param mediaFile\r
+        * @throws IOException\r
+        */\r
+       public static void createMediaCatch(Path mediaFile) throws IOException {\r
+               Path catchedFile = createMediaCathFilePath(mediaFile);\r
+               ensureUNCFolder(catchedFile.getParent());\r
+               Files.createFile(catchedFile);\r
+       }\r
+\r
+       public static Path createMediaCathFilePath(Path mediaFile) {\r
+               String fileName = mediaFile.getFileName().toString() + DOT_CATCHED;\r
+               return Paths.get(mediaFile.getParent().toString(), STATUSFOLDER, fileName);\r
+       }\r
+\r
+       public static void createMetadata(String filePath, String fileName, String metadata) throws IOException {\r
+               ensureUNCFolder(filePath, STATUSFOLDER);\r
+               String metadataFileName = fileName + DOT_JSON;\r
+               Path metadataPath = Paths.get(filePath, STATUSFOLDER, metadataFileName);\r
+               Files.write(metadataPath, metadata.getBytes());\r
+       }\r
+\r
+       public static boolean createMetadataIfNotExists(String filePath, String fileName, String metadata)\r
+                       throws IOException {\r
+               boolean result = false;\r
+               if (!EscortFiles.isMetadataExists(filePath, fileName)) {\r
+                       EscortFiles.createMetadata(filePath, fileName, metadata);\r
+                       result = true;\r
+               }\r
+               return result;\r
+       }\r
+\r
+       public static void createMorpheusXML(String filePath, String fileName, String content) throws IOException {\r
+               ensureUNCFolder(filePath, STATUSFOLDER);\r
+               Path xmlPath = Paths.get(filePath, fileName);\r
+               if (Files.exists(xmlPath))\r
+                       throw new IOException(String.format("Az '%s' Ã¡llomány már létezik.", xmlPath));\r
+               Files.write(xmlPath, content.getBytes());\r
+       }\r
+\r
+       public static byte[] createNEXIODatesMeta(String fileName, Date recorded, Date modified) throws Exception {\r
+               DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+               DocumentBuilder db = dbf.newDocumentBuilder();\r
+               DOMImplementation impl = db.getDOMImplementation();\r
+               Document xmlDocument = impl.createDocument(null, null, null);\r
+\r
+               Element root = xmlDocument.createElement(ID);\r
+               root.setAttribute(EXTENDEDID, fileName);\r
+               // <ModifiedTimeStamp>07-13-2020 (19:36:52)</ModifiedTimeStamp>\r
+               // <RecordTimeStamp>05-18-2013 (18:52:24)</RecordTimeStamp>\r
+               SimpleDateFormat df = new SimpleDateFormat("MM-dd-yyyy (HH:mm:ss)");\r
+               root.appendChild(xmlDocument.createElement(MODIFIEDTIMESTAMP))\r
+                               .appendChild(xmlDocument.createTextNode(df.format(modified)));\r
+               root.appendChild(xmlDocument.createElement(RECORDTIMESTAMP))\r
+                               .appendChild(xmlDocument.createTextNode(df.format(recorded)));\r
+               xmlDocument.appendChild(root);\r
+\r
+               return xmDocumentToString(xmlDocument);\r
+       }\r
+\r
+       public static byte[] createNEXIOKillDateFile(String fileName, Date killDate, String description, String agency)\r
+                       throws Exception {\r
+               DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+               DocumentBuilder db = dbf.newDocumentBuilder();\r
+               DOMImplementation impl = db.getDOMImplementation();\r
+               Document xmlDocument = impl.createDocument(null, null, null);\r
+\r
+               Element root = xmlDocument.createElement(ID);\r
+               root.setAttribute(EXTENDEDID, fileName);\r
+               if (killDate != null) {\r
+                       String sKillDate = CalendarUtils.toString(CalendarUtils.createCalendar(killDate), FORMAT_KILLDATE);\r
+                       root.appendChild(xmlDocument.createElement(KILLDATE)).appendChild(xmlDocument.createTextNode(sKillDate));\r
+               }\r
+\r
+               if (StringUtils.isNotBlank(description))\r
+                       root.appendChild(xmlDocument.createElement(EXTENDEDDESCRIPTION))\r
+                                       .appendChild(xmlDocument.createTextNode(description));\r
+               if (StringUtils.isNotBlank(agency))\r
+                       root.appendChild(xmlDocument.createElement(EXTENDEDAGENCY)).appendChild(xmlDocument.createTextNode(agency));\r
+               xmlDocument.appendChild(root);\r
+\r
+               return xmDocumentToString(xmlDocument);\r
+       }\r
+\r
+       public static Document createNEXIOMeta(byte[] content) throws Exception {\r
+               DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+               DocumentBuilder db = dbf.newDocumentBuilder();\r
+               DOMImplementation impl = db.getDOMImplementation();\r
+               Document xmlDocument = null;\r
+\r
+               try (InputStream is = new ByteArrayInputStream(content)) {\r
+                       xmlDocument = db.parse(is);\r
+               } catch (Exception e) {\r
+                       logger.catching(e);\r
+               }\r
+\r
+               return xmlDocument;\r
+       }\r
+\r
+       public static void createUNCKillDate(String filePath, String fileName, int days, Marker marker) throws IOException {\r
+               ensureUNCFolder(filePath, STATUSFOLDER);\r
+               String killDateFileName = composeKillDateFileName(fileName, days);\r
+               Path killDatePath = Paths.get(filePath, STATUSFOLDER, killDateFileName);\r
+               if (Files.exists(killDatePath))\r
+                       logger.warn(marker, "Az '{}' Ã¡llomány már létezik.", killDatePath);\r
+               else\r
+                       Files.createFile(killDatePath);\r
+       }\r
+\r
+       @SuppressWarnings("unchecked")\r
+       public static <T> T decode(Path escortFile) {\r
+               T result = null;\r
+               try {\r
+                       byte[] bytes = Files.readAllBytes(escortFile);\r
+                       String content = new String(bytes);\r
+                       result = (T) JSON.parse(content);\r
+               } catch (Exception e) {\r
+                       logger.error("Decode error. System message is: ", e.getMessage());\r
+               }\r
+               return result;\r
+       }\r
+\r
+       public static void ensureUNCFolder(Path filePath) throws IOException {\r
+               File folder = filePath.toFile();\r
+               if (!folder.exists() || !folder.isDirectory()) {\r
+                       try {\r
+                               Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxrwxrwx");\r
+                               FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);\r
+                               Files.createDirectories(filePath, attr);\r
+                       } catch (Exception e) {\r
+                               // logger.catching(e);\r
+                               try {\r
+                                       Files.createDirectories(filePath);\r
+                               } catch (Exception e1) {\r
+                                       logger.catching(e1);\r
+                                       throw e1;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       public static void ensureUNCFolder(String filePath, String folderName) throws IOException {\r
+               Path statusPath = Paths.get(filePath, folderName);\r
+               ensureUNCFolder(statusPath);\r
+       }\r
+\r
+       public static boolean isCatchedFileExists(Path escortFile) {\r
+               Path catchedFilePath = Paths.get(escortFile.toString() + DOT_CATCHED);\r
+               return catchedFilePath.toFile().exists();\r
+       }\r
+\r
+       /***\r
+        * A media eleresi utjan alapjan a .STATUS almappaban vizsgalja .catch fajl\r
+        * letezeset.\r
+        *\r
+        * @param mediaFile\r
+        * @return\r
+        */\r
+       public static boolean isMediaCatched(Path mediaFile) {\r
+               Path catchedFile = createMediaCathFilePath(mediaFile);\r
+               return catchedFile.toFile().exists();\r
+       }\r
+\r
+       public static boolean isMetadataExists(String filePath, String fileName) throws IOException {\r
+               boolean result = false;\r
+               String metadataFileName = fileName + DOT_JSON;\r
+               Path metadataPath = Paths.get(filePath, STATUSFOLDER, metadataFileName);\r
+               result = metadataPath.toFile().exists();\r
+               return result;\r
+       }\r
+\r
+       public static void notifyRecipient(Path escortFile, Logger logger, Message msg) {\r
+               if (escortFile.toFile().exists()) {\r
+                       try {\r
+                               BasicDBObject downloadable = EscortFiles.decode(escortFile);\r
+                               String recipientKey = "recipient";\r
+                               if (downloadable.containsKey(recipientKey)) {\r
+                                       String recipient = downloadable.getString(recipientKey);\r
+                                       logger.info(new MediaCubeMarker(recipient, "MediaCube rendszerüzenet"), msg);\r
+                               }\r
+                       } catch (Exception e) {\r
+                               logger.catching(e);\r
+                       }\r
+\r
+               }\r
+       }\r
+\r
+       public static void remove(Path file) {\r
+               try {\r
+                       file.toFile().delete();\r
+               } catch (Exception e) {\r
+                       logger.error("Unable to delete {}", file.toAbsolutePath().toString());\r
+               }\r
+       }\r
+\r
+       public static void removeCatchedFile(Path escortFile) {\r
+               remove(Paths.get(escortFile.toString() + DOT_CATCHED));\r
+       }\r
+\r
+       /***\r
+        * A media eleresi utjan alapjan a .STATUS almappabol torli a .catch fajlt.\r
+        *\r
+        * @param mediaFile\r
+        * @throws IOException\r
+        */\r
+       public static void removeMediaCatch(Path mediaFile) {\r
+               Path catchedFile = createMediaCathFilePath(mediaFile);\r
+               remove(catchedFile);\r
+       }\r
+\r
+       public static void setNEXIOKillDate(int killDateDays, String targetFileName, String nexioAgency, StoreUri targetUri)\r
+                       throws Exception {\r
+               OutputStream outStream = null;\r
+               try {\r
+                       FTPClient targetFTP = ((FtpDirectoryLister) targetUri.getLister()).connect();\r
+                       Calendar killDate = CalendarUtils.createCalendar(new Date());\r
+                       killDate.add(Calendar.DAY_OF_YEAR, killDateDays);\r
+                       if (targetFileName.toLowerCase().contains(".mxf"))\r
+                               targetFileName = targetFileName.substring(0, targetFileName.lastIndexOf('.'));\r
+                       byte[] killDateFile = EscortFiles.createNEXIOKillDateFile(targetFileName, killDate.getTime(), null,\r
+                                       nexioAgency);\r
+                       String xml = targetFileName + ".xml";\r
+                       outStream = targetFTP.storeFileStream(xml);\r
+                       if (outStream == null) {\r
+                               throw new NullPointerException(\r
+                                               "Can not open: " + targetFileName.substring(0, targetFileName.lastIndexOf('.')) + ".xml"\r
+                                                               + " Reply:" + targetFTP.getReplyString());\r
+                       }\r
+                       outStream.write(killDateFile);\r
+                       outStream.flush();\r
+               } catch (Exception e) {\r
+                       throw e;\r
+               } finally {\r
+                       if (outStream != null)\r
+                               outStream.close();\r
+                       targetUri.cleanUp();\r
+               }\r
+       }\r
+\r
+       private static byte[] xmDocumentToString(Document xmlDocument) throws TransformerFactoryConfigurationError,\r
+                       TransformerConfigurationException, TransformerException, IOException, UnsupportedEncodingException {\r
+               DOMSource domSource = new DOMSource(xmlDocument);\r
+               TransformerFactory tf = TransformerFactory.newInstance();\r
+               Transformer transformer = tf.newTransformer();\r
+               transformer.setOutputProperty(OutputKeys.METHOD, "xml");\r
+               transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-16");\r
+               transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
+               StringWriter sw = new StringWriter();\r
+               StreamResult sr = new StreamResult(sw);\r
+               transformer.transform(domSource, sr);\r
+               String result = sw.toString();\r
+               sw.close();\r
+               return result.getBytes("UTF-16");\r
+       }\r
+}\r
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalCommand.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalCommand.java
new file mode 100644 (file)
index 0000000..307f36d
--- /dev/null
@@ -0,0 +1,79 @@
+package user.jobengine.server.steps.shared;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.InputStreamReader;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+\r
+public class ExternalCommand {\r
+       private static final Logger logger = LogManager.getLogger();\r
+       private ExternalProfile profile;\r
+\r
+       public ExternalCommand(ExternalProfile profile) {\r
+               this.profile = profile;\r
+       }\r
+\r
+       public String execute(String input, String output, boolean firstResponse, IExternalCallback responseCallBack) throws Exception {\r
+               List<String> arguments = getArguments(input, output);\r
+               List<String> command = new ArrayList<>();\r
+               command.add(profile.getExecutable());\r
+               command.addAll(arguments);\r
+\r
+               ProcessBuilder processBuilder = new ProcessBuilder();\r
+               processBuilder.command(command);\r
+\r
+               String result = null;\r
+               try {\r
+                       logger.info("Executing : {}", processBuilder.command());\r
+\r
+                       Process process = processBuilder.start();\r
+                       try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {\r
+                               String line = null;\r
+                               while ((line = reader.readLine()) != null) {\r
+                                       logger.debug("Process response: {}", line);\r
+                                       if (responseCallBack != null)\r
+                                               responseCallBack.onResponse(line);\r
+                                       //System.out.println(line);\r
+                                       if (line != null && line.length() > 0) {\r
+                                               result = line;\r
+                                               if (firstResponse)\r
+                                                       break;\r
+                                       }\r
+                               }\r
+                               int exitCode = process.waitFor();\r
+                               if (exitCode != 0) {\r
+                                       StringBuilder msg = new StringBuilder();\r
+                                       try (BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {\r
+                                               String errline = null;\r
+                                               while ((errline = errReader.readLine()) != null) {\r
+                                                       msg.append(errline);\r
+                                               }\r
+                                       } catch (Exception ex) {\r
+                                       }\r
+\r
+                                       throw new Exception("Exited with error code : " + exitCode + ". " + msg);\r
+                               }\r
+                       } catch (Exception e) {\r
+                               throw e;\r
+                       }\r
+               } catch (Exception e) {\r
+                       logger.error(e);\r
+                       throw e;\r
+               }\r
+\r
+               return result;\r
+       }\r
+\r
+       private List<String> getArguments(String input, String output) {\r
+               List<String> result = new ArrayList<>();\r
+\r
+               profile.getArguments().forEach(i -> {\r
+                       result.add(i.replace("%i", input).replace("%o", output));\r
+               });\r
+               return result;\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalCommandExecutor.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalCommandExecutor.java
new file mode 100644 (file)
index 0000000..a34ff7f
--- /dev/null
@@ -0,0 +1,32 @@
+package user.jobengine.server.steps.shared;\r
+\r
+import user.commons.configuration.SystemConfiguration;\r
+\r
+public class ExternalCommandExecutor {\r
+\r
+       public void execute(String profileName, String input, String output, IExternalCallback responseCallBack) throws Exception {\r
+               ExternalCommand externalCommand = getExternalCommand(profileName);\r
+               externalCommand.execute(input, output, false, responseCallBack);\r
+       }\r
+\r
+       private ExternalCommand getExternalCommand(String profileName) throws Exception {\r
+               ExternalProfilesConfig config = SystemConfiguration.getInstance().load("settings/external-commands.yaml", ExternalProfilesConfig.class);\r
+\r
+               if (config == null)\r
+                       throw new Exception("Missing external-commands.yaml configuration");\r
+\r
+               ExternalProfile selectedProfile = null;\r
+               for (ExternalProfile profile : config.getProfiles()) {\r
+                       if (profileName.equals(profile.getName())) {\r
+                               selectedProfile = profile;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if (selectedProfile == null)\r
+                       throw new Exception("Missing profile " + profileName + " in external-commands.yaml configuration");\r
+\r
+               return new ExternalCommand(selectedProfile);\r
+       }\r
+\r
+}\r
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalProfile.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalProfile.java
new file mode 100644 (file)
index 0000000..68e22f4
--- /dev/null
@@ -0,0 +1,33 @@
+package user.jobengine.server.steps.shared;\r
+\r
+import java.util.List;\r
+\r
+public class ExternalProfile {\r
+       private String executable;\r
+       private String name;\r
+       private List<String> arguments;\r
+\r
+       public List<String> getArguments() {\r
+               return arguments;\r
+       }\r
+\r
+       public String getExecutable() {\r
+               return executable;\r
+       }\r
+\r
+       public String getName() {\r
+               return name;\r
+       }\r
+\r
+       public void setArguments(List<String> arguments) {\r
+               this.arguments = arguments;\r
+       }\r
+\r
+       public void setExecutable(String executable) {\r
+               this.executable = executable;\r
+       }\r
+\r
+       public void setName(String name) {\r
+               this.name = name;\r
+       }\r
+}
\ No newline at end of file
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalProfilesConfig.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ExternalProfilesConfig.java
new file mode 100644 (file)
index 0000000..7ef7729
--- /dev/null
@@ -0,0 +1,15 @@
+package user.jobengine.server.steps.shared;\r
+\r
+import java.util.List;\r
+\r
+public class ExternalProfilesConfig {\r
+       private List<ExternalProfile> profiles;\r
+\r
+       public List<ExternalProfile> getProfiles() {\r
+               return profiles;\r
+       }\r
+\r
+       public void setProfiles(List<ExternalProfile> profiles) {\r
+               this.profiles = profiles;\r
+       }\r
+}
\ No newline at end of file
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/IExternalCallback.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/IExternalCallback.java
new file mode 100644 (file)
index 0000000..1e07191
--- /dev/null
@@ -0,0 +1,5 @@
+package user.jobengine.server.steps.shared;\r
+\r
+public interface IExternalCallback {\r
+       void onResponse(String data);\r
+}
\ No newline at end of file
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ItemManagerExtensions.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/ItemManagerExtensions.java
new file mode 100644 (file)
index 0000000..32f17cb
--- /dev/null
@@ -0,0 +1,94 @@
+package user.jobengine.server.steps.shared;\r
+\r
+import java.nio.file.Path;\r
+\r
+import com.ibm.nosql.json.api.BasicDBObject;\r
+\r
+import user.commons.RemoteFile;\r
+import user.commons.StoreUri;\r
+import user.commons.remotestore.RemoteStoreProtocol;\r
+import user.jobengine.db.IItemManager;\r
+import user.jobengine.db.IResultSetConsumer;\r
+import user.jobengine.db.Store;\r
+\r
+public class ItemManagerExtensions {\r
+\r
+       public static BasicDBObject getArchiveInfo(IItemManager manager, long houseid) {\r
+               final BasicDBObject[] result = { null };\r
+               StringBuilder query = new StringBuilder();\r
+               query.append("select count(*) as count, sum(length) as duration FROM media");\r
+               query.append(" ");\r
+               query.append(String.format("where houseid='%d' and itemtypeid = 82", houseid));\r
+               query.append(" ");\r
+               query.append("group by houseid");\r
+               IResultSetConsumer consumer = rs -> {\r
+                       BasicDBObject o = new BasicDBObject();\r
+                       o.put("count", rs.getLong("count"));\r
+                       o.put("duration", rs.getLong("duration"));\r
+                       result[0] = o;\r
+                       return false;\r
+               };\r
+               manager.executeQuery(query.toString(), consumer, null);\r
+               return result[0];\r
+       }\r
+\r
+       public static long getExistingRundownMedia(IItemManager manager, String houseid) {\r
+               final long[] result = new long[] { 0 };\r
+               final String[] idToCheck = new String[] { houseid };\r
+               int pos = houseid.lastIndexOf("-");\r
+               //a hivas a CopyForArchiveNEXIOMaterialsStep-bol is johet, ott meg nincs idobelyegezve a nev!\r
+               if (pos > 0 && houseid.length() - pos > 4)\r
+                       idToCheck[0] = houseid.substring(0, pos);\r
+               MetadataType metadataType = MetadataTypeDetector.GuessMetadataType(idToCheck[0]);\r
+               if (metadataType == MetadataType.OctopusPlaceholder) {\r
+                       StringBuilder query = new StringBuilder();\r
+                       query.append("select mediaid, mediafilehouseid, filename");\r
+                       query.append(" ");\r
+                       query.append(String.format("from vw_rundown_items where mediafilehouseid like '%s%%'", idToCheck[0]));\r
+                       query.append(" ");\r
+                       query.append("order by filename, mediaid");\r
+                       IResultSetConsumer consumer = rs -> {\r
+                               String fileName = rs.getString("filename");\r
+                               if (idToCheck[0].equals(fileName)) {\r
+                                       result[0] = rs.getLong("mediaid");\r
+                                       return false;\r
+                               } else\r
+                                       return true;\r
+                       };\r
+                       manager.executeQuery(query.toString(), consumer, null);\r
+               }\r
+\r
+               return result[0];\r
+       }\r
+\r
+       static public boolean isArchived(IItemManager manager, Path filePath) {\r
+               boolean result = false;\r
+               String name = filePath.getFileName().toString();\r
+               String[] tsmName = new String[] { null };\r
+               String query = String.format("SELECT relativepath FROM MEDIAFILE WHERE houseid = '%s'", name);\r
+               manager.executeQuery(query, rs -> {\r
+                       tsmName[0] = rs.getString("relativepath");\r
+                       return false;\r
+               }, null);\r
+\r
+               Store tsmStore = manager.getSystemStore(false);\r
+               if (tsmStore == null)\r
+                       throw new NullPointerException("A TSM bejegyzés nem található!");\r
+\r
+               StoreUri tsmStoreUri = tsmStore.getSourceStoreUri(RemoteStoreProtocol.TSM);\r
+               if (tsmStoreUri == null)\r
+                       throw new NullPointerException("A TSM forrás elérése nem található!");\r
+\r
+               if (tsmName[0] != null) {\r
+                       try {\r
+                               RemoteFile remoteFile = tsmStoreUri.getRemoteFile(tsmName[0]);\r
+                               result = remoteFile != null;\r
+                       } catch (Exception e) {\r
+                               result = false;\r
+                       } finally {\r
+                               tsmStoreUri.cleanUp();\r
+                       }\r
+               }\r
+               return result;\r
+       }\r
+}\r
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/MediaCubeClient.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/MediaCubeClient.java
new file mode 100644 (file)
index 0000000..0915cc3
--- /dev/null
@@ -0,0 +1,77 @@
+package user.jobengine.server.steps.shared;\r
+\r
+import javax.ws.rs.client.Entity;\r
+import javax.ws.rs.client.Invocation.Builder;\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.MultivaluedMap;\r
+import javax.ws.rs.core.Response;\r
+import javax.ws.rs.core.Response.Status;\r
+\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+import org.jboss.resteasy.client.jaxrs.ResteasyClient;\r
+import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;\r
+import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;\r
+import org.jboss.resteasy.specimpl.MultivaluedMapImpl;\r
+\r
+import com.ibm.nosql.json.JSONUtil;\r
+import com.ibm.nosql.json.api.BasicDBObject;\r
+\r
+public class MediaCubeClient {\r
+       private static Logger logger = LogManager.getLogger();\r
+       private ResteasyWebTarget webTarget;\r
+\r
+       public MediaCubeClient(String address) {\r
+               ResteasyClient client = new ResteasyClientBuilder().build();\r
+               webTarget = client.target(address);\r
+       }\r
+\r
+       BasicDBObject getDbObject(String json) {\r
+               BasicDBObject result = (BasicDBObject) JSONUtil.jsonToDbObject(json);\r
+\r
+               if (result == null)\r
+                       throw new NullPointerException("API Result is null!");\r
+\r
+               if (result.containsKey("exception")) {\r
+                       BasicDBObject e = (BasicDBObject) result.get("exception");\r
+                       throw new RuntimeException(e.getString("message"));\r
+               }\r
+               //{"exception":{"message":"Invalid credentials.","publicName":"AuthenticationFailedException"}}\r
+               return result;\r
+       }\r
+\r
+       public BasicDBObject getStatus(long jobId) {\r
+               MultivaluedMap<String, Object> vars = new MultivaluedMapImpl<>();\r
+               vars.add("jobId", jobId);\r
+               Response response = query("services/rest/jobengine/jobstatus", vars).get();\r
+               if (response.getStatus() != Status.OK.getStatusCode()) {\r
+                       logger.error(response.readEntity(String.class));\r
+                       System.out.println(response.readEntity(String.class));\r
+                       return null;\r
+               }\r
+               String result = response.readEntity(String.class);\r
+               return getDbObject(result);\r
+       }\r
+\r
+       private Builder query(String path, MultivaluedMap<String, Object> vars) {\r
+               ResteasyWebTarget target = webTarget.path(path).queryParams(vars);\r
+               Builder result = target.request();\r
+               return result;\r
+       }\r
+\r
+       public long startjob(String template, String name, BasicDBObject jobParams) throws Exception {\r
+               MultivaluedMap<String, Object> vars = new MultivaluedMapImpl<>();\r
+               vars.add("template", template);\r
+               vars.add("name", name);\r
+               Response response = query("services/rest/jobengine/startjob", vars).post(Entity.entity(jobParams.toString(), MediaType.APPLICATION_JSON));\r
+\r
+               if (response.getStatus() != Status.OK.getStatusCode()) {\r
+                       logger.error(response.readEntity(String.class));\r
+                       return 0;\r
+               }\r
+\r
+               String resultObject = response.readEntity(String.class);\r
+               return Long.parseLong(resultObject);\r
+       }\r
+\r
+}\r
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/MetadataType.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/MetadataType.java
new file mode 100644 (file)
index 0000000..0e27bf3
--- /dev/null
@@ -0,0 +1,5 @@
+package user.jobengine.server.steps.shared;\r
+\r
+public enum MetadataType {\r
+       TrafficMaterial, TrafficPromo, TrafficAD, OctopusStory, OctopusPlaceholder, Generic\r
+}\r
diff --git a/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/MetadataTypeDetector.java b/server/-product/production/MEDIAVIVANTIS/jobs/steps/shared/MetadataTypeDetector.java
new file mode 100644 (file)
index 0000000..9e9e6be
--- /dev/null
@@ -0,0 +1,49 @@
+package user.jobengine.server.steps.shared;\r
+\r
+import org.apache.commons.lang.StringUtils;\r
+\r
+public class MetadataTypeDetector {\r
+\r
+       private static final String HYPHEN = "-";\r
+       private static final String DOT = ".";\r
+\r
+       private static final String REGEXP_TRAFFICMATERIALID = "^M{1}[0-9]{6}[A-Z]{1}";\r
+       private static final String REGEXP_TRAFFICADID = "^R{1}[0-9]{6}[A-Z]{1}";\r
+       private static final String REGEXP_TRAFFICPROMOID = "^P{1}[0-9]{6}[A-Z]{1}";\r
+       private static final String REGEXP_OCTOPUSSTORYID = "^[0-9]+";\r
+       private static final String REGEXP_OCTOPUSPLACEHOLDERID = "^[0-9]+_[0-9]+";\r
+       private static final String REGEXP_OCTOPUSPLACEHOLDERVERSIONEDID = "^[0-9]+_[0-9]+-[0-9]{3}";\r
+\r
+       public static MetadataType GuessMetadataType(String id) {\r
+               if (StringUtils.isBlank(id))\r
+                       return MetadataType.Generic;\r
+               if (id.matches(REGEXP_TRAFFICMATERIALID))\r
+                       return MetadataType.TrafficMaterial;\r
+               if (id.matches(REGEXP_TRAFFICPROMOID))\r
+                       return MetadataType.TrafficPromo;\r
+               if (id.matches(REGEXP_TRAFFICADID))\r
+                       return MetadataType.TrafficAD;\r
+               if (id.matches(REGEXP_OCTOPUSSTORYID))\r
+                       return MetadataType.OctopusStory;\r
+               if (id.matches(REGEXP_OCTOPUSPLACEHOLDERID))\r
+                       return MetadataType.OctopusPlaceholder;\r
+               if (id.matches(REGEXP_OCTOPUSPLACEHOLDERVERSIONEDID))\r
+                       return MetadataType.OctopusPlaceholder;\r
+               return MetadataType.Generic;\r
+       }\r
+\r
+       public static String truncateExtension(String name) {\r
+               String result = name;\r
+               if (result != null && result.contains(DOT))\r
+                       result = result.substring(0, result.lastIndexOf(DOT));\r
+               return result;\r
+       }\r
+\r
+       public static String truncateVersion(String name) {\r
+               String result = name;\r
+               if (result != null && result.contains(HYPHEN))\r
+                       result = result.split(HYPHEN)[0];\r
+               return result;\r
+       }\r
+\r
+}\r
diff --git a/server/user.jobengine.executors/src/user/jobengine/server/steps/EscortFileUpdaterStep.java b/server/user.jobengine.executors/src/user/jobengine/server/steps/EscortFileUpdaterStep.java
new file mode 100644 (file)
index 0000000..5dcb523
--- /dev/null
@@ -0,0 +1,57 @@
+package user.jobengine.server.steps;\r
+\r
+import java.io.FileNotFoundException;\r
+import java.nio.file.Files;\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\r
+\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+\r
+import user.commons.DownloadableMedia;\r
+import user.commons.StoreUri;\r
+import user.commons.mediatool.MediaInfo;\r
+import user.commons.remotestore.RemoteStoreProtocol;\r
+import user.jobengine.server.steps.shared.EscortFiles;\r
+\r
+public class EscortFileUpdaterStep extends JobStep {\r
+       private static final Logger logger = LogManager.getLogger();\r
+\r
+       @StepEntry\r
+       public Object[] execute(StoreUri sourceStoreUri, String fileName, String escortFile) throws Exception {\r
+               if (!RemoteStoreProtocol.LOCAL.equals(sourceStoreUri.getProtocol()))\r
+                       throw new Exception("Store URI protocol must be local.");\r
+               Path filePath = Paths.get(sourceStoreUri.toString(true), fileName);\r
+               if (!filePath.toFile().exists())\r
+                       throw new FileNotFoundException("File not exists: " + filePath.toString());\r
+\r
+               Path escortFilePath = Paths.get(escortFile);\r
+               DownloadableMedia downloadable = null;\r
+               try {\r
+                       downloadable = EscortFiles.decode(escortFilePath);\r
+               } catch (Exception e) {\r
+                       logger.error(getSessionMarker(), e.getMessage());\r
+               }\r
+\r
+               if (downloadable != null)\r
+                       storeCurrentFrames(filePath, downloadable, escortFilePath);\r
+\r
+               return null;\r
+       }\r
+\r
+       private void storeCurrentFrames(Path filePath, DownloadableMedia downloadable, Path escortFilePath) {\r
+               MediaInfo mi = null;\r
+               try {\r
+                       mi = new MediaInfo(filePath);\r
+                       mi.process();\r
+                       long frames = mi.getFrames();\r
+                       downloadable.put("frames", frames);\r
+                       Files.write(escortFilePath, downloadable.toPrettyString("").getBytes());\r
+                       logger.info(getMarker(), "{} length {} is saved to escort file", filePath, frames,\r
+                                       escortFilePath.getFileName().toString());\r
+               } catch (Exception e) {\r
+                       logger.error(getSessionMarker(), e.getMessage());\r
+               }\r
+       }\r
+\r
+}\r
index d47c2b79d19975fdc4f5bb467d0203500950e814..7ff4702ffe0cd8068515988d69d0597b0e771166 100644 (file)
@@ -1,19 +1,12 @@
 package user.jobengine.server.steps;\r
 \r
-import java.nio.file.Path;\r
-import java.nio.file.Paths;\r
-\r
-import org.apache.logging.log4j.LogManager;\r
-import org.apache.logging.log4j.Logger;\r
-\r
 import user.commons.StoreUri;\r
 \r
 public class PBARCHIVETransferFromStep extends TransferStep {\r
-       private static final Logger logger = LogManager.getLogger();\r
-\r
        @Override\r
        @StepEntry\r
-       public Object[] execute(StoreUri sourceStoreUri, String sourceFileName, StoreUri targetStoreUri, String targetFileName) throws Exception {\r
+       public Object[] execute(StoreUri sourceStoreUri, String sourceFileName, StoreUri targetStoreUri,\r
+                       String targetFileName) throws Exception {\r
                Object[] result = null;\r
                result = super.execute(sourceStoreUri, sourceFileName, targetStoreUri, targetFileName);\r
                return result;\r
index 071ed7cfccc6ee28e66d25102c7be89b01e39f0f..75b1a357790074fc7afa70933d68c5eafcb4909e 100644 (file)
@@ -3,38 +3,28 @@ package user.jobengine.server.steps;
 import java.io.IOException;\r
 import java.nio.file.Paths;\r
 import java.sql.Timestamp;\r
-import java.text.SimpleDateFormat;\r
 import java.time.Duration;\r
 import java.time.Instant;\r
 import java.util.ArrayList;\r
-import java.util.Iterator;\r
 import java.util.List;\r
 \r
 import org.apache.commons.net.ftp.FTPClient;\r
 import org.apache.logging.log4j.LogManager;\r
 import org.apache.logging.log4j.Logger;\r
-import org.w3c.dom.stylesheets.LinkStyle;\r
 \r
 import user.commons.DownloadableMedia;\r
 import user.commons.RemoteFile;\r
 import user.commons.StoreUri;\r
-import user.commons.nexio.api.Clip;\r
 import user.commons.nexio.api.ClipNotFoundException;\r
-import user.commons.nexio.api.Controller;\r
-import user.commons.nexio.api.Mediabase;\r
 import user.commons.nexio.server.protocol.ProtocolException;\r
 import user.commons.remotestore.FtpDirectoryLister;\r
-import user.commons.remotestore.IDirectoryLister;\r
 import user.commons.remotestore.RemoteStoreProtocol;\r
 import user.jobengine.db.Media;\r
-import user.jobengine.db.MediaFile;\r
 import user.jobengine.server.steps.shared.EscortFiles;\r
 \r
 public class PBArchiveCheckerStep extends JobStep {\r
        private static final String DOT_MXF = ".mxf";\r
        private static final Logger logger = LogManager.getLogger();\r
-       private SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");\r
-\r
 \r
        private boolean checkModifiedByTime(String title, Timestamp modified, int lastModifiedHours) {\r
                long modifiedHours = Duration.between(modified.toInstant(), Instant.now()).toHours();\r
@@ -43,7 +33,7 @@ public class PBArchiveCheckerStep extends JobStep {
                        return false;\r
                }\r
                if (modifiedHours < lastModifiedHours) {\r
-                       logger.debug(getMarker(), "{} modification time is too cloose for now", title);\r
+                       logger.info(getMarker(), "{} modification time is too cloose for now", title);\r
                        return false;\r
                }\r
 \r
@@ -67,24 +57,25 @@ public class PBArchiveCheckerStep extends JobStep {
                        FTPClient client = lister.connect();\r
                        //a StoreUri alapu listazas nem mukodik, miota a working directory beallitas fix\r
                        List<RemoteFile> remoteFiles = new ArrayList<>();\r
-                       \r
+\r
                        String[] listNames = client.listNames();\r
                        for (String f : listNames) {\r
                                logger.info(getMarker(), "File name is {}", f);\r
-                               \r
+\r
                                try {\r
                                        RemoteFile remoteFile = lister.get(f);\r
                                        if (remoteFile == null)\r
                                                logger.info(getMarker(), "Remote file for {} is not available", f);\r
                                        else\r
                                                remoteFiles.add(remoteFile);\r
-                                       \r
-                               } catch (Exception iex){\r
+\r
+                               } catch (Exception iex) {\r
                                        logger.error(getMarker(), iex.getMessage());\r
                                }\r
                        }\r
-                       \r
-                       logger.info(getMarker(), "Found {} files in working dir {}", remoteFiles.size(), client.printWorkingDirectory());\r
+\r
+                       logger.info(getMarker(), "Found {} files in working dir {}", remoteFiles.size(),\r
+                                       client.printWorkingDirectory());\r
                        processClips(sourceStoreName, sourceStoreUri, targetStoreUri, outputPath, remoteFiles, lastModifiedHours);\r
 \r
                } catch (Exception e) {\r
@@ -100,9 +91,9 @@ public class PBArchiveCheckerStep extends JobStep {
                return null;\r
        }\r
 \r
-       private void processClips(String storeName, StoreUri sourceStoreUri, StoreUri targetStoreUri, String outputPath, List<RemoteFile> remoteFiles,\r
-                       int lastModifiedHours) throws ClipNotFoundException, IOException, ProtocolException {\r
-               int processed = 0;\r
+       private void processClips(String storeName, StoreUri sourceStoreUri, StoreUri targetStoreUri, String outputPath,\r
+                       List<RemoteFile> remoteFiles, int lastModifiedHours)\r
+                       throws ClipNotFoundException, IOException, ProtocolException {\r
                for (RemoteFile remoteFile : remoteFiles) {\r
 \r
                        if (getJobRuntime().isWaitingCancel()) {\r
@@ -111,46 +102,45 @@ public class PBArchiveCheckerStep extends JobStep {
                                break;\r
                        }\r
                        try {\r
-                               \r
+\r
                                String title = null;\r
                                Timestamp created = null;\r
                                Timestamp modified = null;\r
                                title = remoteFile.getName();\r
+\r
+                               int dotIdx = title.lastIndexOf(".");\r
+                               if (dotIdx > -1)\r
+                                       title = title.substring(0, dotIdx);\r
+\r
                                created = remoteFile.getCreated();\r
                                modified = remoteFile.getModify();\r
 \r
-                               logger.info(getMarker(), "{} with extension {} created {} modified {}", title, remoteFile.getExtension(), created, modified);\r
+                               logger.info(getMarker(), "{} created {} modified {}", title, created, modified);\r
                                Media media = getManager().getMedia(title);\r
                                boolean createEscort = false;\r
 \r
-                               if (!createEscort)\r
-                                       continue;\r
-                               \r
-                               if (checkModifiedByTime(title, modified, lastModifiedHours)) {\r
+                               if (checkModifiedByTime(title, modified, lastModifiedHours))\r
                                        createEscort = true;\r
-                                       logger.info(getMarker(), "{} not archived yet", title);\r
-                               }\r
 \r
-                               long mediaId = 0;\r
-                               if (media != null)\r
-                                       mediaId = media.getId();\r
+                               if (!createEscort)\r
+                                       continue;\r
 \r
                                if (createEscort) {\r
+                                       long mediaId = 0;\r
+                                       if (media != null)\r
+                                               mediaId = media.getId();\r
                                        String fileName = title + DOT_MXF;\r
-                                       DownloadableMedia downloadable = DownloadableMedia.create(title, fileName, modified, created, 0, 0, sourceStoreUri.getId(),\r
-                                                       targetStoreUri.getId(), mediaId);\r
+                                       DownloadableMedia downloadable = DownloadableMedia.create(title, fileName, modified, created, 0, 0,\r
+                                                       sourceStoreUri.getId(), targetStoreUri.getId(), mediaId);\r
                                        String escortFileName = storeName + "." + downloadable.getString("fileName");\r
-                                       if (EscortFiles.createMetadataIfNotExists(outputPath, escortFileName, downloadable.toPrettyString(""))) {\r
+                                       if (EscortFiles.createMetadataIfNotExists(outputPath, escortFileName,\r
+                                                       downloadable.toPrettyString(""))) {\r
                                                logger.info(getMarker(), "Archive status file created for {}", fileName);\r
                                        } else {\r
                                                logger.info(getMarker(), "Archive status file already exists for {}", fileName);\r
                                        }\r
-\r
                                }\r
 \r
-                               processed++;\r
-                               if (processed % 100 == 0)\r
-                                       logger.info(getMarker(), "Processed {} records", processed);\r
                        } catch (Exception e) {\r
                                logger.error(getSessionMarker(), e.getMessage());\r
                                continue;\r