/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/sam/trunk/samigo-app/src/java/org/sakaiproject/tool/assessment/ui/servlet/delivery/UploadAudioMediaServlet.java $ * $Id: UploadAudioMediaServlet.java 121258 2013-03-15 15:03:36Z ottenhoff@longsight.com $ *********************************************************************************** * * Copyright (c) 2006, 2008, 2009 The Sakai Foundation * * Licensed under the Educational Community 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 * * http://www.opensource.org/licenses/ECL-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.sakaiproject.tool.assessment.ui.servlet.delivery; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.tool.assessment.data.dao.grading.AssessmentGradingData; import org.sakaiproject.tool.assessment.data.dao.grading.ItemGradingData; import org.sakaiproject.tool.assessment.data.dao.grading.MediaData; import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedItemData; import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedItemText; import org.sakaiproject.tool.assessment.services.assessment.PublishedAssessmentService; import org.sakaiproject.tool.assessment.services.GradingService; import java.util.Date; import java.util.ArrayList; /** * <p>Title: Samigo</p> * <p>Description: Sakai Assessment Manager. * Upload audio media to delivery bean. * This gets a posted input stream (from AudioRecorder.java in the client JVM) * and writes out to a file.</p> * @author Ed Smiley * @version $Id: UploadAudioMediaServlet.java 121258 2013-03-15 15:03:36Z ottenhoff@longsight.com $ */ public class UploadAudioMediaServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 8389831837152012411L; private static Log log = LogFactory.getLog(UploadAudioMediaServlet.class); public UploadAudioMediaServlet() { } public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { doPost(req,res); } public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { boolean mediaIsValid = true; ServletContext context = super.getServletContext(); String repositoryPath = (String)context.getAttribute("FILEUPLOAD_REPOSITORY_PATH"); String saveToDb = (String)context.getAttribute("FILEUPLOAD_SAVE_MEDIA_TO_DB"); log.debug("req content length ="+req.getContentLength()); log.debug("req content type ="+req.getContentType()); // we get media location in assessmentXXX/questionXXX/agentId/audio_assessmentGradingIdXXX.au form String suffix = req.getParameter("suffix"); if (suffix == null || ("").equals(suffix)) suffix = "au"; String mediaLocation = req.getParameter("media")+"."+suffix; log.debug("****media location="+mediaLocation); String response = "empty"; // test for nonemptiness first if (mediaLocation != null && !(mediaLocation.trim()).equals("")) { mediaLocation = repositoryPath+"/"+mediaLocation; File mediaFile = new File(mediaLocation); File mediaDir = mediaFile.getParentFile(); if (!mediaDir.exists()) mediaDir.mkdirs(); //log.debug("*** directory exist="+mediaDir.exists()); mediaIsValid=writeToFile(req, mediaLocation); //this is progess for SAK-5792, comment is out for now //zip_mediaLocation = createZipFile(mediaDir.getPath(), mediaLocation); } //#2 - record media as question submission if (mediaIsValid){ // note that this delivery bean is empty. this is not the same one created for the // user during take assessment. try{ response = submitMediaAsAnswer(req, mediaLocation, saveToDb); log.info("Audio has been saved and submitted as answer to the question. Any old recordings have been removed from the system."); } catch (Exception ex){ log.info(ex.getMessage()); } } res.setContentType("text/plain"); res.setContentLength(response.length()); PrintWriter out = res.getWriter(); out.println(response); out.close(); out.flush(); } private boolean writeToFile(HttpServletRequest req, String mediaLocation){ // default status message, if things go wrong boolean mediaIsValid = false; String status = "Upload failure: empty media location."; ServletInputStream inputStream = null; FileOutputStream fileOutputStream = null; BufferedInputStream bufInputStream = null; BufferedOutputStream bufOutputStream = null; int count = 0; try{ inputStream = req.getInputStream(); fileOutputStream = getFileOutputStream(mediaLocation); // buffered input for servlet bufInputStream = new BufferedInputStream(inputStream); // buffered output to file bufOutputStream = new BufferedOutputStream(fileOutputStream); // write the binary data int i = 0; count = 0; if (bufInputStream != null){ while ( (i = bufInputStream.read()) != -1){ bufOutputStream.write(i); count++; } } bufOutputStream.flush(); /* Move following clean up code to finally block // clean up bufOutputStream.close(); bufInputStream.close(); if (inputStream != null){ inputStream.close(); } fileOutputStream.close(); */ status = "Acknowleged: " +mediaLocation+"-> "+count+" bytes."; if (count > 0) mediaIsValid = true; } catch (Exception ex){ log.info(ex.getMessage()); status = "Upload failure: "+ mediaLocation; } finally { if (bufOutputStream != null) { try { bufOutputStream.close(); } catch(IOException e) { log.error(e.getMessage()); } } if (bufInputStream != null) { try { bufInputStream.close(); } catch(IOException e) { log.error(e.getMessage()); } } if (inputStream != null) { try { inputStream.close(); } catch(IOException e) { log.error(e.getMessage()); } } if (fileOutputStream != null) { try { fileOutputStream.close(); } catch(IOException e) { log.error(e.getMessage()); } } } log.info(status); return mediaIsValid; } /* private String createZipFile(String mediaDirString, String mediaLocation){ // Create a buffer for reading the files File file = new File(mediaLocation); String fileName=file.getName(); byte[] buf = new byte[1024]; String zip_mediaLocation = mediaDirString+"/"+fileName+".zip"; ZipOutputStream zip = null; FileInputStream in = null; FileOutputStream out = null; try { // Create the ZIP file log.debug("*** zip file="+zip_mediaLocation); out = new FileOutputStream(zip_mediaLocation); zip = new ZipOutputStream(out); // Add ZIP entry to output stream. zip.putNextEntry(new ZipEntry(fileName)); // Transfer bytes from the file to the ZIP file in = new FileInputStream(mediaLocation); int len; while ((len = in.read(buf)) > 0) { zip.write(buf, 0, len); } } catch (IOException e) { zip_mediaLocation=null; log.error("problem zipping file at "+mediaLocation); } finally { if (zip != null) { try { zip.closeEntry(); zip.close(); } catch (IOException e) { log.error(e.getMessage()); } } if (in != null) { try { in.close(); } catch (IOException e) { log.error(e.getMessage()); } } if (out != null) { try { out.close(); } catch (IOException e) { log.error(e.getMessage()); } } } return zip_mediaLocation; } */ private FileOutputStream getFileOutputStream(String mediaLocation){ FileOutputStream outputStream=null; try{ File media = new File(mediaLocation); outputStream = new FileOutputStream(media); } catch (FileNotFoundException ex) { log.warn("file not found="+ex.getMessage()); } return outputStream; } private String submitMediaAsAnswer(HttpServletRequest req, String mediaLocation, String saveToDb) throws Exception{ // read parameters passed in String mimeType = req.getContentType(); String duration = req.getParameter("lastDuration"); String agentId = req.getParameter("agent"); int attemptsRemaining = Integer.parseInt(req.getParameter("attempts")); GradingService gradingService = new GradingService(); PublishedAssessmentService pubService = new PublishedAssessmentService(); int assessmentIndex = mediaLocation.indexOf("assessment"); int questionIndex = mediaLocation.indexOf("question"); int agentIndex = mediaLocation.indexOf("/", questionIndex + 8); //int myfileIndex = mediaLocation.lastIndexOf("/"); String pubAssessmentId = mediaLocation.substring(assessmentIndex + 10, questionIndex - 1); String questionId = mediaLocation.substring(questionIndex + 8, agentIndex); //String agentEid = mediaLocation.substring(agentIndex+1, myfileIndex); //log.debug("****pubAss="+pubAssessmentId); //log.debug("****questionId="+questionId); //log.debug("****agent="+agentId); PublishedItemData item = pubService.loadPublishedItem(questionId); PublishedItemText itemText = (PublishedItemText)(item.getItemTextSet()).iterator().next(); log.debug("****agentId="+agentId); log.debug("****pubAssId="+pubAssessmentId); // 1. get assessmentGrading form DB AssessmentGradingData adata = gradingService.getLastSavedAssessmentGradingByAgentId( pubAssessmentId, agentId); if (adata == null){ // adata should already be created by BeginAssessment // lets throws exception throw new Exception("This page must have been reached by mistake."); } // 2. get itemGrading from DB, remove any attached media // also work out no. of attempts remaining ItemGradingData itemGrading = gradingService.getItemGradingData( adata.getAssessmentGradingId().toString(), questionId); ArrayList mediaList = new ArrayList(); if (itemGrading != null){ // just need update itemGrading, and media.media GradingService service = new GradingService(); if (itemGrading.getItemGradingId() != null) mediaList = service.getMediaArray(itemGrading.getItemGradingId().toString()); if (mediaList.size()>0){ log.debug("*** delete old audio"); gradingService.deleteAll(mediaList); } if (itemGrading.getAttemptsRemaining() == null){ // this is not possible unless the question is submitted without the // attempt set correctly if ((item.getTriesAllowed()).intValue() >= 9999) attemptsRemaining = 9999; } else{ if ((item.getTriesAllowed()).intValue() >= 9999 ) attemptsRemaining = 9999; else if (itemGrading.getAttemptsRemaining().intValue() > 0); // We're now getting the applet to tell us how many attempts remain // attemptsRemaining = itemGrading.getAttemptsRemaining().intValue() - 1; else throw new Exception("This page must have been reached by mistake. Our record shows that no more attempt for this question is allowed."); } } else{ // create an itemGrading if ((item.getTriesAllowed()).intValue() >= 9999 ) attemptsRemaining = 9999; else; // attemptsRemaining = (item.getTriesAllowed()).intValue() -1; itemGrading = new ItemGradingData(); itemGrading.setAssessmentGradingId(adata.getAssessmentGradingId()); itemGrading.setPublishedItemId(item.getItemId()); itemGrading.setPublishedItemTextId(itemText.getId()); itemGrading.setAgentId(agentId); itemGrading.setOverrideScore(Double.valueOf(0)); itemGrading.setSubmittedDate(new Date()); itemGrading.setAttemptsRemaining(Integer.valueOf(attemptsRemaining)); itemGrading.setLastDuration(duration); gradingService.saveItemGrading(itemGrading); } log.debug("****1. assessmentGradingId="+adata.getAssessmentGradingId()); log.debug("****2. attemptsRemaining="+attemptsRemaining); log.debug("****3. itemGradingDataId="+itemGrading.getItemGradingId()); // 3. save Media and fix up itemGrading return saveMedia(attemptsRemaining, mimeType, agentId, mediaLocation, itemGrading, saveToDb, duration); } private String saveMedia(int attemptsRemaining, String mimeType, String agent, String mediaLocation, ItemGradingData itemGrading, String saveToDb, String duration){ boolean SAVETODB = false; if ("true".equals(saveToDb)) SAVETODB = true; log.debug("****4. saveMedia, saveToDB"+SAVETODB); log.debug("****5. saveMedia, mediaLocation"+mediaLocation); GradingService gradingService = new GradingService(); // 1. create a media record File media = new File(mediaLocation); byte[] mediaByte = getMediaStream(mediaLocation); log.debug("**** SAVETODB=" + SAVETODB); MediaData mediaData = null; if (SAVETODB) { // put the byte[] in mediaData = new MediaData(itemGrading, mediaByte, Long.valueOf(mediaByte.length + ""), mimeType, "description", null, media.getName(), false, false, Integer.valueOf(1), agent, new Date(), agent, new Date(), duration); } else { // put the location in mediaData = new MediaData(itemGrading, null, Long.valueOf(mediaByte.length + ""), mimeType, "description", mediaLocation, media.getName(), false, false, Integer.valueOf(1), agent, new Date(), agent, new Date(), duration); } Long mediaId = gradingService.saveMedia(mediaData); log.debug("mediaId=" + mediaId); // 2. store mediaId in itemGradingRecord.answerText itemGrading.setAttemptsRemaining(Integer.valueOf(attemptsRemaining)); itemGrading.setSubmittedDate(new Date()); itemGrading.setAnswerText(mediaId + ""); itemGrading.setAutoScore(Double.valueOf(0)); gradingService.saveItemGrading(itemGrading); // 3. if saveToDB, remove file from file system try{ if (SAVETODB) { boolean success = media.delete(); if (!success) log.error ("Delete Failed for media. mediaid = " + mediaId); } } catch(Exception e){ log.warn(e.getMessage()); } return mediaId.toString(); } private byte[] getMediaStream(String mediaLocation) { FileInputStream mediaStream = null; FileInputStream mediaStream2 = null; byte[] mediaByte = new byte[0]; try { //int i = 0; int size = 0; mediaStream = new FileInputStream(mediaLocation); if (mediaStream != null) { //while ( (i = mediaStream.read()) != -1) while (mediaStream.read() != -1) { size++; } } mediaStream2 = new FileInputStream(mediaLocation); mediaByte = new byte[size]; if (mediaStream2 != null) { mediaStream2.read(mediaByte, 0, size); } } catch (FileNotFoundException ex) { log.debug("file not found=" + ex.getMessage()); } catch (IOException ex) { log.debug("io exception=" + ex.getMessage()); } finally { if (mediaStream != null) { try { mediaStream.close(); } catch (IOException ex1) { log.warn(ex1.getMessage()); } } if (mediaStream2 != null) { try { mediaStream2.close(); } catch (IOException ex1) { log.warn(ex1.getMessage()); } } } return mediaByte; } }