/** * Licensed to Apereo under one or more contributor license * agreements. See the NOTICE file distributed with this work * for additional information regarding copyright ownership. * Apereo licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a * copy of the License at the following location: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.jasig.portlet.blackboardvcportlet.service.impl; import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import javax.activation.DataHandler; import javax.activation.FileDataSource; import javax.servlet.ServletContext; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.jasig.portlet.blackboardvcportlet.dao.ConferenceUserDao; import org.jasig.portlet.blackboardvcportlet.dao.MultimediaDao; import org.jasig.portlet.blackboardvcportlet.dao.PresentationDao; import org.jasig.portlet.blackboardvcportlet.dao.SessionDao; import org.jasig.portlet.blackboardvcportlet.dao.SessionTelephonyDao; import org.jasig.portlet.blackboardvcportlet.dao.UserSessionUrlDao; import org.jasig.portlet.blackboardvcportlet.dao.ws.MultimediaWSDao; import org.jasig.portlet.blackboardvcportlet.dao.ws.PresentationWSDao; import org.jasig.portlet.blackboardvcportlet.dao.ws.SessionWSDao; import org.jasig.portlet.blackboardvcportlet.data.ConferenceUser; import org.jasig.portlet.blackboardvcportlet.data.ConferenceUser.Roles; import org.jasig.portlet.blackboardvcportlet.data.Multimedia; import org.jasig.portlet.blackboardvcportlet.data.Presentation; import org.jasig.portlet.blackboardvcportlet.data.Session; import org.jasig.portlet.blackboardvcportlet.data.SessionTelephony; import org.jasig.portlet.blackboardvcportlet.data.UserSessionUrl; import org.jasig.portlet.blackboardvcportlet.security.ConferenceUserService; import org.jasig.portlet.blackboardvcportlet.service.MailTemplateService; import org.jasig.portlet.blackboardvcportlet.service.SessionForm; import org.jasig.portlet.blackboardvcportlet.service.SessionService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.oxm.XmlMappingException; import org.springframework.security.access.prepost.PostFilter; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import org.springframework.web.context.ServletContextAware; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.util.WebUtils; import org.springframework.ws.client.WebServiceClientException; import com.elluminate.sas.BlackboardMultimediaResponse; import com.elluminate.sas.BlackboardPresentationResponse; import com.elluminate.sas.BlackboardSessionResponse; import com.elluminate.sas.BlackboardSessionTelephonyResponse; import com.google.common.base.Function; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterators; @Service public class SessionServiceImpl implements SessionService, ServletContextAware { protected final Logger logger = LoggerFactory.getLogger(getClass()); private ConferenceUserService conferenceUserService; private ConferenceUserDao conferenceUserDao; private SessionDao sessionDao; private MultimediaDao multimediaDao; private PresentationDao presentationDao; private SessionWSDao sessionWSDao; private MultimediaWSDao multimediaWSDao; private PresentationWSDao presentationWSDao; private MailTemplateService mailService; private SessionTelephonyDao sessionTelephonyDao; private File tempDir; private UserSessionUrlDao userSessionUrlDao; @Autowired public void setMailTemplateService(MailTemplateService mailService) { this.mailService = mailService; } @Autowired public void setUserSessionUrlDao (UserSessionUrlDao dao) { this.userSessionUrlDao = dao; } @Autowired public void setPresentationDao(PresentationDao presentationDao) { this.presentationDao = presentationDao; } @Autowired public void setMultimediaDao(MultimediaDao multimediaDao) { this.multimediaDao = multimediaDao; } @Autowired public void setConferenceUserDao(ConferenceUserDao conferenceUserDao) { this.conferenceUserDao = conferenceUserDao; } @Autowired public void setConferenceUserService(ConferenceUserService conferenceUserService) { this.conferenceUserService = conferenceUserService; } @Autowired public void setSessionDao(SessionDao sessionDao) { this.sessionDao = sessionDao; } @Autowired public void setSessionWSDao(SessionWSDao value) { this.sessionWSDao = value; } @Autowired public void setMultimediaWSDao(MultimediaWSDao multimediaWSDao) { this.multimediaWSDao = multimediaWSDao; } @Autowired public void setPresentationWSDao(PresentationWSDao presentationWSDao) { this.presentationWSDao = presentationWSDao; } @Autowired public void setSessionTelephonyDao(SessionTelephonyDao dao) { this.sessionTelephonyDao = dao; } @Override public void setServletContext(ServletContext servletContext) { this.tempDir = WebUtils.getTempDir(servletContext); } /** * A user needs "edit" to view the set of session chairs but we don't want the call to fail * if they only have "view" permission. So we pre-auth them with view and then filter all * the results unless they have "edit" */ @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#session, 'view')") @PostFilter("hasRole('ROLE_ADMIN') || hasPermission(#session, 'edit')") public Set<ConferenceUser> getSessionChairs(Session session) { return new LinkedHashSet<ConferenceUser>(sessionDao.getSessionChairs(session)); } @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#session, 'view')") public boolean isSessionParticipant(Session session, ConferenceUser user) { ConferenceUser userFromDB = conferenceUserDao.getUser(user.getUserId()); return (sessionDao.getSessionChairs(session).contains(userFromDB) || sessionDao.getSessionNonChairs(session).contains(userFromDB)); } @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#session, 'view')") @Transactional public String getOrCreateSessionUrl(ConferenceUser user, Session session) { return getOrCreateSessionUrl(user, session,false); } @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#session, 'view')") @Transactional public String getOrCreateSessionUrl(ConferenceUser user, Session session, boolean forceFetch) { //check for the url in the db UserSessionUrl url = null; if(!forceFetch) url = userSessionUrlDao.getUserSessionUrlsBySessionAndUser(session, user); if(url == null) { //if null then create a user's session url via web service call String urlString = sessionWSDao.buildSessionUrl(session.getBbSessionId(), user); //save to the database url = userSessionUrlDao.createUserSessionUrl(session, user, urlString); } return url.getUrl(); } @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#session, 'view')") @Transactional public void deleteSessionUrl(ConferenceUser user, Session session) { userSessionUrlDao.deleteOldSessionUrls(session, user); } @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#session, 'view')") public void populateLaunchUrl(ConferenceUser user, Session session) { if(isSessionParticipant(session, user)) { session.setLaunchUrl(getOrCreateSessionUrl(user, session)); } else { session.setLaunchUrl(session.getGuestUrl()); } } /** * A user needs "edit" to view the set of session non chairs but we don't want the call to fail * if they only have "view" permission. So we pre-auth them with view and then filter all * the results unless they have "edit" */ @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#session, 'view')") @PostFilter("hasRole('ROLE_ADMIN') || hasPermission(#session, 'edit')") public Set<ConferenceUser> getSessionNonChairs(Session session) { return new LinkedHashSet<ConferenceUser>(sessionDao.getSessionNonChairs(session)); } /** * A user needs "edit" and ROLE_FULL_ACCESS to view the set of session multemedia * but we don't want the call to fail if they only have "view" permission. So we * pre-auth them with view and then filter all the results unless they have ROLE_FULL_ACCESS and "edit" */ @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#session, 'view')") @PostFilter("hasRole('ROLE_ADMIN') || (hasRole('ROLE_FULL_ACCESS') && hasPermission(#session, 'edit'))") public Set<Multimedia> getSessionMultimedia(Session session) { return new LinkedHashSet<Multimedia>(sessionDao.getSessionMultimedias(session)); } @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'view')") public Session getSession(long sessionId) { return this.sessionDao.getSession(sessionId); } @Override @PreAuthorize("hasRole('ROLE_ADMIN')") public Set<Session> getAllSessions() { return this.sessionDao.getAllSessions(); } /* * Not rolling back for WS related exceptions so the work done "so far" is still persisted to the database in * an attempt to keep the WS and DB layers in sync */ @Override @Transactional(noRollbackFor = { WebServiceClientException.class, XmlMappingException.class }) @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void removeSession(long sessionId) { final Session session = this.sessionDao.getSession(sessionId); final Set<Multimedia> multimedias = this.sessionDao.getSessionMultimedias(session); for (final Multimedia multimedia : multimedias) { removeMultimediaFromSession(session, null, multimedia); } this.deletePresentation(session.getSessionId()); //This sends cancellation email for creator, chairs, and non-chairs this.mailService.buildAndSendCancelationMeetingEmail(session); this.sessionWSDao.deleteSession(session.getBbSessionId()); this.sessionDao.deleteSession(session); } private void removeMultimediaFromSession(Session session, Set<Long> bbMultimediaIds, Multimedia multimedia) { //Un-link multimedia file from session if (bbMultimediaIds != null) { if(bbMultimediaIds.contains(multimedia.getBbMultimediaId())) this.multimediaWSDao.removeSessionMultimedia(session.getBbSessionId(), multimedia.getBbMultimediaId()); } else { this.multimediaWSDao.removeSessionMultimedia(session.getBbSessionId(), multimedia.getBbMultimediaId()); } this.sessionDao.deleteMultimediaFromSession(session, multimedia); //Delete multimedia file from repository try { this.multimediaWSDao.removeRepositoryMultimedia(multimedia.getBbMultimediaId()); } catch (WebServiceClientException e) { //See if the multimedia file actually exists final List<BlackboardMultimediaResponse> userMultimedias = this.multimediaWSDao.getRepositoryMultimedias(null, multimedia.getBbMultimediaId(), null); //Multimedia file exists but we failed to remove it, throw the exception if (!userMultimedias.isEmpty()) { throw e; } //Multimedia file doesn't exist on the BB side, remove our local DB version } this.multimediaDao.deleteMultimedia(multimedia); } @Override @Transactional @PreAuthorize("#sessionForm.newSession || hasRole('ROLE_ADMIN') || hasPermission(#sessionForm.sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public Session createOrUpdateSession(ConferenceUser user, SessionForm sessionForm) { final Session session; if (sessionForm.isNewSession()) { final BlackboardSessionResponse sessionResponse = sessionWSDao.createSession(user, sessionForm); final String guestUrl = sessionWSDao.buildGuestSessionUrl(sessionResponse.getSessionId()); session = sessionDao.createSession(sessionResponse, guestUrl); mailService.buildAndSendSessionEmails(session, false, true); } else { session = sessionDao.getSession(sessionForm.getSessionId()); final BlackboardSessionResponse sessionResponse = sessionWSDao.updateSession(session.getBbSessionId(), sessionForm); boolean isTimeChange = !(session.getStartTime().getMillis() == sessionResponse.getStartTime()) || !(session.getEndTime().getMillis() == sessionResponse.getEndTime()); sessionDao.updateSession(sessionResponse); if(isTimeChange) { mailService.buildAndSendSessionEmails(session, true, sessionForm.isNeedToSendInitialEmail()); } } return session; } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public ConferenceUser addSessionChair(long sessionId, String displayName, String email) { final ConferenceUser newSessionChair = this.conferenceUserService.getOrCreateConferenceUser(displayName, email); this.addSessionChair(sessionId, newSessionChair, true); return newSessionChair; } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public ConferenceUser updateRole(long sessionId, long userId, Roles newRole) { final ConferenceUser user = this.conferenceUserDao.getUser(userId); final Session session = this.sessionDao.getSession(sessionId); this.deleteSessionUrl(user, session); if(Roles.CHAIR.equals(newRole)) { //remove nonchair this.removeSessionNonChairs(sessionId, false, userId); //add chair this.addSessionChair(sessionId, user, false); } else { //remove chair this.removeSessionChairs(sessionId, false, userId); //add nonchair this.addSessionNonChair(sessionId, user, false); } //send update role email mailService.sendEmail(mailService.buildSwitchRolesEmail(user, session, newRole)); return user; } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public ConferenceUser addSessionChair(long sessionId, long userId, boolean sendEmail) { final ConferenceUser user = this.conferenceUserDao.getUser(userId); if (user != null) { addSessionChair(sessionId, user, sendEmail); } return user; } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public ConferenceUser addSessionChair(long sessionId, long userId) { return addSessionChair(sessionId,userId, true); } private void addSessionChair(long sessionId, ConferenceUser user, boolean sendEmail) { Assert.notNull(user, "user must not be null"); final Session session = this.sessionDao.getSession(sessionId); final Set<ConferenceUser> sessionChairs = new LinkedHashSet<ConferenceUser>(this.getSessionChairs(session)); sessionChairs.add(user); final BlackboardSessionResponse sessionResponse = this.sessionWSDao.setSessionChairs(session.getBbSessionId(), sessionChairs); sessionDao.updateSession(sessionResponse); if(sendEmail) mailService.sendEmail(mailService.buildModeratorMailTask(user, session, false)); } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void removeSessionChairs(long sessionId, boolean sendEmail, long... userIds) { final Set<ConferenceUser> users = conferenceUserDao.getUsers(userIds); this.removeSessionChairs(sessionId, users, sendEmail); } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void removeSessionChairs(long sessionId, long... userIds) { removeSessionChairs(sessionId, true, userIds); } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void removeSessionChairs(long sessionId, Iterable<ConferenceUser> users) { removeSessionChairs(sessionId, users, true); } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void removeSessionChairs(long sessionId, Iterable<ConferenceUser> users, boolean sendCancelEmail) { final Session session = this.sessionDao.getSession(sessionId); final Set<ConferenceUser> sessionChairs = new LinkedHashSet<ConferenceUser>(this.getSessionChairs(session)); for (final ConferenceUser user : users) { // the user might or might not be a session chair, // so we might or might not be making a change. // If we're not making a change because they are not a chair to remove // then don't bother sending an email. // remove the user if present and note whether was present boolean madeChange = sessionChairs.remove(user); // if we made a change and we are to send an email, send it. if(madeChange && sendCancelEmail) { mailService.sendEmail(mailService.buildCancellationNoticeMailTask(user, session)); } } final BlackboardSessionResponse sessionResponse; if(sessionChairs.isEmpty()) { this.sessionWSDao.clearSessionChairList(session.getBbSessionId()); sessionDao.clearSessionUserList(session.getSessionId(), true); } else { sessionResponse = this.sessionWSDao.setSessionChairs(session.getBbSessionId(), sessionChairs); sessionDao.updateSession(sessionResponse); } } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public ConferenceUser addSessionNonChair(long sessionId, String displayName, String email) { final ConferenceUser newSessionNonChair = this.conferenceUserService.getOrCreateConferenceUser(displayName, email); addSessionNonChair(sessionId, newSessionNonChair, true); return newSessionNonChair; } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public ConferenceUser addSessionNonChair(long sessionId, long userId) { final ConferenceUser user = this.conferenceUserDao.getUser(userId); if (user != null) { this.addSessionNonChair(sessionId, user, true); } return user; } private void addSessionNonChair(long sessionId, ConferenceUser user, boolean sendEmail) { Assert.notNull(user, "user must not be null"); final Session session = this.sessionDao.getSession(sessionId); final Set<ConferenceUser> sessionNonChairs = new LinkedHashSet<ConferenceUser>(this.getSessionNonChairs(session)); sessionNonChairs.add(user); final BlackboardSessionResponse sessionResponse = this.sessionWSDao.setSessionNonChairs(session.getBbSessionId(), sessionNonChairs); sessionDao.updateSession(sessionResponse); if(sendEmail) mailService.sendEmail(mailService.buildParticipantMailTask(user, session, false)); } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void removeSessionNonChairs(long sessionId, long... userIds) { final Set<ConferenceUser> users = conferenceUserDao.getUsers(userIds); this.removeSessionNonChairs(sessionId, users); } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void removeSessionNonChairs(long sessionId, boolean sendEmail, long... userIds) { final Set<ConferenceUser> users = conferenceUserDao.getUsers(userIds); this.removeSessionNonChairs(sessionId, users, sendEmail); } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void removeSessionNonChairs(long sessionId, Iterable<ConferenceUser> users) { removeSessionNonChairs(sessionId, users,true); } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void removeSessionNonChairs(long sessionId, Iterable<ConferenceUser> users, boolean sendEmail) { final Session session = this.sessionDao.getSession(sessionId); final Set<ConferenceUser> sessionNonChairs = new LinkedHashSet<ConferenceUser>(this.getSessionNonChairs(session)); for (final ConferenceUser user : users) { // the user might or might not be a non-chair, so // we might or might not be there to remove. // if this is a no-op, do not bother the user with a confusing email. // remove the user and note whether this had any effect boolean madeChange = sessionNonChairs.remove(user); if (madeChange && sendEmail) { mailService.sendEmail(mailService.buildCancellationNoticeMailTask(user, session)); } } if(sessionNonChairs.isEmpty()) { this.sessionWSDao.clearSessionNonChairList(session.getBbSessionId()); sessionDao.clearSessionUserList(session.getSessionId(), false); } else { final BlackboardSessionResponse sessionResponse = this.sessionWSDao.setSessionNonChairs(session.getBbSessionId(), sessionNonChairs); sessionDao.updateSession(sessionResponse); } } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || (hasRole('ROLE_FULL_ACCESS') && hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit'))") public void addMultimedia(long sessionId, MultipartFile file) { final Session session = this.sessionDao.getSession(sessionId); final ConferenceUser conferenceUser = this.conferenceUserService.getCurrentConferenceUser(); final BlackboardMultimediaResponse multimediaResponse = createSessionMultimedia(session, conferenceUser, file); //Add Multimedia object to local DB final String filename = FilenameUtils.getName(file.getOriginalFilename()); final Multimedia multimedia = this.multimediaDao.createMultimedia(multimediaResponse, filename); //Associate Multimedia with session this.sessionDao.addMultimediaToSession(session, multimedia); } @Override @Transactional(noRollbackFor = { WebServiceClientException.class, XmlMappingException.class }) @PreAuthorize("hasRole('ROLE_ADMIN') || (hasRole('ROLE_FULL_ACCESS') && hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit'))") public void deleteMultimedia(long sessionId, long... multimediaIds) { final Session session = this.sessionDao.getSession(sessionId); final Set<Long> bbMultimediaIds = getBlackboardMultimediaIds(session); for (final long multimediaId : multimediaIds) { final Multimedia multimedia = this.multimediaDao.getMultimediaById(multimediaId); removeMultimediaFromSession(session, bbMultimediaIds, multimedia); } } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || (hasRole('ROLE_FULL_ACCESS') && hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit'))") public void addPresentation(long sessionId, MultipartFile file) { final Session session = this.sessionDao.getSession(sessionId); if (session.getPresentation() != null) { this.deletePresentation(session.getSessionId()); } final ConferenceUser conferenceUser = this.conferenceUserService.getCurrentConferenceUser(); final BlackboardPresentationResponse presentationResponse = createSessionPresentation(session, conferenceUser, file); final String filename = FilenameUtils.getName(file.getOriginalFilename()); final Presentation presentation = this.presentationDao.createPresentation(presentationResponse, filename); //Associate Presentation with session this.sessionDao.addPresentationToSession(session, presentation); } @Override @Transactional @PreAuthorize("hasRole('ROLE_ADMIN') || (hasRole('ROLE_FULL_ACCESS') && hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit'))") public void deletePresentation(long sessionId) { final Session session = this.sessionDao.getSession(sessionId); final Presentation presentation = session.getPresentation(); if (presentation == null) { return; } try { this.presentationWSDao.deleteSessionPresenation(session.getBbSessionId(), presentation.getBbPresentationId()); } catch (WebServiceClientException e) { //See if the presentation association actually exists final List<BlackboardPresentationResponse> sessionPresentations = this.presentationWSDao.getSessionPresentations(session.getBbSessionId()); //Session presentation exists but failed to remove it, throw the exception if (!sessionPresentations.isEmpty()) { throw e; } //Presentation association doesn't exist but we still need to delete the association no our side. } this.sessionDao.removePresentationFromSession(session); try { this.presentationWSDao.deletePresentation(presentation.getBbPresentationId()); } catch (WebServiceClientException e) { //See if the presentation actually exists final ConferenceUser creator = session.getCreator(); final List<BlackboardPresentationResponse> repositoryPresentations = this.presentationWSDao.getRepositoryPresentations(creator.getUniqueId(), presentation.getBbPresentationId(), null); //Presentation exists but failed to remove it, throw the exception if (!repositoryPresentations.isEmpty()) { throw e; } //Presentation doesn't exist but we still need to delete the association no our side. } this.presentationDao.deletePresentation(presentation); } private Set<Long> getBlackboardMultimediaIds(final Session session) { final List<BlackboardMultimediaResponse> multimedias = this.multimediaWSDao.getSessionMultimedias(session.getBbSessionId()); final Iterator<BlackboardMultimediaResponse> multimediasItr = multimedias.iterator(); return ImmutableSet.copyOf( Iterators.transform(multimediasItr, new Function<BlackboardMultimediaResponse, Long>() { public Long apply(BlackboardMultimediaResponse r) { return r.getMultimediaId(); } })); } private BlackboardMultimediaResponse createSessionMultimedia(Session session, ConferenceUser conferenceUser, MultipartFile file) { final String filename = FilenameUtils.getName(file.getOriginalFilename()); File multimediaFile = null; try { //Transfer the uploaded file to our own temp file so we can use a FileDataSource multimediaFile = File.createTempFile(filename, ".tmp", this.tempDir); file.transferTo(multimediaFile); //Upload the file to BB return this.multimediaWSDao.createSessionMultimedia( session.getBbSessionId(), conferenceUser.getUniqueId(), filename, "", new DataHandler(new FileDataSource(multimediaFile))); } catch (IOException e) { throw new RuntimeException("Failed to upload multimedia file '" + filename + "'", e); } finally { FileUtils.deleteQuietly(multimediaFile); } } //TODO consolidate these, extract uploadPresentation/createSessionMultimedia to generic interface and use that private BlackboardPresentationResponse createSessionPresentation(Session session, ConferenceUser conferenceUser, MultipartFile file) { final String filename = FilenameUtils.getName(file.getOriginalFilename()); File multimediaFile = null; try { //Transfer the uploaded file to our own temp file so we can use a FileDataSource multimediaFile = File.createTempFile(filename, ".tmp", this.tempDir); file.transferTo(multimediaFile); //Upload the file to BB return this.presentationWSDao.uploadPresentation( session.getBbSessionId(), conferenceUser.getUniqueId(), filename, "", new DataHandler(new FileDataSource(multimediaFile))); } catch (IOException e) { throw new RuntimeException("Failed to upload multimedia file '" + filename + "'", e); } finally { FileUtils.deleteQuietly(multimediaFile); } } @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#session, 'view')") public SessionTelephony getSessionTelephony(Session session) { return sessionTelephonyDao.getSessionTelephony(session); } @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void createOrUpdateSessionTelephony(long sessionId, SessionTelephony telephony) { Session session = getSession(sessionId); BlackboardSessionTelephonyResponse response = sessionWSDao.createSessionTelephony(session.getBbSessionId(), telephony); sessionTelephonyDao.createOrUpdateTelephony(response); } @Override @PreAuthorize("hasRole('ROLE_ADMIN') || hasPermission(#sessionId, 'org.jasig.portlet.blackboardvcportlet.data.Session', 'edit')") public void deleteSessionTelephony(long sessionId) { Session session = getSession(sessionId); //delete ws record sessionWSDao.removeSessionTelephony(session.getBbSessionId()); //delete local db record sessionTelephonyDao.deleteTelephony(sessionId); } }