You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pluto-scm@portals.apache.org by cd...@apache.org on 2006/12/03 17:39:15 UTC
svn commit: r481803 - in
/portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble:
ReassemblerConfig.java WarReassembler.java file/WarFileReassembler.java
Author: cdoremus
Date: Sun Dec 3 08:39:14 2006
New Revision: 481803
URL: http://svn.apache.org/viewvc?view=rev&rev=481803
Log:
New addition to support PLUTO-215.
Added:
portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/ReassemblerConfig.java
portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WarReassembler.java
portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/file/WarFileReassembler.java
Added: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/ReassemblerConfig.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/ReassemblerConfig.java?view=auto&rev=481803
==============================================================================
--- portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/ReassemblerConfig.java (added)
+++ portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/ReassemblerConfig.java Sun Dec 3 08:39:14 2006
@@ -0,0 +1,133 @@
+package org.apache.pluto.util.assemble;
+
+import java.io.File;
+
+/**
+ * Holds configuration for a <code>Reassembler</code>.
+ *
+ * @author <a href="cdoremus@apache.org">Craig Doremus</a>
+ *
+ */
+public class ReassemblerConfig {
+
+ /**
+ * Full path to the war file before unassembly.
+ */
+ private File warFilePath = null;
+
+ /**
+ * War file name
+ */
+ private String strWarFileName = null;
+
+ /**
+ * Root of the war file name without the .war
+ */
+ private String strRootWarFileName = null;
+
+ /**
+ * Root directory where file will unassemble war file.
+ */
+ private File rootUnassemblyDir = null;
+
+ /**
+ * Directory to unassemble war file.
+ */
+ private File unassemblyDir = null;
+
+ /**
+ * The destination of the reassembled war.
+ */
+ private File warDestination = null;
+
+ /**
+ * List of files in the archive
+ */
+ private String[] fileList = null;
+
+ /**
+ * @return the warFilePath
+ */
+ public File getWarFilePath() {
+ return warFilePath;
+ }
+
+ /**
+ * @param warFilePath the warFilePath to set
+ */
+ public void setWarFilePath(File warFilePath) {
+ this.warFilePath = warFilePath;
+ String strWarFilePath = warFilePath.getAbsolutePath();
+ //parse out the war file name
+ int index = strWarFilePath.lastIndexOf(File.separator);
+ //get file name
+ if (strWarFilePath == null) {
+ throw new IllegalArgumentException("War file path has not been set.");
+ }
+ if (strWarFileName == null) {
+ strWarFileName = strWarFilePath.substring(index + 1);
+ System.out.println("FileName: " + strWarFileName);
+ //Get root of file name (minus extension)
+ strRootWarFileName = strWarFileName.substring(0, strWarFileName.lastIndexOf("."));
+ }
+ System.out.println("rootFileName: " + strRootWarFileName);
+ }
+
+// public void setUnassemblyDir(File dir){
+// unassemblyDir = dir;
+// }
+
+ public File getUnassemblyDir(){
+ if (rootUnassemblyDir == null) {
+ throw new IllegalArgumentException("Parent directory to unassemble the war files so their web.xml file can be updated has not been set.");
+ }
+ if (unassemblyDir == null) {
+ unassemblyDir = new File(rootUnassemblyDir, strRootWarFileName);
+ }
+ return unassemblyDir;
+ }
+
+ /**
+ * @return the fileList
+ */
+ public String[] getFileList() {
+ return fileList;
+ }
+
+ /**
+ * @param fileList the fileList to set
+ */
+ public void setFileList(String[] fileList) {
+ this.fileList = fileList;
+ }
+
+ /**
+ * @return the warDestination
+ */
+ public File getWarDestination() {
+ return warDestination;
+ }
+
+ /**
+ * @param warDestination the warDestination to set
+ */
+ public void setWarDestination(File warDestination) {
+ this.warDestination = warDestination;
+ }
+
+ /**
+ * @return the rootUnassemblyDir
+ */
+ public File getRootUnassemblyDir() {
+ return rootUnassemblyDir;
+ }
+
+ /**
+ * @param rootUnassemblyDir the rootUnassemblyDir to set
+ */
+ public void setRootUnassemblyDir(File rootUnassemblyDir) {
+ this.rootUnassemblyDir = rootUnassemblyDir;
+ }
+
+
+}
Added: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WarReassembler.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WarReassembler.java?view=auto&rev=481803
==============================================================================
--- portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WarReassembler.java (added)
+++ portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/WarReassembler.java Sun Dec 3 08:39:14 2006
@@ -0,0 +1,18 @@
+package org.apache.pluto.util.assemble;
+
+import java.io.File;
+
+import org.apache.pluto.util.UtilityException;
+
+/**
+ * <code>Assembler</code> that reassembles an existing
+ * war file by, decompressing it, updating the web.xml file via
+ * the <code>Assembler</code> and rebuilding the war.
+ *
+ * @author <a href="cdoremus@apache.org">Craig Doremus</a>
+ *
+ */
+public interface WarReassembler extends Assembler {
+
+ public File reassemble(ReassemblerConfig config) throws UtilityException;
+}
Added: portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/file/WarFileReassembler.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/file/WarFileReassembler.java?view=auto&rev=481803
==============================================================================
--- portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/file/WarFileReassembler.java (added)
+++ portals/pluto/trunk/pluto-util/src/main/java/org/apache/pluto/util/assemble/file/WarFileReassembler.java Sun Dec 3 08:39:14 2006
@@ -0,0 +1,349 @@
+package org.apache.pluto.util.assemble.file;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pluto.descriptors.portlet.PortletAppDD;
+import org.apache.pluto.descriptors.services.castor.PortletAppDescriptorServiceImpl;
+import org.apache.pluto.util.UtilityException;
+import org.apache.pluto.util.assemble.AssemblerConfig;
+import org.apache.pluto.util.assemble.ReassemblerConfig;
+import org.apache.pluto.util.assemble.WarReassembler;
+
+/**
+ * This implementation of <code>WarReassemler</code> rebuilds an existing war
+ * file with an updated web.xml file so it can be deployed to Pluto.
+ *
+ * This file would be called after an <code>FileUploader</code> has uploaded
+ * a file to a directory that is the argument for the reassemble() method.
+ *
+ * @author <a href="cdoremus@apache.org">Craig Doremus</a>
+ *
+ */
+public class WarFileReassembler extends FileAssembler implements WarReassembler {
+ private static final Log LOG = LogFactory.getLog(WarFileReassembler.class);
+ private static final int BUFFER = 256;
+
+ /**
+ * Does the reassembly by decompressing the war, assembling the new web.xml file,
+ * and rebuilding the war.
+ *
+ * @see org.apache.pluto.driver.services.portal.admin.services.ReassembleWarAdminService#reassemble(java.lang.String)
+ */
+ public File reassemble(ReassemblerConfig config) throws UtilityException {
+ List portlets = null;
+ ReassemblerConfig config2 = null;
+ File newWar = null;
+ try {
+ //first, unzip war, returning a new config with file list and unassembly dir added
+ config2 = decompressWar(config);
+ //second, update web.xml using Assembler, checking for portlet.xml and web.xml before it does so
+ // returning a list of portlets from portlet.xml
+ portlets = updateWebXml(config2);
+ //third, create new war
+ newWar = createNewWar(config2);
+ } finally {
+ //cleanup
+// File dir = config2.getUnassemblyDir();
+// if (dir != null && dir.exists()) {
+// LOG.debug("Deleting dir: " + dir);
+// try {
+// FileUtils.forceDelete(dir);
+// } catch (IOException e) {
+// String msg = "Problem deleting unzipped directory structure";
+// UtilityException ue = new UtilityException(msg);
+// ue.initCause(e);
+// throw ue;
+// }
+// }
+ }
+ return newWar;
+ }
+
+ /**
+ * Unzips a war file into the file system into a directory that
+ * the parent directory plus a subdirectory that is the same
+ * name as the file name (without its extension).
+ *
+ * @param config Holds the path to the file to decompress.
+ * @return
+ */
+ ReassemblerConfig decompressWar(ReassemblerConfig config) throws UtilityException {
+// ReassemblerConfig retConfig = config;
+ ArrayList fileList = new ArrayList();
+ BufferedInputStream is = null;
+ FileOutputStream fos = null;
+ ZipFile zipFile = null;
+ try
+ {
+ // Specify file to decompress
+ File warFile = config.getWarFilePath();
+
+ //get the unzipping directory
+ File fUnzipDirectory = config.getUnassemblyDir();
+ //create the directory if necessary
+ if (!fUnzipDirectory.exists()) {
+ fUnzipDirectory.mkdir();
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Directory to unzip war for manipulating the web.xml : " + fUnzipDirectory.getAbsolutePath());
+ }
+
+ // Open Zip file for reading
+ zipFile = new ZipFile(warFile, ZipFile.OPEN_READ);
+
+ // Create an enumeration of the entries in the zip file
+ Enumeration zipFileEntries = zipFile.entries();
+
+ // Process each entry
+ while (zipFileEntries.hasMoreElements())
+ {
+ //grab a war file entry
+ ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
+
+ String currentEntry = entry.getName();
+ fileList.add(currentEntry);
+// System.out.println("Extracting: " + entry);
+
+ //Create a file representing the destination of the unwared file
+ File destDir =
+ new File(fUnzipDirectory, currentEntry);
+
+ //grab file's parent directory structure
+ File destinationParent = destDir.getParentFile();
+
+ //create the parent directory structure if needed
+ destinationParent.mkdirs();
+
+ //extract file from war if not a directory
+ if (!entry.isDirectory())
+ {
+// LOG.debug("Zip entry: " + entry.getName());
+ is = new BufferedInputStream(zipFile.getInputStream(entry));
+ // establish buffer for writing file into new location
+ byte data[] = new byte[BUFFER];
+
+ // read and write the current file to disk
+ fos = new FileOutputStream(destDir);
+ //read and write the file to disk until last byte is encountered
+ synchronized (is) {
+ synchronized (fos) {
+ while (true){
+ int bytesRead = is.read(data);
+ if (bytesRead == -1) {
+ break;
+ }
+ fos.write(data, 0, bytesRead);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ String msg = "Problem decompressing war";
+ LOG.error(msg, e);
+ UtilityException ue = new UtilityException(msg);
+ ue.initCause(e);
+ throw ue;
+ } finally {
+ if (zipFile != null) {
+ try {
+ zipFile.close();
+ } catch (IOException e) {
+ LOG.warn("Problem closing zip file output stream in decompressWar()", e);
+ }
+ }
+ if (fos != null) {
+ try {
+ fos.flush();
+ fos.close();
+ } catch (IOException e) {
+ LOG.warn("Problem flushing/closing file output stream in decompressWar()", e);
+ }
+ }
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ LOG.warn("Problem closing input stream in decompressWar()", e);
+ }
+ }
+ }
+ config.setFileList((String[])fileList.toArray(new String[fileList.size()]));
+ return config;
+ }
+
+ /**
+ * Uses the <code>assemble()</code> method to update the web.xml file.
+ *
+ */
+ List updateWebXml(ReassemblerConfig rconfig) throws UtilityException {
+ File fUnassembleDir = rconfig.getUnassemblyDir();
+ if (!fUnassembleDir.exists()) {
+ throw new UtilityException("The unzippling directory does not exist. Please check your configuration.");
+ }
+ String unassembledDir = fUnassembleDir.getAbsolutePath();
+ LOG.debug("Unassemble Dir in updateWebXml:" + unassembledDir);
+ File portletXmlFile = new File(unassembledDir + "/WEB-INF/portlet.xml");
+ //Check that portlet.xml and web.xml exists
+ if (!portletXmlFile.exists()) {
+ throw new UtilityException("The portlet.xml file does not exist in the archive.");
+ }
+ //get portlet list from portlet.xml
+ List portlets = getPortletList(portletXmlFile);
+ File webXmlFile = new File(unassembledDir + "/WEB-INF/web.xml");
+ if (!webXmlFile.exists()) {
+ throw new UtilityException("The web.xml file does not exist in the archive.");
+ }
+ //new file will replace the old one
+ File newWebXmlFile = new File(unassembledDir + "/WEB-INF/web.xml");
+ //Use assemble method to modify web.xml
+ // and replace it in unzipped war
+ AssemblerConfig config = new AssemblerConfig();
+ config.setPortletDescriptor(portletXmlFile);
+ config.setWebappDescriptor(webXmlFile);
+ config.setDestination(newWebXmlFile);
+
+ assemble(config);
+
+ return portlets;
+ }
+
+ /**
+ * Creates the fully assembled new war file.
+ * @param fileList
+ * @param warFilePath
+ */
+ File createNewWar(ReassemblerConfig config) throws UtilityException {
+
+ byte[] buffer = new byte[BUFFER];
+ //list of files in the war
+ String[] fileList = config.getFileList();
+ File file = config.getWarFilePath();
+ String warName = file.getName();
+ //there needs to be at least a web.xml, portlet.xml and portlet class file in the archive
+ if (fileList.length < 3) {
+ throw new UtilityException("There needs to be at least a web.xml, portlet.xml and portlet class file in the war file.");
+ }
+ File warFilePath = config.getWarDestination();
+ File newWar = new File(warFilePath + File.separator + warName);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Creating new war:" + newWar);
+ }
+ ZipOutputStream out = null;
+ try {
+// out = new ZipOutputStream(new FileOutputStream(warFilePath));
+ out = new ZipOutputStream(new FileOutputStream(newWar));
+ // Set the compression ratio
+ out.setLevel(Deflater.DEFAULT_COMPRESSION);
+
+ // iterate through the array of files, adding each to the zip file
+ for (int i = 0; i < fileList.length; i++) {
+ System.out.println("File to add to new zip: " + fileList[i]);
+ // Associate a file input stream for the current file
+ String entryFilePath = config.getUnassemblyDir() + File.separator + fileList[i];
+ // Create a file object for the entry
+ File entryFile = new File(entryFilePath);
+ LOG.debug("Path of file to add to new zip: " + entryFile.getAbsolutePath());
+// System.out.println("Does this file exist?: " + entryFile.exists());
+// System.out.println("Is this a file?: " + entryFile.isFile());
+ if (entryFile.isFile()) {
+ FileInputStream in = new FileInputStream(entryFile);
+
+ // Add ZIP entry to output stream.
+ out.putNextEntry(new ZipEntry(fileList[i]));
+
+ int len;
+ while ((len = in.read(buffer)) > 0) {
+ out.write(buffer, 0, len);
+ }
+
+ // Close the current entry
+ out.closeEntry();
+
+ // Close the current file input stream
+ in.close();
+ }
+ }
+ } catch (IllegalArgumentException e) {
+ String msg = "Problem creating new war";
+ LOG.error(msg, e);
+ UtilityException ue = new UtilityException(msg);
+ ue.initCause(e);
+ throw ue;
+ } catch (FileNotFoundException e) {
+ String msg = "Problem creating new war";
+ LOG.error(msg, e);
+ UtilityException ue = new UtilityException(msg);
+ ue.initCause(e);
+ throw ue;
+ } catch (IOException e) {
+ String msg = "Problem creating new war";
+ LOG.error(msg, e);
+ UtilityException ue = new UtilityException(msg);
+ ue.initCause(e);
+ throw ue;
+ } finally {
+ // Close the ZipOutPutStream
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ LOG.warn("Problem closing output stream to write a new war", e);
+ }
+ }
+ }
+
+ return newWar;
+ }
+
+ /**
+ * File list of portlet names in portlet.xml.
+ *
+ * @param portletXml The portlet.xml
+ * @return A <code>List</code> of portlet names.
+ */
+ List getPortletList(File portletXml) throws UtilityException {
+ List portlets = null;
+ //find portlets in portlet.xml
+ PortletAppDD dd = null;
+ try {
+ InputStream is = new FileInputStream(portletXml);
+ PortletAppDescriptorServiceImpl pappdesc = new PortletAppDescriptorServiceImpl();
+ dd = pappdesc.read(is);
+ } catch (FileNotFoundException e) {
+ String msg = "File cannot be found creating portlet list";
+ LOG.error(msg, e);
+ UtilityException ue = new UtilityException(msg);
+ ue.initCause(e);
+ throw ue;
+ } catch (IOException e) {
+ String msg = "I/O problem creating portlet list";
+ LOG.error(msg, e);
+ UtilityException ue = new UtilityException(msg);
+ ue.initCause(e);
+ throw ue;
+ }
+ if (dd != null) {
+ portlets = dd.getPortlets();
+ }
+ return portlets;
+ }
+}