Return-Path: Delivered-To: apmail-jakarta-jetspeed-dev-archive@www.apache.org Received: (qmail 5244 invoked from network); 2 Jul 2004 14:37:25 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 2 Jul 2004 14:37:25 -0000 Received: (qmail 48615 invoked by uid 500); 2 Jul 2004 14:37:24 -0000 Delivered-To: apmail-jakarta-jetspeed-dev-archive@jakarta.apache.org Received: (qmail 48537 invoked by uid 500); 2 Jul 2004 14:37:22 -0000 Mailing-List: contact jetspeed-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Jetspeed Developers List" Reply-To: "Jetspeed Developers List" Delivered-To: mailing list jetspeed-dev@jakarta.apache.org Received: (qmail 48510 invoked by uid 500); 2 Jul 2004 14:37:22 -0000 Received: (qmail 48483 invoked by uid 500); 2 Jul 2004 14:37:21 -0000 Received: (qmail 48455 invoked by uid 99); 2 Jul 2004 14:37:20 -0000 X-ASF-Spam-Status: No, hits=0.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.27.1) with SMTP; Fri, 02 Jul 2004 07:37:20 -0700 Received: (qmail 5066 invoked by uid 1642); 2 Jul 2004 14:37:13 -0000 Date: 2 Jul 2004 14:37:13 -0000 Message-ID: <20040702143713.5065.qmail@minotaur.apache.org> From: weaver@apache.org To: jakarta-jetspeed-2-cvs@apache.org Subject: cvs commit: jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/util/descriptor PortletApplicationWar.java X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N weaver 2004/07/02 07:37:13 Modified: portal/src/java/org/apache/jetspeed/util/descriptor PortletApplicationWar.java Log: Big clean up/bug squashing on PortletApplicationWar Revision Changes Path 1.9 +269 -201 jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/util/descriptor/PortletApplicationWar.java Index: PortletApplicationWar.java =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/util/descriptor/PortletApplicationWar.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- PortletApplicationWar.java 24 Jun 2004 20:22:52 -0000 1.8 +++ PortletApplicationWar.java 2 Jul 2004 14:37:13 -0000 1.9 @@ -17,19 +17,19 @@ import java.io.File; import java.io.FileNotFoundException; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.io.Reader; +import java.io.Writer; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; -import java.util.Locale; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -37,9 +37,8 @@ import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSystemException; import org.apache.commons.vfs.FileSystemManager; -import org.apache.commons.vfs.VFS; +import org.apache.commons.vfs.FileType; import org.apache.commons.vfs.impl.VFSClassLoader; -import org.apache.commons.vfs.impl.StandardFileSystemManager; import org.apache.jetspeed.om.common.portlet.MutablePortletApplication; import org.apache.jetspeed.om.common.servlet.MutableWebApplication; import org.apache.jetspeed.tools.pamanager.PortletApplicationException; @@ -58,10 +57,18 @@ import org.xml.sax.SAXException; /** - * This class facilitates opertions a portlet applications WAR file or WAR file-like - * structure. - * + *

+ * This class facilitates operations a portlet applications WAR file or WAR + * file-like structure. + *

+ *

