- publish/unpublish recording
This commit is contained in:
parent
1ccf55fd97
commit
058a4044d6
@ -32,11 +32,14 @@ libraryDependencies += "org.scala-lang" % "scala-library" % scalaV
|
||||
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaV
|
||||
|
||||
libraryDependencies += "commons-lang" % "commons-lang" % "2.5"
|
||||
libraryDependencies += "commons-io" % "commons-io" % "2.4"
|
||||
libraryDependencies += "org.freemarker" % "freemarker" % "2.3.23"
|
||||
libraryDependencies += "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.6.3"
|
||||
// https://mvnrepository.com/artifact/org.codehaus.woodstox/woodstox-core-asl
|
||||
libraryDependencies += "org.codehaus.woodstox" % "woodstox-core-asl" % "4.4.1"
|
||||
|
||||
libraryDependencies += "org.slf4j" % "slf4j-api" % "1.7.5"
|
||||
|
||||
libraryDependencies += "org.pegdown" % "pegdown" % "1.4.0" % "test"
|
||||
libraryDependencies += "junit" % "junit" % "4.12" % "test"
|
||||
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test"
|
||||
|
@ -92,7 +92,7 @@ public class RecordingService {
|
||||
return recs;
|
||||
}
|
||||
|
||||
private RecordingMetadata getRecordingMetadata(File dir) {
|
||||
private static RecordingMetadata getRecordingMetadata(File dir) {
|
||||
File file = new File(dir.getPath() + File.separatorChar + "metadata.xml");
|
||||
RecordingMetadata rec = RecordingMetadataReaderHelper.getRecordingMetadata(file);
|
||||
return rec;
|
||||
@ -262,7 +262,7 @@ public class RecordingService {
|
||||
return rec;
|
||||
}
|
||||
|
||||
private void deleteRecording(String id, String path) {
|
||||
private static void deleteRecording(String id, String path) {
|
||||
String[] format = getPlaybackFormats(path);
|
||||
for (int i = 0; i < format.length; i++) {
|
||||
List<File> recordings = getDirectories(path + File.separatorChar + format[i]);
|
||||
@ -275,12 +275,12 @@ public class RecordingService {
|
||||
}
|
||||
}
|
||||
|
||||
private void createDirectory(File directory) {
|
||||
private static void createDirectory(File directory) {
|
||||
if (!directory.exists())
|
||||
directory.mkdirs();
|
||||
}
|
||||
|
||||
private void deleteDirectory(File directory) {
|
||||
private static void deleteDirectory(File directory) {
|
||||
/**
|
||||
* Go through each directory and check if it's not empty. We need to
|
||||
* delete files inside a directory before a directory can be deleted.
|
||||
@ -297,7 +297,7 @@ public class RecordingService {
|
||||
directory.delete();
|
||||
}
|
||||
|
||||
private List<File> getDirectories(String path) {
|
||||
private static List<File> getDirectories(String path) {
|
||||
List<File> files = new ArrayList<File>();
|
||||
try {
|
||||
DirectoryStream<Path> stream = Files.newDirectoryStream(FileSystems.getDefault().getPath(path));
|
||||
@ -313,7 +313,7 @@ public class RecordingService {
|
||||
return files;
|
||||
}
|
||||
|
||||
private String[] getPlaybackFormats(String path) {
|
||||
private static String[] getPlaybackFormats(String path) {
|
||||
List<File> dirs = getDirectories(path);
|
||||
String[] formats = new String[dirs.size()];
|
||||
|
||||
@ -388,41 +388,94 @@ public class RecordingService {
|
||||
List<File> recordings = getDirectories(path + File.separatorChar + format[i]);
|
||||
for (int f = 0; f < recordings.size(); f++) {
|
||||
if (recordings.get(f).getName().equalsIgnoreCase(recordingId)) {
|
||||
Recording r = getRecordingInfo(recordings.get(f));
|
||||
if (r != null) {
|
||||
File dest;
|
||||
if (state.equals(Recording.STATE_PUBLISHED)) {
|
||||
dest = new File(publishedDir + File.separatorChar + format[i]);
|
||||
} else if (state.equals(Recording.STATE_UNPUBLISHED)) {
|
||||
dest = new File(unpublishedDir + File.separatorChar + format[i]);
|
||||
} else if (state.equals(Recording.STATE_DELETED)) {
|
||||
dest = new File(deletedDir + File.separatorChar + format[i]);
|
||||
} else {
|
||||
log.debug(String.format("State: %s, is not supported", state));
|
||||
return;
|
||||
}
|
||||
if (!dest.exists())
|
||||
dest.mkdirs();
|
||||
boolean moved = recordings.get(f).renameTo(new File(dest, recordings.get(f).getName()));
|
||||
if (moved) {
|
||||
log.debug("Recording successfully moved!");
|
||||
r.setState(state);
|
||||
r.setPublished(state.equals(Recording.STATE_PUBLISHED));
|
||||
if (state.equals(Recording.STATE_DELETED)) {
|
||||
r.setPlaybackFormat(null);
|
||||
deleteRecording(recordingId, deletedDir);
|
||||
}
|
||||
recordingServiceHelper.writeRecordingInfo(dest.getAbsolutePath() + File.separatorChar + recordings.get(f).getName(), r);
|
||||
log.debug(String.format("Recording successfully %s!", state));
|
||||
} else {
|
||||
log.debug("Recording was not moved");
|
||||
}
|
||||
File dest;
|
||||
if (state.equals(Recording.STATE_PUBLISHED)) {
|
||||
dest = new File(publishedDir + File.separatorChar + format[i]);
|
||||
RecordingService.publishRecording(dest, recordingId, recordings.get(f));
|
||||
} else if (state.equals(Recording.STATE_UNPUBLISHED)) {
|
||||
dest = new File(unpublishedDir + File.separatorChar + format[i]);
|
||||
RecordingService.unpublishRecording(dest, recordingId, recordings.get(f));
|
||||
} else if (state.equals(Recording.STATE_DELETED)) {
|
||||
dest = new File(deletedDir + File.separatorChar + format[i]);
|
||||
RecordingService.deleteRecording(dest, recordingId, recordings.get(f));
|
||||
} else {
|
||||
log.debug(String.format("State: %s, is not supported", state));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void publishRecording(File destDir, String recordingId, File recordingDir) {
|
||||
File metadataXml = RecordingMetadataReaderHelper.getMetadataXmlLocation(recordingDir.getPath() + File.separatorChar + recordingId);
|
||||
RecordingMetadata r = RecordingMetadataReaderHelper.getRecordingMetadata(metadataXml);
|
||||
if (r != null) {
|
||||
if (!destDir.exists()) destDir.mkdirs();
|
||||
|
||||
boolean moved = recordingDir.renameTo(destDir);
|
||||
if (moved) {
|
||||
log.debug("Recording successfully moved!");
|
||||
r.setState(Recording.STATE_PUBLISHED);
|
||||
r.setPublished(true);
|
||||
|
||||
File medataXmlFile = RecordingMetadataReaderHelper.getMetadataXmlLocation(destDir.getAbsolutePath() + File.separatorChar + recordingId);
|
||||
// Process the changes by saving the recording into metadata.xml
|
||||
RecordingMetadataReaderHelper.saveRecordingMetadata(medataXmlFile, r);
|
||||
|
||||
log.debug(String.format("Published successfully %s!", recordingId));
|
||||
} else {
|
||||
log.debug("Recording was not moved");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void unpublishRecording(File destDir, String recordingId, File recordingDir) {
|
||||
File metadataXml = RecordingMetadataReaderHelper.getMetadataXmlLocation(recordingDir.getPath() + File.separatorChar + recordingId);
|
||||
RecordingMetadata r = RecordingMetadataReaderHelper.getRecordingMetadata(metadataXml);
|
||||
if (r != null) {
|
||||
if (!destDir.exists()) destDir.mkdirs();
|
||||
|
||||
boolean moved = recordingDir.renameTo(destDir);
|
||||
if (moved) {
|
||||
r.setState(Recording.STATE_UNPUBLISHED);
|
||||
r.setPublished(false);
|
||||
|
||||
File medataXmlFile = RecordingMetadataReaderHelper.getMetadataXmlLocation(destDir.getAbsolutePath() + File.separatorChar + recordingId);
|
||||
// Process the changes by saving the recording into metadata.xml
|
||||
RecordingMetadataReaderHelper.saveRecordingMetadata(medataXmlFile, r);
|
||||
|
||||
log.debug(String.format("Unpublished successfully %s!", recordingId));
|
||||
} else {
|
||||
log.debug("Recording was not moved");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteRecording(File destDir, String recordingId, File recordingDir) {
|
||||
File metadataXml = RecordingMetadataReaderHelper.getMetadataXmlLocation(recordingDir.getPath() + File.separatorChar + recordingId);
|
||||
RecordingMetadata r = RecordingMetadataReaderHelper.getRecordingMetadata(metadataXml);
|
||||
if (r != null) {
|
||||
if (!destDir.exists()) destDir.mkdirs();
|
||||
|
||||
boolean moved = recordingDir.renameTo(destDir);
|
||||
if (moved) {
|
||||
r.setState(Recording.STATE_DELETED);
|
||||
r.setPublished(false);
|
||||
deleteRecording(recordingId, destDir.getAbsolutePath());
|
||||
|
||||
File medataXmlFile = RecordingMetadataReaderHelper.getMetadataXmlLocation(destDir.getAbsolutePath() + File.separatorChar + recordingId);
|
||||
// Process the changes by saving the recording into metadata.xml
|
||||
RecordingMetadataReaderHelper.saveRecordingMetadata(medataXmlFile, r);
|
||||
|
||||
log.debug(String.format("Unpublished successfully %s!", recordingId));
|
||||
} else {
|
||||
log.debug("Recording was not moved");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<File> getAllDirectories(String state) {
|
||||
List<File> allDirectories = new ArrayList<File>();
|
||||
|
||||
@ -488,22 +541,8 @@ public class RecordingService {
|
||||
Map<String,File> recsIndexed = indexRecordings(recs);
|
||||
if ( recsIndexed.containsKey(recordID) ) {
|
||||
File recFile = recsIndexed.get(recordID);
|
||||
Recording rec = getRecordingInfo(recFile);
|
||||
if (rec != null) {
|
||||
for (Map.Entry<String,String> meta : metaParams.entrySet()) {
|
||||
if ( !"".equals(meta.getValue()) ) {
|
||||
// As it has a value, if the meta parameter exists update it, otherwise add it
|
||||
rec.updateMetadata(meta.getKey(), meta.getValue());
|
||||
} else {
|
||||
// As it doesn't have a value, if it exists delete it
|
||||
if ( rec.containsMetadata(meta.getKey()) ) {
|
||||
rec.deleteMetadata(meta.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Process the changes by saving the recording into metadata.xml
|
||||
recordingServiceHelper.writeRecordingInfo(recFile.getAbsolutePath(), rec);
|
||||
}
|
||||
File metadataXml = RecordingMetadataReaderHelper.getMetadataXmlLocation(recFile.getPath());
|
||||
updateRecordingMetadata(metadataXml, metaParams, metadataXml);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -511,6 +550,27 @@ public class RecordingService {
|
||||
return;
|
||||
}
|
||||
|
||||
public static void updateRecordingMetadata(File srxMetadataXml, Map<String,String> metaParams, File destMetadataXml) {
|
||||
RecordingMetadata rec = RecordingMetadataReaderHelper.getRecordingMetadata(srxMetadataXml);
|
||||
if (rec != null && rec.getMeta() != null) {
|
||||
for (Map.Entry<String,String> meta : metaParams.entrySet()) {
|
||||
if ( !"".equals(meta.getValue()) ) {
|
||||
// As it has a value, if the meta parameter exists update it, otherwise add it
|
||||
rec.getMeta().set(meta.getKey(), meta.getValue());
|
||||
} else {
|
||||
// As it doesn't have a value, if it exists delete it
|
||||
if ( rec.getMeta().containsKey(meta.getKey()) ) {
|
||||
rec.getMeta().remove(meta.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process the changes by saving the recording into metadata.xml
|
||||
RecordingMetadataReaderHelper.saveRecordingMetadata(destMetadataXml, rec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Map<String,File> indexRecordings(List<File> recs) {
|
||||
Map<String,File> indexedRecs = new HashMap<String,File>();
|
||||
|
@ -20,4 +20,12 @@ public class Metadata {
|
||||
public void set(String name, String value) {
|
||||
map.put(name, value);
|
||||
}
|
||||
|
||||
public void remove(String key) {
|
||||
map.remove(key);
|
||||
}
|
||||
|
||||
public boolean containsKey(String key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,9 @@ package org.bigbluebutton.api.util;
|
||||
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
import org.bigbluebutton.api.domain.RecordingMetadata;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.*;
|
||||
import java.io.*;
|
||||
|
||||
public class RecordingMetadataReaderHelper {
|
||||
@ -48,4 +47,29 @@ public class RecordingMetadataReaderHelper {
|
||||
|
||||
return recMeta;
|
||||
}
|
||||
|
||||
public static File getMetadataXmlLocation(String destDir) {
|
||||
return new File(destDir + File.separatorChar + "metadata.xml");
|
||||
}
|
||||
|
||||
public static void saveRecordingMetadata(File metadataXml, RecordingMetadata recordingMetadata) {
|
||||
|
||||
//XMLOutputFactory factory = XMLOutputFactory.newInstance();
|
||||
JacksonXmlModule module = new JacksonXmlModule();
|
||||
module.setDefaultUseWrapper(false);
|
||||
|
||||
XmlMapper mapper = new XmlMapper(module);
|
||||
|
||||
//Reading from xml file and creating XMLStreamReader
|
||||
//XMLStreamWriter writer = null;
|
||||
try {
|
||||
//writer = factory.createXMLStreamWriter(new FileOutputStream(metadataXml));
|
||||
mapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
mapper.writeValue(metadataXml, recordingMetadata);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,6 @@ import javax.xml.stream.{XMLInputFactory, XMLStreamReader}
|
||||
import com.fasterxml.jackson.dataformat.xml.{JacksonXmlModule, XmlMapper}
|
||||
import org.bigbluebutton.api.domain.{RecordingMetadata, RecordingMetadataPlayback}
|
||||
|
||||
/**
|
||||
* Created by ralam on 3/10/2017.
|
||||
*/
|
||||
class RecordingMetadataReaderHelperTest extends UnitSpec {
|
||||
|
||||
it should "deserialize playback part of metadata.xml" in {
|
||||
@ -53,4 +50,30 @@ class RecordingMetadataReaderHelperTest extends UnitSpec {
|
||||
|
||||
}
|
||||
|
||||
it should "save metadata.xml" in {
|
||||
val factory: XMLInputFactory = XMLInputFactory.newInstance();
|
||||
|
||||
val xml = new File("src/test/resources/breakout-room-metadata.xml")
|
||||
val module: JacksonXmlModule = new JacksonXmlModule();
|
||||
// and then configure, for example:
|
||||
module.setDefaultUseWrapper(false);
|
||||
|
||||
val mapper: XmlMapper = new XmlMapper(module)
|
||||
|
||||
//Reading from xml file and creating XMLStreamReader
|
||||
val reader: XMLStreamReader = factory.createXMLStreamReader(new FileInputStream(xml))
|
||||
|
||||
val recMeta: RecordingMetadata = mapper.readValue(reader, classOf[RecordingMetadata])
|
||||
|
||||
recMeta.getMeta().set("FOO", "BAR");
|
||||
|
||||
val metadataXml = RecordingMetadataReaderHelper.getMetadataXmlLocation("target")
|
||||
if (metadataXml.exists()) metadataXml.delete()
|
||||
|
||||
RecordingMetadataReaderHelper.saveRecordingMetadata(metadataXml, recMeta)
|
||||
|
||||
assert(metadataXml.exists())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,74 @@
|
||||
package org.bigbluebutton.api.util
|
||||
|
||||
import java.io.File
|
||||
import java.util
|
||||
|
||||
import org.apache.commons.io.FileUtils
|
||||
import org.bigbluebutton.api.RecordingService
|
||||
|
||||
class RecordingServiceTest extends UnitSpec {
|
||||
|
||||
it should "deserialize playback part of metadata.xml" in {
|
||||
val srcXml = new File("src/test/resources/breakout-room-metadata.xml")
|
||||
val metaParams: util.Map[String, String] = new util.TreeMap[String, String]()
|
||||
|
||||
metaParams.put("foo", "bar")
|
||||
metaParams.put("bar", "baz")
|
||||
|
||||
val destXml = new File("target/updated-metadata.xml")
|
||||
RecordingService.updateRecordingMetadata(srcXml, metaParams, destXml)
|
||||
}
|
||||
|
||||
it should "publish recording" in {
|
||||
// Make a copy of our sample recording
|
||||
val destDir = new File("target/sample-recording/publish")
|
||||
if (destDir.exists()) FileUtils.deleteDirectory(destDir)
|
||||
|
||||
val srcDir = new File("src/test/resources/sample-recording")
|
||||
FileUtils.copyDirectory(srcDir, destDir)
|
||||
|
||||
val recordingId = "foo"
|
||||
|
||||
val publishedDir = new File("target/published")
|
||||
RecordingService.publishRecording(publishedDir, recordingId, destDir)
|
||||
|
||||
assert(true)
|
||||
}
|
||||
|
||||
it should "unpublish recording" in {
|
||||
// Make a copy of our sample recording
|
||||
val destDir = new File("target/sample-recording/unpublish")
|
||||
if (destDir.exists()) FileUtils.deleteDirectory(destDir)
|
||||
|
||||
val srcDir = new File("src/test/resources/sample-recording")
|
||||
FileUtils.copyDirectory(srcDir, destDir)
|
||||
|
||||
val recordingId = "foo"
|
||||
|
||||
val unpublishedDir = new File("target/unpublished")
|
||||
if (unpublishedDir.exists()) FileUtils.deleteDirectory(unpublishedDir)
|
||||
|
||||
RecordingService.unpublishRecording(unpublishedDir, recordingId, destDir)
|
||||
|
||||
assert(unpublishedDir.exists())
|
||||
}
|
||||
|
||||
it should "delete recording" in {
|
||||
// Make a copy of our sample recording
|
||||
val destDir = new File("target/sample-recording/delete")
|
||||
if (destDir.exists()) FileUtils.deleteDirectory(destDir)
|
||||
|
||||
val srcDir = new File("src/test/resources/sample-recording")
|
||||
FileUtils.copyDirectory(srcDir, destDir)
|
||||
|
||||
val recordingId = "foo"
|
||||
|
||||
val deletedDir = new File("target/deleted")
|
||||
if (deletedDir.exists()) FileUtils.deleteDirectory(deletedDir)
|
||||
|
||||
RecordingService.deleteRecording(deletedDir, recordingId, destDir)
|
||||
|
||||
assert(deletedDir.exists())
|
||||
}
|
||||
|
||||
}
|
@ -1772,7 +1772,7 @@ class ApiController {
|
||||
}
|
||||
|
||||
List<RecordingMetadata> recsList = meetingService.getRecordingsMetadata(internalRecordIds, states);
|
||||
List<RecordingMetadata>recs = meetingService.filterRecordingsByMetadata(recsList, ParamsProcessorUtil.processMetaParam(params));
|
||||
List<RecordingMetadata> recs = meetingService.filterRecordingsByMetadata(recsList, ParamsProcessorUtil.processMetaParam(params));
|
||||
|
||||
if (recs.isEmpty()) {
|
||||
response.addHeader("Cache-Control", "no-cache")
|
||||
@ -1794,7 +1794,7 @@ class ApiController {
|
||||
def templateLoc = getServletContext().getRealPath("/WEB-INF/freemarker")
|
||||
ResponseBuilder responseBuilder = new ResponseBuilder(new File(templateLoc))
|
||||
|
||||
def xmlText = responseBuilder.buildGetRecordingsResponse(recsList, "success")
|
||||
def xmlText = responseBuilder.buildGetRecordingsResponse(recs, "success")
|
||||
withFormat {
|
||||
xml {
|
||||
render(text: xmlText, contentType: "text/xml")
|
||||
|
@ -517,8 +517,7 @@ public class MeetingService implements MessageListener {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateRecordings(List<String> idList,
|
||||
Map<String, String> metaParams) {
|
||||
public void updateRecordings(List<String> idList, Map<String, String> metaParams) {
|
||||
recordingService.updateMetaParams(idList, metaParams);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user