diff --git a/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy b/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy index 5f6ea1408a..4abaaf64e6 100755 --- a/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy +++ b/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy @@ -29,59 +29,61 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RecordingServiceHelperImp implements RecordingServiceHelper { - private static Logger log = LoggerFactory.getLogger(RecordingServiceHelperImp.class); - /* - - 6e35e3b2778883f5db637d7a5dba0a427f692e91-1398363221956 - available - true - 1398363223514 - 1398363348994 - - presentation - http://example.com/playback/presentation/playback.html?meetingID=6e35e3b2778883f5db637d7a5dba0a427f692e91-1398363221956 - 5429 - 101014 - - ... Any XML element, to be passed through into playback format element. - - - - English 101 - English 101 - Test recording - English 101 - - - */ - - public void writeRecordingInfo(String path, Recording info) { - def writer = new StringWriter() - def builder = new groovy.xml.MarkupBuilder(writer) - def metadataXml = builder.recording { - builder.id(info.getId()) - builder.state(info.getState()) - builder.published(info.isPublished()) - builder.start_time(info.getStartTime()) - builder.end_time(info.getEndTime()) - builder.playback { - builder.format(info.getPlaybackFormat()) - builder.link(info.getPlaybackLink()) - builder.duration(info.getPlaybackDuration()) - builder.extension(info.getPlaybackExtensions()) - } - Map metainfo = info.getMetadata(); - builder.meta{ - metainfo.keySet().each { key -> - builder."$key"(metainfo.get(key)) - } - } - - } - - def xmlEventFile = new File(path + File.separatorChar + "metadata.xml") - xmlEventFile.write writer.toString() - } + private static Logger log = LoggerFactory.getLogger(RecordingServiceHelperImp.class); + /* + + 6e35e3b2778883f5db637d7a5dba0a427f692e91-1398363221956 + available + true + 1398363223514 + 1398363348994 + + presentation + http://example.com/playback/presentation/playback.html?meetingID=6e35e3b2778883f5db637d7a5dba0a427f692e91-1398363221956 + 5429 + 101014 + + ... Any XML element, to be passed through into playback format element. + + + + English 101 + English 101 + Test recording + English 101 + + + */ + + public void writeRecordingInfo(String path, Recording info) { + def writer = new StringWriter() + def builder = new groovy.xml.MarkupBuilder(writer) + def metadataXml = builder.recording { + builder.id(info.getId()) + builder.state(info.getState()) + builder.published(info.isPublished()) + builder.start_time(info.getStartTime()) + builder.end_time(info.getEndTime()) + if ( info.getPlaybackFormat() == null ) { + builder.playback() + } else { + builder.playback { + builder.format(info.getPlaybackFormat()) + builder.link(info.getPlaybackLink()) + builder.duration(info.getPlaybackDuration()) + builder.extension(info.getPlaybackExtensions()) + } + } + Map metainfo = info.getMetadata(); + builder.meta{ + metainfo.keySet().each { key -> + builder."$key"(metainfo.get(key)) + } + } + } + def xmlEventFile = new File(path + File.separatorChar + "metadata.xml") + xmlEventFile.write writer.toString() + } public Recording getRecordingInfo(String id, String recordingDir, String playbackFormat) { String path = recordingDir + File.separatorChar + playbackFormat; @@ -93,28 +95,30 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { return null; } - private Recording getInfo(GPathResult rec) { - Recording r = new Recording(); - r.setId(rec.id.text()); - r.setState(rec.state.text()); - r.setPublished(Boolean.parseBoolean(rec.published.text())); - r.setStartTime(rec.start_time.text()); - r.setEndTime(rec.end_time.text()); - r.setPlaybackFormat(rec.playback.format.text()); - r.setPlaybackLink(rec.playback.link.text()); - r.setPlaybackDuration(rec.playback.duration.text()); - + private Recording getInfo(GPathResult rec) { + Recording r = new Recording(); + r.setId(rec.id.text()); + r.setState(rec.state.text()); + r.setPublished(Boolean.parseBoolean(rec.published.text())); + r.setStartTime(rec.start_time.text()); + r.setEndTime(rec.end_time.text()); + if ( !rec.playback.text().equals("") ) { + r.setPlaybackFormat(rec.playback.format.text()); + r.setPlaybackLink(rec.playback.link.text()); + r.setPlaybackDuration(rec.playback.duration.text()); + } + /* Commenting this out to see if this is causing memory to hang around resulting in - OOM in tomcat7 (ralam july 23, 2015) - r.setPlaybackExtensions(rec.playback.extension.children()); + OOM in tomcat7 (ralam july 23, 2015) + r.setPlaybackExtensions(rec.playback.extension.children()); */ - Map meta = new HashMap(); - rec.meta.children().each { anode -> - meta.put(anode.name().toString(), anode.text().toString()); - } - r.setMetadata(meta); - return r; - } + Map meta = new HashMap(); + rec.meta.children().each { anode -> + meta.put(anode.name().toString(), anode.text().toString()); + } + r.setMetadata(meta); + return r; + } } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java index 88e9618573..fa58ea61e5 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java @@ -63,6 +63,7 @@ import org.bigbluebutton.api.messaging.messages.UserUnsharedWebcam; import org.bigbluebutton.web.services.ExpiredMeetingCleanupTimerTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import com.google.gson.Gson; public class MeetingService implements MessageListener { @@ -348,37 +349,40 @@ public class MeetingService implements MessageListener { return recordingService.filterRecordingsByMetadata(recordings, metadataFilters); } - public HashMap reorderRecordings(ArrayList olds){ - HashMap map= new HashMap(); - for (Recording r:olds) { - if (!map.containsKey(r.getId())) { - Map meta= r.getMetadata(); + public HashMap reorderRecordings(ArrayList olds){ + HashMap map= new HashMap(); + for (Recording r:olds) { + if (!map.containsKey(r.getId())) { + Map meta= r.getMetadata(); String mid = meta.remove("meetingId"); String name = meta.remove("meetingName"); - + r.setMeetingID(mid); r.setName(name); ArrayList plays = new ArrayList(); - - plays.add(new Playback(r.getPlaybackFormat(), r.getPlaybackLink(), - getDurationRecording(r.getPlaybackDuration(), - r.getEndTime(), r.getStartTime()), - r.getPlaybackExtensions())); + if ( r.getPlaybackFormat() != null ) { + plays.add(new Playback(r.getPlaybackFormat(), r.getPlaybackLink(), + getDurationRecording(r.getPlaybackDuration(), + r.getEndTime(), + r.getStartTime()), + r.getPlaybackExtensions())); + } + r.setPlaybacks(plays); map.put(r.getId(), r); - } else { - Recording rec = map.get(r.getId()); - rec.getPlaybacks().add(new Playback(r.getPlaybackFormat(), r.getPlaybackLink(), - getDurationRecording(r.getPlaybackDuration(), - r.getEndTime(), r.getStartTime()), - r.getPlaybackExtensions())); - } - } - - return map; - } - + } else { + Recording rec = map.get(r.getId()); + rec.getPlaybacks().add(new Playback(r.getPlaybackFormat(), r.getPlaybackLink(), + getDurationRecording(r.getPlaybackDuration(), + r.getEndTime(), r.getStartTime()), + r.getPlaybackExtensions())); + } + } + + return map; + } + private int getDurationRecording(String playbackDuration, String end, String start) { int duration; try { @@ -398,19 +402,23 @@ public class MeetingService implements MessageListener { public boolean existsAnyRecording(ArrayList idList){ return recordingService.existAnyRecording(idList); } - - public void setPublishRecording(ArrayList idList,boolean publish){ - for(String id:idList){ - recordingService.publish(id,publish); - } - } - - public void deleteRecordings(ArrayList idList){ - for(String id:idList){ - recordingService.delete(id); - } - } - + + public void setPublishRecording(ArrayList idList,boolean publish){ + for (String id:idList) { + if( publish ) { + recordingService.changeState(id, Recording.STATE_PUBLISHED); + } else { + recordingService.changeState(id, Recording.STATE_UNPUBLISHED); + } + } + } + + public void deleteRecordings(ArrayList idList){ + for(String id:idList){ + recordingService.changeState(id, Recording.STATE_DELETED); + } + } + public void processRecording(String meetingId) { recordingService.startIngestAndProcessing(meetingId); } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/RecordingService.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/RecordingService.java index 95704c041a..b239d6fca5 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/api/RecordingService.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/RecordingService.java @@ -149,23 +149,27 @@ public class RecordingService { return recs; } - public Recording getRecordingInfo(String recordingId, String format) { - return getRecordingInfo(publishedDir, recordingId, format); - } - private Recording getRecordingInfo(String path, String recordingId, String format) { Recording rec = recordingServiceHelper.getRecordingInfo(recordingId, path, format); return rec; } - public void publish(String recordingId, boolean publish) { - if(publish) - publish(unpublishedDir, recordingId, publish); - else - publish(publishedDir, recordingId, publish); + public void changeState(String recordingId, String state) { + if ( state.equals(Recording.STATE_PUBLISHED) ) { + // It can only be published if it is unpublished + changeState(unpublishedDir, recordingId, state); + } else if ( state.equals(Recording.STATE_UNPUBLISHED) ) { + // It can only be unpublished if it is published + changeState(publishedDir, recordingId, state); + } if ( state.equals(Recording.STATE_DELETED) ) { + // It can be deleted from any state + changeState(publishedDir, recordingId, state); + changeState(unpublishedDir, recordingId, state); + changeState(deletedDir, recordingId, state); + } } - private void publish(String path, String recordingId, boolean publish) { + private void changeState(String path, String recordingId, String state) { String[] format = getPlaybackFormats(path); for (int i = 0; i < format.length; i++) { File[] recordings = getDirectories(path + File.separatorChar + format[i]); @@ -174,18 +178,30 @@ public class RecordingService { Recording r = getRecordingInfo(path, recordingId, format[i]); if (r != null) { File dest; - if (publish) { - dest = new File(publishedDir+ File.separatorChar + format[i]); + 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 { - dest = new File(unpublishedDir+ File.separatorChar + format[i]); + log.debug(String.format("State: %s, is not supported", state)); + return; } if(!dest.exists()) dest.mkdir(); boolean moved = recordings[f].renameTo(new File(dest, recordings[f].getName())); if (moved) { log.debug("Recording successfully moved!"); - r.setPublished(publish); - r.setState(publish? Recording.STATE_PUBLISHED: Recording.STATE_UNPUBLISHED); + 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[f].getName(), r); + log.debug(String.format("Recording successfully %s!", state)); + } else { + log.debug("Recording was not moved"); } } } @@ -193,11 +209,6 @@ public class RecordingService { } } - public void delete(String recordingId) { - deleteRecording(recordingId, publishedDir); - deleteRecording(recordingId, unpublishedDir); - } - private void deleteRecording(String id, String path) { String[] format = getPlaybackFormats(path); for (int i = 0; i < format.length; i++) { @@ -205,11 +216,16 @@ public class RecordingService { for (int f = 0; f < recordings.length; f++) { if (recordings[f].getName().equals(id)) { deleteDirectory(recordings[f]); + createDirectory(recordings[f]); } } } } + private void createDirectory(File directory) { + if(!directory.exists()) directory.mkdir(); + } + private void deleteDirectory(File directory) { /** * Go through each directory and check if it's not empty. diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Recording.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Recording.java index ad57e94dda..fd55e1e195 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Recording.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Recording.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Map; + import groovy.util.slurpersupport.GPathResult; public class Recording { @@ -108,7 +109,7 @@ public class Recording { public String getPlaybackFormat() { return playbackFormat; } - + public void setPlaybackFormat(String playbackFormat) { this.playbackFormat = playbackFormat; }