/** * Copyright (c) 2009--2011 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package com.redhat.rhn.frontend.servlets; import com.redhat.rhn.common.util.OvalFileAggregator; import com.redhat.rhn.domain.errata.Errata; import com.redhat.rhn.domain.errata.ErrataFactory; import com.redhat.rhn.manager.errata.ErrataManager; import org.apache.log4j.Logger; import org.jdom.JDOMException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet interface for downloading OVAL files * * @version $Rev $ */ public class OvalServlet extends HttpServlet { private static Logger logger = Logger.getLogger(OvalServlet.class); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String[] errataIds = request.getParameterValues("errata"); if (errataIds == null || errataIds.length == 0) { response.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } for (int x = 0; x < errataIds.length; x++) { try { String tmp = URLDecoder.decode(errataIds[x], "UTF-8"); errataIds[x] = tmp; } catch (UnsupportedEncodingException e) { logger.warn(e.getMessage(), e); } } String format = request.getParameter("format"); if (format == null || (!format.equalsIgnoreCase("xml") && !format.equals("zip"))) { format = "xml"; } else { format = format.toLowerCase(); } List erratas = new LinkedList(); for (int x = 0; x < errataIds.length; x++) { List tmp = ErrataManager.lookupErrataByIdentifier(errataIds[x]); if (tmp != null && tmp.size() > 0) { erratas.addAll(tmp); } } if (erratas.size() == 0) { response.sendError(HttpServletResponse.SC_NOT_FOUND, errataIds[0]); return; } List ovalFiles = new LinkedList(); if (erratas.size() == 1) { Errata errata = (Errata) erratas.get(0); List of = ErrataFactory.lookupErrataFilesByErrataAndFileType(errata.getId(), "oval"); if (of != null && of.size() > 0) { ovalFiles.addAll(of); } } else if (erratas.size() > 1) { for (Iterator iter = erratas.iterator(); iter.hasNext();) { Errata errata = (Errata) iter.next(); List files = ErrataFactory.lookupErrataFilesByErrataAndFileType( errata.getId(), "oval"); ovalFiles.addAll(files); } } if (format.equals("xml")) { streamXml(ovalFiles, response); } else { prepareZipFile(ovalFiles, response); } } private void prepareZipFile(List ovalFiles, HttpServletResponse response) throws IOException { File tempFile = File.createTempFile("rhn", "errata", new File("/tmp")); List files = ErrataManager.resolveOvalFiles(ovalFiles); if (files.size() == 0) { return; } try { ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(tempFile)); for (Iterator iter = files.iterator(); iter.hasNext();) { File f = (File) iter.next(); ZipEntry entry = new ZipEntry(f.getName()); zipOut.putNextEntry(entry); writeFileEntry(f, zipOut); } zipOut.flush(); zipOut.close(); streamZipFile(tempFile, response); } finally { if (!tempFile.delete()) { tempFile.deleteOnExit(); } } } private void streamZipFile(File zipFile, HttpServletResponse response) throws IOException { response.setContentType("application/zip"); response.addHeader("Content-disposition", "attachment; filename=oval.zip"); if (zipFile.length() < Integer.MAX_VALUE) { response.setContentLength((int) zipFile.length()); } InputStream fileIn = null; try { fileIn = new FileInputStream(zipFile); sendFileContents(fileIn, response); } finally { if (fileIn != null) { fileIn.close(); } } } private void sendFileContents(InputStream contents, HttpServletResponse response) throws IOException { try { OutputStream out = response.getOutputStream(); byte[] chunk = new byte[4096]; int readsize = -1; while ((readsize = contents.read(chunk)) > -1) { out.write(chunk, 0, readsize); } } finally { contents.close(); } } private void writeFileEntry(File f, ZipOutputStream zipOut) throws IOException { byte[] chunk = new byte[4096]; int readsize = -1; InputStream fileIn = null; try { fileIn = new FileInputStream(f); while ((readsize = fileIn.read(chunk)) > -1) { zipOut.write(chunk, 0, readsize); } zipOut.closeEntry(); } finally { if (fileIn != null) { fileIn.close(); } } } private void streamXml(List files, HttpServletResponse response) throws IOException { response.setContentType("text/xml"); String fileName = null; List ovalFiles = ErrataManager.resolveOvalFiles(files); switch(ovalFiles.size()) { case 0: return; case 1: File ftmp = (File) ovalFiles.get(0); if (ftmp == null) { response.sendError(404, (String) files.get(0)); } fileName = ftmp.getName().toLowerCase(); if (!fileName.endsWith(".xml")) { fileName += ".xml"; } break; default: fileName = "oval.xml"; break; } response.addHeader("Content-disposition", "attachment; filename=" + fileName); if (ovalFiles.size() == 1) { File f = (File) ovalFiles.get(0); if (f.length() < Integer.MAX_VALUE) { response.setContentLength((int) f.length()); } InputStream fileIn = null; try { fileIn = new FileInputStream(f); sendFileContents(fileIn, response); } finally { if (fileIn != null) { fileIn.close(); } } } else { try { String aggregate = aggregateOvalFiles(ovalFiles); response.getWriter().print(aggregate); response.getWriter().flush(); } catch (Exception e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); logger.error(e.getMessage(), e); } } } private String aggregateOvalFiles(List files) throws JDOMException, IOException { OvalFileAggregator aggregator = new OvalFileAggregator(); String retval = null; for (Iterator iter = files.iterator(); iter.hasNext();) { File f = (File) iter.next(); if (f == null) { continue; } aggregator.add(f); } retval = aggregator.finish(false); return retval; } }