+ * This class is utility class used mainly implementors of + * {@link org.apache.jetspeed.pamanager.Deployment}and + * {@link org.apache.jetspeed.pamanager.Registration}to assist in deployment + * and undeployment of portlet applications. + * * @author Scott T. Weaver + * @author Matt Avery * @version $Id$ */ public class PortletApplicationWar @@ -77,91 +84,109 @@ protected String paName; protected String webAppContextRoot; - protected Locale locale; - protected String webAppDisplayName; protected FileObject warStruct; protected FileSystemManager fsManager; private MutableWebApplication webApp; private MutablePortletApplication portletApp; - - protected static final String[] ELEMENTS_BEFORE_SERVLET = new String[]{"icon", "display-name", "description", "distributable", "context-param", "filter", "filter-mapping", "listener", "servlet"}; protected static final String[] ELEMENTS_BEFORE_SERVLET_MAPPING = new String[]{"icon", "display-name", - "description", "distributable", "context-param", "filter", "filter-mapping", "listener", "servlet", "servlet-mapping"}; + "description", "distributable", "context-param", "filter", "filter-mapping", "listener", "servlet", + "servlet-mapping"}; /** - * @param warPath - * Path to a war file or war file structure - * @param paName - * name of the portlet application the warPath - * contains + * @param warFile + * org.apache.commons.vfs.FileObject representing + * the WAR file we are working with. This FileObject + * can be an actual WAR file or a directory structure layed out + * in a WAR-like fashion. name of the portlet application the + * warPath contains * @param webAppContextRoot - * context root relative to the servlet container of this app - * @param locale - * locale to deploy to - * @param webAppDisplayName - * @param vfsConfigUri - * Optional URI to a Commons VFS configuration file, since - * this class uses it to manipulate the WAR file. Can be - * null if we want Common VFS to use default behavior. + * context root relative to the servlet container of this app + * @param fsManager + * org.apache.commons.vfs.FileSystemManager that will be used to + * operate on the WAR file. * @throws IOException */ - public PortletApplicationWar( String warPath, String paName, String webAppContextRoot, Locale locale, - String webAppDisplayName, String vfsConfigUri ) throws IOException + public PortletApplicationWar( FileObject warStruct, String paName, String webAppContextRoot, + FileSystemManager fsManager ) throws IOException { - if (paName == null || paName.startsWith("/") || paName.startsWith("\\") || paName.endsWith("/") - || paName.endsWith("\\")) - { - throw new IllegalStateException("Invalid paName \"" + paName - + "\". paName cannot be null nor can it begin nor end with any slashes."); - } + validatePortletApplicationName(paName); - if (vfsConfigUri != null) + if (fsManager != null) { - StandardFileSystemManager standardManager = new StandardFileSystemManager(); - standardManager.setConfiguration(vfsConfigUri); - standardManager.init(); - fsManager = standardManager; + this.fsManager = fsManager; } else { - fsManager = VFS.getManager(); + throw new IllegalArgumentException("PortletApplicationWar requires a non-null FileSystemManager instance."); } - File warPathFile = new File(warPath).getAbsoluteFile(); - - if (!warPathFile.exists()) - { - throw new FileNotFoundException(warPathFile.getPath() + " does not exist."); - } - - if (warPathFile.isDirectory()) + + if(warStruct.getType().equals(FileType.FOLDER)) { - warStruct = fsManager.resolveFile(warPathFile.toURL().toExternalForm()); + this.warStruct = warStruct; } - else if (warPathFile.isFile()) + else { - warStruct = fsManager.resolveFile("jar:" + warPathFile.getAbsolutePath()); + throw new IllegalArgumentException(warStruct.getURL()+" must be of type FileType.FOLDER, not "+warStruct.getType()); } + this.paName = paName; this.webAppContextRoot = webAppContextRoot; - this.locale = locale; - this.webAppDisplayName = webAppDisplayName; } /** - * + * + * @param warPath + * A path on the file system that points to a WAR file we are + * working with. The warPath can be an actual WAR + * file or a directory structure layed out in a WAR-like fashion. + * name of the portlet application the warPath + * contains + * @param webAppContextRoot + * context root relative to the servlet container of this app + * @param fsManager + * org.apache.commons.vfs.FileSystemManager that will be used to + * operate on the WAR file. + * @throws IOException + */ + public PortletApplicationWar( String warPath, String paName, String webAppContextRoot, FileSystemManager fsManager ) + throws IOException + { + this(fsManager.toFileObject(new File(warPath)), paName, webAppContextRoot, fsManager); + } + + /** + *

+ * validatePortletApplicationName + *

+ * + * @param paName + */ + private void validatePortletApplicationName( String paName ) + { + if (paName == null || paName.startsWith("/") || paName.startsWith("\\") || paName.endsWith("/") + || paName.endsWith("\\")) + { + throw new IllegalStateException("Invalid paName \"" + paName + + "\". paName cannot be null nor can it begin nor end with any slashes."); + } + } + + /** + * *

* createWebApp *

* Creates a web applicaiton object based on the values in this WAR's * WEB-INF/web.xml - * + * * @return @throws - * PortletApplicationException + * PortletApplicationException * @throws IOException + * @see org.apache.jetspeed.util.descriptor.WebApplicationDescriptor */ public MutableWebApplication createWebApp() throws PortletApplicationException, IOException { @@ -169,8 +194,7 @@ try { - WebApplicationDescriptor webAppDescriptor = new WebApplicationDescriptor(webXmlReader, webAppContextRoot, - locale, webAppDisplayName); + WebApplicationDescriptor webAppDescriptor = new WebApplicationDescriptor(webXmlReader, webAppContextRoot); webApp = webAppDescriptor.createWebApplication(); return webApp; } @@ -193,16 +217,17 @@ } /** - * + * *

* createPortletApp *

* Creates a portlet application object based of the WAR file's * WEB-INF/portlet.xml - * + * * @return @throws - * PortletApplicationException + * PortletApplicationException * @throws IOException + * @see org.apache.jetspeed.uitl.descriptor.PortletApplicationDescriptor */ public MutablePortletApplication createPortletApp() throws PortletApplicationException, IOException { @@ -243,14 +268,20 @@ } /** - * + * *

* getReader *

- * + * Returns a java.io.Reader to a resource within this WAR's + * structure. + * * @param path - * @return @throws - * IOException + * realtive to an object within this WAR's file structure + * @return java.io.Reader to the file within the WAR + * @throws IOException + * if the path does not exist or there was a problem reading the + * WAR. + * */ protected Reader getReader( String path ) throws IOException { @@ -258,130 +289,128 @@ } /** - * + * *

* getInputStream *

- * + * + * Returns a java.io.InputStream to a resource within this + * WAR's structure. + * * @param path - * @return @throws - * IOException + * realtive to an object within this WAR's file structure + * @return java.io.InputStream to the file within the WAR + * @throws IOException + * if the path does not exist or there was a problem reading the + * WAR. */ protected InputStream getInputStream( String path ) throws IOException { FileObject child = warStruct.resolveFile(path); if (child == null) { - throw new IOException("Unable to locate file or path " + child); + throw new FileNotFoundException("Unable to locate file or path " + child); } return child.getContent().getInputStream(); } /** - * + * *

- * copyWar + * getOutputStream *

- * Copies the entire WAR structure to the path defined in - * targetAppRoot - * - * @param targetAppRoot + * + * Returns a java.io.OutputStream to a resource within this + * WAR's structure. + * + * @param path + * realtive to an object within this WAR's file structure + * @return java.io.Reader to the file within the WAR * @throws IOException + * if the path does not exist or there was a problem reading the + * WAR. */ - public void copyWar( String targetAppRoot ) throws IOException + protected OutputStream getOutputStream( String path ) throws IOException { - FileObject target = fsManager.resolveFile(new File(targetAppRoot).getAbsolutePath()); - - try - { - // fsManager.getFilesCache().clear(target.getFileSystem()); - - target.createFolder(); - target.copyFrom(warStruct, new AllFileSelector()); - - } - catch (FileSystemException e) - { - throw e; - } - finally + FileObject child = warStruct.resolveFile(path); + if (child == null) { - target.close(); - + throw new FileNotFoundException("Unable to locate file or path " + child); } - - + return child.getContent().getOutputStream(); } - public void copyWarAndProcessWebXml( String targetAppRoot ) throws IOException, MetaDataException + protected Writer getWriter( String path ) throws IOException { - copyWar(targetAppRoot); - InputStream webXmlIn = null; - OutputStream webXmlOut = null; - try - { - webXmlIn = getInputStream(WEB_XML_PATH); - processWebXML(webXmlIn, targetAppRoot + WEB_XML_PATH); - } - finally - { - if (webXmlIn != null) - { - webXmlIn.close(); - } - - if (webXmlOut != null) - { - webXmlOut.close(); - } - } - + return new OutputStreamWriter(getOutputStream(path)); } /** - * @param targetWebXml - * web.xml to "infuse" with J2 specific information + * + *

+ * copyWar + *

+ * Copies the entire WAR structure to the path defined in + * targetAppRoot + * + * @param targetAppRoot + * target to copy this WAR's content to. If the path ends in + * .war or .jar. The war will be + * copied into that file in jar format. + * @return PortletApplicationWar representing the newly created WAR. * @throws IOException - * when there is a problem reading or writing web.xml - * information - * @throws PortletApplicationException */ - public void processWebXML( String targetWebXml ) throws MetaDataException, IOException + public PortletApplicationWar copyWar( String targetAppRoot ) throws IOException { - InputStream webXmlIn = null; + FileObject target = fsManager.resolveFile(new File(targetAppRoot).getAbsolutePath()); try + { + target.copyFrom(warStruct, new AllFileSelector()); + + return new PortletApplicationWar(target, paName, webAppContextRoot, fsManager); + + } + catch (FileSystemException e) { - webXmlIn = getInputStream(WEB_XML_PATH); - processWebXML(webXmlIn, targetWebXml); + throw e; } finally { - if (webXmlIn != null) - { - webXmlIn.close(); - } + target.close(); + } } /** - * + * *

* removeWar *

* Deletes this WAR. If the WAR is a file structure and not an actual WAR * file, all children are delted first, then the directory is removed. - * + * * @throws IOException - * if there is an error removing the WAR from the file system. + * if there is an error removing the WAR from the file system. */ public void removeWar() throws IOException { - warStruct.delete(new AllFileSelector()); - warStruct.delete(); + File checkFile = new File(warStruct.getURL().getFile()); + if(checkFile.exists()) + { + warStruct.delete(new AllFileSelector()); + warStruct.delete(); + checkFile.delete(); + fsManager.getFilesCache().clear(warStruct.getFileSystem()); + } + else + { + fsManager.getFilesCache().clear(warStruct.getFileSystem()); + throw new FileNotFoundException("PortletApplicationWar ,"+warStruct.getURL().getFile()+", does not exist."); + } } /** @@ -395,9 +424,7 @@ * web application. An error message is logged and a * PortletApplicationException is thrown if not. * - * - * @param app - * The PortletApplicationDefinition to validate + * * @throws PortletApplicationException */ public void validate() throws PortletApplicationException @@ -435,24 +462,24 @@ } /** - * + * *

* processWebXML *

- * - * Infuses this the webXmlIn, which is expected to be the contents of a web.xml web - * application descriptor, with servlet and a servlet-mapping element - * for the JetspeedContainer servlet. This is only done if the descriptor does not already contain these - * items. - * - * @param webXmlIn web.xml content that is not yet infused - * @param webXmlOut target for infused web.xml content - * @throws MetaDataException if there is a problem infusing + * + * Infuses this PortletApplicationWar's web.xml file with + * servlet and a servlet-mapping element for + * the JetspeedContainer servlet. This is only done if the descriptor does + * not already contain these items. + * + * @throws MetaDataException + * if there is a problem infusing */ - protected void processWebXML( InputStream webXmlIn, String targetWebXml ) throws MetaDataException + public void processWebXML() throws MetaDataException { SAXBuilder builder = new SAXBuilder(); - FileWriter webXmlWriter = null; + Writer webXmlWriter = null; + InputStream webXmlIn = null; try { @@ -460,20 +487,19 @@ // allows to deploy the application offline builder.setEntityResolver(new EntityResolver() { - public InputSource resolveEntity(java.lang.String publicId, java.lang.String systemId) - throws SAXException, java.io.IOException + public InputSource resolveEntity( java.lang.String publicId, java.lang.String systemId ) + throws SAXException, java.io.IOException { if (systemId.equals("http://java.sun.com/dtd/web-app_2_3.dtd")) { return new InputSource(getClass().getResourceAsStream("web-app_2_3.dtd")); } - else - return null; + else return null; } }); - + webXmlIn = getInputStream(WEB_XML_PATH); Document doc = builder.build(webXmlIn); Element root = doc.getRootElement(); @@ -483,12 +509,11 @@ Object jetspeedServlet = XPath.selectSingleNode(doc, JETSPEED_SERVLET_XPATH); Object jetspeedServletMapping = XPath.selectSingleNode(doc, JETSPEED_SERVLET_MAPPING_XPATH); - if(doc.getRootElement().getChildren().size() ==0) + if (doc.getRootElement().getChildren().size() == 0) { throw new MetaDataException("Source web.xml has no content!!!"); } - log.debug("web.xml already contains servlet for the JetspeedContainer servlet."); log.debug("web.xml already contains servlet-mapping for the JetspeedContainer servlet."); @@ -496,16 +521,17 @@ { Element jetspeedServletElement = new Element("servlet"); Element servletName = (Element) new Element("servlet-name").addContent("JetspeedContainer"); - Element servletDspName =(Element) new Element("display-name").addContent("Jetspeed Container"); - Element servletDesc =(Element) new Element("description").addContent("MVC Servlet for Jetspeed Portlet Applications"); - Element servletClass = (Element) new Element("servlet-class") + Element servletDspName = (Element) new Element("display-name").addContent("Jetspeed Container"); + Element servletDesc = (Element) new Element("description") + .addContent("MVC Servlet for Jetspeed Portlet Applications"); + Element servletClass = (Element) new Element("servlet-class") .addContent("org.apache.jetspeed.container.JetspeedContainerServlet"); jetspeedServletElement.addContent(servletName); jetspeedServletElement.addContent(servletDspName); jetspeedServletElement.addContent(servletDesc); jetspeedServletElement.addContent(servletClass); - insertElementCorrectly(root, jetspeedServletElement, ELEMENTS_BEFORE_SERVLET); + insertElementCorrectly(root, jetspeedServletElement, ELEMENTS_BEFORE_SERVLET); changed = true; } @@ -514,7 +540,7 @@ Element jetspeedServletMappingElement = new Element("servlet-mapping"); - Element servletMapName = (Element) new Element("servlet-name").addContent("JetspeedContainer"); + Element servletMapName = (Element) new Element("servlet-name").addContent("JetspeedContainer"); Element servletUrlPattern = (Element) new Element("url-pattern").addContent("/container/*"); jetspeedServletMappingElement.addContent(servletMapName); @@ -526,12 +552,9 @@ if (changed) { - System.out.println("Writing out infused web.xml for "+paName); + System.out.println("Writing out infused web.xml for " + paName); XMLOutputter output = new XMLOutputter(Format.getPrettyFormat()); -// output.setIndent(" "); -// output.setNewlines(true); -// output.setTrimAllWhite(true); - webXmlWriter = new FileWriter(targetWebXml); + webXmlWriter = getWriter(WEB_XML_PATH); output.output(doc, webXmlWriter); webXmlWriter.flush(); @@ -544,7 +567,7 @@ } finally { - if(webXmlWriter != null) + if (webXmlWriter != null) { try { @@ -555,28 +578,43 @@ } } + + if (webXmlIn != null) + { + try + { + webXmlIn.close(); + } + catch (IOException e1) + { + + } + } } } /** - * + * *

* insertElementCorrectly *

- * - * @param root JDom element representing the < web-app > - * @param toInsert JDom element to insert into the web.xml hierarchy. - * @param elementsBefore an array of web.xml elements that should be defined - * before the element we want to insert. This order should be the order defined by the - * web.xml's DTD type definition. + * + * @param root + * JDom element representing the < web-app > + * @param toInsert + * JDom element to insert into the web.xml hierarchy. + * @param elementsBefore + * an array of web.xml elements that should be defined before the + * element we want to insert. This order should be the order + * defined by the web.xml's DTD type definition. */ protected void insertElementCorrectly( Element root, Element toInsert, String[] elementsBefore ) { List allChildren = root.getChildren(); List elementsBeforeList = Arrays.asList(elementsBefore); toInsert.detach(); - int insertAfter = 0; + int insertAfter = 0; for (int i = 0; i < allChildren.size(); i++) { Element element = (Element) allChildren.get(i); @@ -586,10 +624,10 @@ insertAfter = root.indexOf(element); } } - + try { - root.addContent((insertAfter+1), toInsert); + root.addContent((insertAfter + 1), toInsert); } catch (ArrayIndexOutOfBoundsException e) { @@ -598,42 +636,46 @@ } /** - * + * *

* close *

* Closes any resource this PortletApplicationWar may have opened. - * + * * @throws IOException */ public void close() throws IOException { warStruct.close(); + fsManager.getFilesCache().removeFile(warStruct.getFileSystem(), warStruct.getName()); + //fsManager.getFilesCache().clear(warStruct.getFileSystem()); } /** - * + * *

* createClassloader *

- * - * Use this method to create a classloader based on this wars structure. I.e. - * it will create a ClassLoader containing the contents of WEB-INF/classes and - * WEB-INF/lib and the ClassLoader will be searched in that order. - * - * - * @param parent Parent ClassLoader - * @return - * @throws IOException + * + * Use this method to create a classloader based on this wars structure. + * I.e. it will create a ClassLoader containing the contents of + * WEB-INF/classes and WEB-INF/lib and the ClassLoader will be searched in + * that order. + * + * + * @param parent + * Parent ClassLoader. Can be null + * @return @throws + * IOException */ - public ClassLoader createClassloader(ClassLoader parent) throws IOException + public ClassLoader createClassloader( ClassLoader parent ) throws IOException { ArrayList fileObjects = new ArrayList(); FileObject webInfClasses = null; try { webInfClasses = warStruct.resolveFile("WEB-INF/classes/"); - log.info("Adding "+webInfClasses.getURL()+" to class path."); + log.info("Adding " + webInfClasses.getURL() + " to class path."); fileObjects.add(webInfClasses); } catch (FileSystemException e) @@ -641,29 +683,55 @@ log.info("No class dependencies found"); } - - try + try { FileObject webInfLib = warStruct.resolveFile("WEB-INF/lib"); FileObject[] jars = webInfLib.getChildren(); URL[] jarUrls = new URL[jars.length]; - for(int i=0; i + * getDeployedPath + *

+ * + * @return A string representing the path to this WAR in the form of a URL + * or null is the URL could not be created. + */ + public String getDeployedPath() + { + try + { + return warStruct.getURL().toExternalForm(); + } + catch (FileSystemException e) + { + return null; + } + } +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: jetspeed-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: jetspeed-dev-help@jakarta.apache.org