Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF 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 * * 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.apache.pluto.util.assemble.io; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import java.util.jar.JarOutputStream; import java.util.zip.CRC32; import java.util.zip.ZipEntry; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.pluto.util.assemble.Assembler; /** * Utility class responsible for accepting a JarInputStream representing a web application archive, * iterating over each JarEntry in the input stream and assembling the WAR web.xml for portlet * deployment. */ public class JarStreamingAssembly { private static final Logger LOG = LoggerFactory.getLogger(JarStreamingAssembly.class); /** * Reads the source JarInputStream, copying entries to the destination JarOutputStream. * The web.xml and portlet.xml are cached, and after the entire archive is copied * (minus the web.xml) a re-written web.xml is generated and written to the * destination JAR. * * @param source the WAR source input stream * @param dest the WAR destination output stream * @param dispatchServletClass the name of the dispatch class * @throws IOException */ public static void assembleStream(JarInputStream source, JarOutputStream dest, String dispatchServletClass) throws IOException { try { //Need to buffer the web.xml and portlet.xml files for the rewritting JarEntry servletXmlEntry = null; byte[] servletXmlBuffer = null; byte[] portletXmlBuffer = null; JarEntry originalJarEntry; //Read the source archive entry by entry while ((originalJarEntry = source.getNextJarEntry()) != null) { final JarEntry newJarEntry = smartClone(originalJarEntry); originalJarEntry = null; //Capture the web.xml JarEntry and contents as a byte[], don't write it out now or //update the CRC or length of the destEntry. if (Assembler.SERVLET_XML.equals(newJarEntry.getName())) { servletXmlEntry = newJarEntry; servletXmlBuffer = IOUtils.toByteArray(source); } //Capture the portlet.xml contents as a byte[] else if (Assembler.PORTLET_XML.equals(newJarEntry.getName())) { portletXmlBuffer = IOUtils.toByteArray(source); dest.putNextEntry(newJarEntry); IOUtils.write(portletXmlBuffer, dest); } //Copy all other entries directly to the output archive else { dest.putNextEntry(newJarEntry); IOUtils.copy(source, dest); } dest.closeEntry(); dest.flush(); } // If no portlet.xml was found in the archive, skip the assembly step. if (portletXmlBuffer != null) { // container for assembled web.xml bytes final byte[] webXmlBytes; // Checks to make sure the web.xml was found in the archive if (servletXmlBuffer == null) { throw new FileNotFoundException( "File '" + Assembler.SERVLET_XML + "' could not be found in the source input stream."); } //Create streams of the byte[] data for the updater method final InputStream webXmlIn = new ByteArrayInputStream(servletXmlBuffer); final InputStream portletXmlIn = new ByteArrayInputStream(portletXmlBuffer); final ByteArrayOutputStream webXmlOut = new ByteArrayOutputStream(servletXmlBuffer.length); //Update the web.xml WebXmlStreamingAssembly.assembleStream(webXmlIn, portletXmlIn, webXmlOut, dispatchServletClass); IOUtils.copy(webXmlIn, webXmlOut); webXmlBytes = webXmlOut.toByteArray(); //If no compression is being used (STORED) we have to manually update the size and crc if (servletXmlEntry.getMethod() == ZipEntry.STORED) { servletXmlEntry.setSize(webXmlBytes.length); final CRC32 webXmlCrc = new CRC32(); webXmlCrc.update(webXmlBytes); servletXmlEntry.setCrc(webXmlCrc.getValue()); } //write out the assembled web.xml entry and contents dest.putNextEntry(servletXmlEntry); IOUtils.write(webXmlBytes, dest); if (LOG.isDebugEnabled()) { LOG.debug("Jar stream " + source + " successfully assembled."); } } else { if (LOG.isDebugEnabled()) { LOG.debug("No portlet XML file was found, assembly was not required."); } //copy the original, unmodified web.xml entry to the destination dest.putNextEntry(servletXmlEntry); IOUtils.write(servletXmlBuffer, dest); if (LOG.isDebugEnabled()) { LOG.debug("Jar stream " + source + " successfully assembled."); } } } finally { dest.flush(); dest.close(); } } private static JarEntry smartClone(JarEntry originalJarEntry) { final JarEntry newJarEntry = new JarEntry(originalJarEntry.getName()); newJarEntry.setComment(originalJarEntry.getComment()); newJarEntry.setExtra(originalJarEntry.getExtra()); newJarEntry.setMethod(originalJarEntry.getMethod()); newJarEntry.setTime(originalJarEntry.getTime()); //Must set size and CRC for STORED entries if (newJarEntry.getMethod() == ZipEntry.STORED) { newJarEntry.setSize(originalJarEntry.getSize()); newJarEntry.setCrc(originalJarEntry.getCrc()); } return newJarEntry; } }