Java tutorial
/* * eXist Open Source Native XML Database * Copyright (C) 2001-06 The eXist Project * http://exist-db.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * $Id$ */ package org.exist.webstart; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamWriter; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; import org.apache.commons.io.output.ByteArrayOutputStream; /** * Class for writing JNLP file, jar files and image files. * * @author Dannes Wessels */ public class JnlpWriter { public static final String JAR_MIME_TYPE = "application/x-java-archive"; public static final String PACK_MIME_TYPE = "application/x-java-pack200"; public static final String ACCEPT_ENCODING = "accept-encoding"; public static final String CONTENT_TYPE = "content-type"; public static final String CONTENT_ENCODING = "content-encoding"; public static final String PACK200_GZIP_ENCODING = "pack200-gzip"; private static Logger logger = Logger.getLogger(JnlpWriter.class); /** * Write JNLP xml file to browser. * * @param response Object for writing to end user. * @throws java.io.IOException */ void writeJnlpXML(JnlpJarFiles jnlpFiles, HttpServletRequest request, HttpServletResponse response) throws IOException { logger.debug("Writing JNLP file"); // Format URL: "http://host:8080/CONTEXT/webstart/exist.jnlp" final String currentUrl = request.getRequestURL().toString(); // Find BaseUrl http://host:8080/CONTEXT final int webstartPos = currentUrl.indexOf("/webstart"); final String existBaseUrl = currentUrl.substring(0, webstartPos); // Find codeBase for jarfiles http://host:8080/CONTEXT/webstart/ final String codeBase = existBaseUrl + "/webstart/"; // Perfom sanity checks int counter = 0; for (final File jar : jnlpFiles.getAllWebstartJars()) { counter++; // debugging if (jar == null || !jar.exists()) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Missing Jar file! (" + counter + ")"); return; } } // Find URL to connect to with client final String startUrl = existBaseUrl.replaceFirst("http:", "xmldb:exist:") .replaceFirst("https:", "xmldb:exist:").replaceAll("-", "%2D") + "/xmlrpc"; // response.setDateHeader("Last-Modified", mainJar.lastModified()); response.setContentType("application/x-java-jnlp-file"); try { final XMLStreamWriter writer = XMLOutputFactory.newInstance() .createXMLStreamWriter(response.getOutputStream()); writer.writeStartDocument(); writer.writeStartElement("jnlp"); writer.writeAttribute("spec", "1.0+"); writer.writeAttribute("codebase", codeBase); writer.writeAttribute("href", "exist.jnlp"); writer.writeStartElement("information"); writer.writeStartElement("title"); writer.writeCharacters("eXist XML-DB client"); writer.writeEndElement(); writer.writeStartElement("vendor"); writer.writeCharacters("exist-db.org"); writer.writeEndElement(); writer.writeStartElement("homepage"); writer.writeAttribute("href", "http://exist-db.org"); writer.writeEndElement(); writer.writeStartElement("description"); writer.writeCharacters("Integrated command-line and gui client, " + "entirely based on the XML:DB API and provides commands " + "for most database related tasks, like creating and " + "removing collections, user management, batch-loading " + "XML data or querying."); writer.writeEndElement(); writer.writeStartElement("description"); writer.writeAttribute("kind", "short"); writer.writeCharacters("eXist XML-DB client"); writer.writeEndElement(); writer.writeStartElement("description"); writer.writeAttribute("kind", "tooltip"); writer.writeCharacters("eXist XML-DB client"); writer.writeEndElement(); writer.writeStartElement("icon"); writer.writeAttribute("href", "jnlp_logo.jpg"); writer.writeEndElement(); writer.writeStartElement("icon"); writer.writeAttribute("href", "jnlp_icon_128x128.gif"); writer.writeAttribute("width", "128"); writer.writeAttribute("height", "128"); writer.writeEndElement(); writer.writeStartElement("icon"); writer.writeAttribute("href", "jnlp_icon_64x64.gif"); writer.writeAttribute("width", "64"); writer.writeAttribute("height", "64"); writer.writeEndElement(); writer.writeStartElement("icon"); writer.writeAttribute("href", "jnlp_icon_32x32.gif"); writer.writeAttribute("width", "32"); writer.writeAttribute("height", "32"); writer.writeEndElement(); writer.writeEndElement(); // information writer.writeStartElement("security"); writer.writeEmptyElement("all-permissions"); writer.writeEndElement(); // ---------- writer.writeStartElement("resources"); writer.writeStartElement("property"); writer.writeAttribute("name", "jnlp.packEnabled"); writer.writeAttribute("value", "true"); writer.writeEndElement(); writer.writeStartElement("j2se"); writer.writeAttribute("version", "1.6+"); writer.writeEndElement(); for (final File jar : jnlpFiles.getAllWebstartJars()) { writer.writeStartElement("jar"); writer.writeAttribute("href", jar.getName()); writer.writeAttribute("size", "" + jar.length()); writer.writeEndElement(); } writer.writeEndElement(); // resources writer.writeStartElement("application-desc"); writer.writeAttribute("main-class", "org.exist.client.InteractiveClient"); writer.writeStartElement("argument"); writer.writeCharacters("-ouri=" + startUrl); writer.writeEndElement(); writer.writeStartElement("argument"); writer.writeCharacters("--no-embedded-mode"); writer.writeEndElement(); if (request.isSecure()) { writer.writeStartElement("argument"); writer.writeCharacters("--use-ssl"); writer.writeEndElement(); } writer.writeEndElement(); // application-desc writer.writeEndElement(); // jnlp writer.writeEndDocument(); writer.flush(); writer.close(); } catch (final Throwable ex) { logger.error(ex); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage()); } } /** * Send JAR or JAR.PACK.GZ file to end user. * * @param filename Name of JAR file * @param response Object for writing to end user. * @throws java.io.IOException */ void sendJar(JnlpJarFiles jnlpFiles, String filename, HttpServletRequest request, HttpServletResponse response) throws IOException { logger.debug("Send jar file " + filename); final File localFile = jnlpFiles.getJarFile(filename); if (localFile == null || !localFile.exists()) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "Jar file '" + filename + "' not found."); return; } logger.debug("Actual file " + localFile.getAbsolutePath()); if (localFile.getName().endsWith(".jar")) { //response.setHeader(CONTENT_ENCODING, JAR_MIME_TYPE); response.setContentType(JAR_MIME_TYPE); } else if (localFile.getName().endsWith(".jar.pack.gz")) { response.setHeader(CONTENT_ENCODING, PACK200_GZIP_ENCODING); response.setContentType(PACK_MIME_TYPE); } // It is very improbable that a 64 bit jar is needed, but // it is better to be ready // response.setContentLength(Integer.parseInt(Long.toString(localFile.length()))); response.setHeader("Content-Length", Long.toString(localFile.length())); response.setDateHeader("Last-Modified", localFile.lastModified()); final FileInputStream fis = new FileInputStream(localFile); final ServletOutputStream os = response.getOutputStream(); try { // Transfer bytes from in to out final byte[] buf = new byte[4096]; int len; while ((len = fis.read(buf)) > 0) { os.write(buf, 0, len); } } catch (final IllegalStateException ex) { logger.debug(ex.getMessage()); } catch (final IOException ex) { logger.debug("Ignore IOException for '" + filename + "'"); } os.flush(); os.close(); fis.close(); } void sendImage(JnlpHelper jh, JnlpJarFiles jf, String filename, HttpServletResponse response) throws IOException { logger.debug("Send image " + filename); String type = null; if (filename.endsWith(".gif")) { type = "image/gif"; } else if (filename.endsWith(".png")) { type = "image/png"; } else { type = "image/jpeg"; } final InputStream is = this.getClass().getResourceAsStream("resources/" + filename); if (is == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "Image file '" + filename + "' not found."); return; } // Copy data final ByteArrayOutputStream baos = new ByteArrayOutputStream(); IOUtils.copy(is, baos); IOUtils.closeQuietly(is); // It is very improbable that a 64 bit jar is needed, but // it is better to be ready response.setContentType(type); response.setContentLength(baos.size()); //response.setHeader("Content-Length", ""+baos.size()); final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); final ServletOutputStream os = response.getOutputStream(); try { IOUtils.copy(bais, os); } catch (final IllegalStateException ex) { logger.debug(ex.getMessage()); } catch (final IOException ex) { logger.debug("Ignored IOException for '" + filename + "' " + ex.getMessage()); } // Release resources os.flush(); os.close(); bais.close(); } }