User: d_jencks Date: 02/04/13 18:19:54 Modified: src/main/org/jboss/deployment JARDeployer.java MainDeployer.java SARDeployer.java SubDeployerSupport.java Log: Larry Sanderson's patch to enable deploying unpacked directories Revision Changes Path 1.3 +21 -9 jboss-system/src/main/org/jboss/deployment/JARDeployer.java Index: JARDeployer.java =================================================================== RCS file: /cvsroot/jboss/jboss-system/src/main/org/jboss/deployment/JARDeployer.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- JARDeployer.java 3 Apr 2002 08:18:59 -0000 1.2 +++ JARDeployer.java 14 Apr 2002 01:19:54 -0000 1.3 @@ -14,6 +14,7 @@ import java.net.JarURLConnection; import java.net.URL; import java.net.URLConnection; +import java.net.URLClassLoader; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -90,11 +91,26 @@ return false; } // end of if () - URL ddDir = di.localCl.getResource("META-INF/"); - if (ddDir == null) + // Since a META-INF directory exists within rt.jar, we can't just do a + // getResource (it will always return rt.jar's version). + // The method we want is findResource, but it is marked protected in + // ClassLoader. Fortunately, URLClassLoader exposes it which makes + // this hack possible. Anybody have a better way to check a URL + // for the existance of a META-INF?? + URL ddDir; + try { - log.debug("no META-INF or WEB-INF found, this is for us"); - return true; + ddDir = ((URLClassLoader)di.localCl).findResource("META-INF/"); + if (ddDir == null) + { + log.debug("no META-INF or WEB-INF found, this is for us"); + return true; + } + } + catch (ClassCastException e) + { + // assume there is a META-INF... + ddDir = new URL(di.url, "META-INF/"); } if (ddDir.getProtocol().equals("file")) @@ -119,16 +135,12 @@ } // end of if () else if (ddDir.getProtocol().equals("jar") || ddDir.getProtocol().equals("njar")) { - //trying to open ddDir as a jarFile seems to result in listing - //the entire contents of the JRE!!! log.trace("jar or njar protocol: " + ddDir.getProtocol()); JarFile jarFile =null; - String jarURLString = "njar:"+di.localUrl.toString()+"^/"; try { - URL jarURL = new URL(jarURLString); - URLConnection con = jarURL.openConnection(); + URLConnection con = ddDir.openConnection(); JarURLConnection jarConn = (JarURLConnection)con; jarFile = jarConn.getJarFile(); } 1.26 +36 -163 jboss-system/src/main/org/jboss/deployment/MainDeployer.java Index: MainDeployer.java =================================================================== RCS file: /cvsroot/jboss/jboss-system/src/main/org/jboss/deployment/MainDeployer.java,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- MainDeployer.java 13 Apr 2002 17:16:08 -0000 1.25 +++ MainDeployer.java 14 Apr 2002 01:19:54 -0000 1.26 @@ -45,6 +45,7 @@ import org.jboss.system.server.ServerConfig; import org.jboss.system.server.ServerConfigLocator; import org.jboss.util.Counter; +import org.jboss.util.file.JarUtils; import org.jboss.util.jmx.MBeanProxy; import org.jboss.util.stream.Streams; import java.util.LinkedList; @@ -57,7 +58,7 @@ * @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a> * @author <a href="mailto:[EMAIL PROTECTED]">Scott Stark</a> * @author <a href="mailto:[EMAIL PROTECTED]">David Jencks</a> - * @version $Revision: 1.25 $ + * @version $Revision: 1.26 $ * * @jmx:mbean name="jboss.system:service=MainDeployer" * extends="org.jboss.system.ServiceMBean, org.jboss.deployment.DeployerMBean" @@ -90,9 +91,6 @@ /** The string naming the tempDir **/ private String tempDirString; - /** The temporary directory where native libs are unpacked. */ - private File tempNativeDir; - /** * Holds the native library <em>prefix</em> for this system. * Determined by examining the result of System.mapLibraryName("XxX"). @@ -254,7 +252,6 @@ File basedir = config.getServerTempDir(); tempDir = new File(basedir, "deploy"); - tempNativeDir = new File(basedir, "native"); // used in isWatched tempDirString = tempDir.toURL().toString(); @@ -428,6 +425,10 @@ deploymentList.remove(deploymentList.lastIndexOf(di)); } } + synchronized (waitingDeployments) + { + waitingDeployments.remove(di); + } // Nuke my stuff, this includes the class loader di.cleanup(log); @@ -554,7 +555,7 @@ } catch (Exception e) { - log.info("Exception notifying class removed", e); + log.info("Exception notifying classloader added", e); } //serviceController.newClassLoaderNotification(); } // end of if () @@ -575,7 +576,7 @@ deployment.deployer.init(deployment); // create subdeployments as needed - unpackSubPackages(deployment); + parseManifestLibraries(deployment); log.debug("found " + deployment.subDeployments.size() + " subpackages of " + deployment.url); for (Iterator lt = sorter.sort(deployment.subDeployments).listIterator(); lt.hasNext();) { @@ -744,161 +745,6 @@ } /** - * extractPackages - * - * TODO marcf: support directories as well right now depends on the jar format - * - * In case of identifiable sub-deployment we recursively call the deploy method - * on the deployer - */ - protected void unpackSubPackages(DeploymentInfo di) - throws DeploymentException - { - // If XML only no subdeployment to speak of. We also do not - // break a war into subdeployments as this opens the door to - // servlet 2.3 classloading stuff we don't want to deal with here - // FIXME do the sub deploy for directory and the move to - if (di.isXML || di.isDirectory || di.shortName.endsWith(".war") ) - { - return ; - } - // J2EE legacy goo in manifest - parseManifestLibraries(di); - - JarFile jarFile =null; - - // Then the packages inside the package being deployed - - // marcf FIXME FIXME FIXME add support for directories not just jar files - - // Do we have a jar file jar:<theURL>!/.. - String jarURLString = "njar:"+di.localUrl.toString()+"^/"; - try - { - URL jarURL = new URL(jarURLString); - URLConnection con = jarURL.openConnection(); - JarURLConnection jarConn = (JarURLConnection)con; - jarFile = jarConn.getJarFile(); - } - catch (Exception e) - { - log.warn("operation failed; ignoring", e); - - //maybe this is not a jar nor a directory... - log.info("deploying non-jar/xml file: " + di.url); - return; - } - - for (Enumeration e = jarFile.entries(); e.hasMoreElements();) - { - JarEntry entry = (JarEntry)e.nextElement(); - String name = entry.getName(); - - // Everything that is not - // a- an XML file - // b- a class in a normal directory structure - // is a "package" and will be deployed - if (name.endsWith(".jar") - || name.endsWith(".sar") - || name.endsWith(".ear") - || name.endsWith(".rar") - || name.endsWith(".zip") - || name.endsWith(".wsr")) - { - try - { - // It is a sub-deployment - URL subURL = new URL("njar:" + di.localUrl.toString() + "^/" + name); - DeploymentInfo sub = new DeploymentInfo(subURL, di); - - // And deploy it, this call is recursive - di.subDeployments.add(sub); - } - catch (Exception ex) - { - log.error("Error in subDeployment with name "+name, ex); - throw new DeploymentException - ("Could not deploy sub deployment "+name+" of deployment "+di.url, ex); - } - } - - // WARNING: Do not close the jarFile let it hang until undeployment - // The reason is that if you close the jarFile you cannot open streams - // to files inside. The bug can be seen as follow - // Thread.currentThread().getContextClassLoader().getResource("a text file in jar").openStream()) - // Doesn't work while - // Thread.currentThread().getContextClassLoader().loadClass("a class in the jar") - // works - // We should encapsulate "opening and closing of the jarFile" in the DeploymentInfo - // Here we let it be open and cached - else if (name.endsWith(".war")) - { - /**we need to copy wars to a real file, no one else will understand our njar:...^/ - * protocol... not even jetty - */ - try - { - URL subUrl = new URL("njar:" + di.localUrl.toString() + "^/" + name); - //!!!!!!!!!!!!!!!!NONONONONO FIXME TODO etc etc - //this is not where the dest file should be - File destFile = new File(tempDir, name); - URL destUrl = destFile.toURL(); - //System.out.println("war copy: subUrl: " + subUrl); - //System.out.println("war copy: destFile: " + destFile); - - log.debug("copying war to: " + destUrl.toString()); - copy(subUrl, destUrl); - DeploymentInfo sub = new DeploymentInfo(destUrl, di); - } - catch (Exception ware) - { - throw new DeploymentException("Problem copying war: " + di.localUrl, ware); - } // end of try-catch - } // end of if () - else - { - //is it a native library? - if (nativeSuffix == null) - { - String nativex = System.mapLibraryName("XxX"); - int xPos = nativex.indexOf("XxX"); //hope "XxX' is not part of any native lib goo! - nativePrefix = nativex.substring(0, xPos); - nativeSuffix = nativex.substring(xPos + 3); - } // end of if () - - if (name.endsWith(nativeSuffix)) - { - int i = name.lastIndexOf("/"); - if (name.substring(Math.max(i, 0)).startsWith(nativePrefix)) - { - try - { - //it's a native library for our system (we hope!), copy it. - URL subUrl = new URL("njar:" + di.localUrl.toString() + "^/" + name); - File destFile = new File(tempNativeDir, name); - log.info("Loading native library: " + destFile.toString()); - URL destUrl = destFile.toURL(); - copy(subUrl, destUrl); - System.load(destFile.toString()); - } - catch (Exception nativee) - { - throw new DeploymentException("error with native library! " + di.localUrl, nativee); - } // end of try-catch - - - } // end of if () - - - } // end of if () - - - } // end of else - } - } - - - /** * The <code>parseManifestLibraries</code> method looks into the manifest for classpath * goo, and tries to deploy referenced packages. * @@ -967,7 +813,6 @@ * Downloads the jar file or directory the src URL points to. * In case of directory it becomes packed to a jar file. * - * @todo Add support for Directory copying over. * @todo FIXME: $JBOSS_HOME/tmp/deploy is not a valid reference. * * @return a File object representing the downloaded module @@ -1043,6 +888,19 @@ dir.mkdirs(); } + if (_src.getProtocol().equals("file")) + { + File srcFile = new File(_src.getFile()); + if (srcFile.isDirectory()) + { + log.debug("Making zip copy of: " + srcFile); + // make a jar archive of the directory + OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); + JarUtils.jar(out, srcFile.listFiles()); + out.close(); + return; + } + } InputStream in = new BufferedInputStream(_src.openStream()); OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); Streams.copy(in, out); @@ -1090,6 +948,7 @@ * * @param url an <code>URL</code> value * @return a <code>DeploymentInfo</code> value + * @jmx:managed-operation */ public DeploymentInfo getDeployment(URL url) { @@ -1097,6 +956,20 @@ { return (DeploymentInfo) deploymentMap.get(url); } + } + + /** + * The <code>getWatchUrl</code> method returns the URL that, when modified, + * indicates that a redeploy is needed. + * + * @param url an <code>URL</code> value + * @return a <code>URL</code> value + * @jmx:managed-operation + */ + public URL getWatchUrl(URL url) + { + DeploymentInfo info = getDeployment(url); + return info == null ? null : info.watch; } } 1.7 +7 -3 jboss-system/src/main/org/jboss/deployment/SARDeployer.java Index: SARDeployer.java =================================================================== RCS file: /cvsroot/jboss/jboss-system/src/main/org/jboss/deployment/SARDeployer.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- SARDeployer.java 12 Apr 2002 05:01:39 -0000 1.6 +++ SARDeployer.java 14 Apr 2002 01:19:54 -0000 1.7 @@ -72,7 +72,7 @@ * @author <a href="mailto:[EMAIL PROTECTED]">David Maplesden</a> * @author <a href="mailto:[EMAIL PROTECTED]">David Jencks</a> * @author <a href="mailto:[EMAIL PROTECTED]">Jason Dillon</a> - * @version $Revision: 1.6 $ + * @version $Revision: 1.7 $ * * <p><b>20010830 marc fleury:</b> * <ul> @@ -143,8 +143,9 @@ */ public boolean accepts(DeploymentInfo di) { - return (di.url.toString().endsWith(".sar") - || di.url.toString().endsWith("service.xml")); + String urlStr = di.url.toString(); + return urlStr.endsWith("sar") || urlStr.endsWith("sar/") || + urlStr.endsWith("service.xml"); } /** @@ -217,6 +218,9 @@ log.error("Problem in init", e); throw new DeploymentException(e); } + + // invoke super-class initialization + processNestedDeployments(di); } /** 1.2 +239 -4 jboss-system/src/main/org/jboss/deployment/SubDeployerSupport.java Index: SubDeployerSupport.java =================================================================== RCS file: /cvsroot/jboss/jboss-system/src/main/org/jboss/deployment/SubDeployerSupport.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SubDeployerSupport.java 3 Apr 2002 08:18:02 -0000 1.1 +++ SubDeployerSupport.java 14 Apr 2002 01:19:54 -0000 1.2 @@ -10,6 +10,24 @@ package org.jboss.deployment; import org.jboss.system.ServiceMBeanSupport; +import java.net.URL; +import java.util.ArrayList; +import java.io.File; +import java.net.URLConnection; +import java.net.JarURLConnection; +import java.util.jar.JarFile; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.net.MalformedURLException; +import java.util.List; +import org.jboss.system.server.ServerConfigLocator; +import org.jboss.system.server.ServerConfig; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.FileOutputStream; +import org.jboss.util.stream.Streams; /** * An abstract {@link SubDeployer}. @@ -17,13 +35,54 @@ * <p>Provides registration with {@link MainDeployer} as well as empty * implementations of init, create, start, stop and destroy. * - * @version <tt>$Revision: 1.1 $</tt> + * @version <tt>$Revision: 1.2 $</tt> * @author <a href="mailto:[EMAIL PROTECTED]">Jason Dillon</a> */ public abstract class SubDeployerSupport extends ServiceMBeanSupport implements SubDeployer, SubDeployerMBean { + + /** + * Holds the native library <em>suffix</em> for this system. + * Determined by examining the result of System.mapLibraryName("XxX"). + */ + protected static final String nativeSuffix; + + /** + * Holds the native library <em>prefix</em> for this system. + * Determined by examining the result of System.mapLibraryName("XxX"). + */ + protected static final String nativePrefix; + + /** The temporary directory where native libs are unpacked. */ + private File tempNativeDir; + + static + { + String nativex = System.mapLibraryName("XxX"); + int xPos = nativex.indexOf("XxX"); //hope "XxX' is not part of any native lib goo! + nativePrefix = nativex.substring(0, xPos); + nativeSuffix = nativex.substring(xPos + 3); + } + + /** + * The <code>createService</code> method is one of the ServiceMBean lifecyle operations. + * (no jmx tag needed from superinterface) + * @exception Exception if an error occurs + */ + protected void createService() throws Exception + { + // watch the deploy directory, it is a set so multiple adds + // (start/stop) only one entry is present + // get the temporary directory to use + + ServerConfig config = ServerConfigLocator.locate(); + File basedir = config.getServerTempDir(); + + tempNativeDir = new File(basedir, "native"); + } + /** * Performs SubDeployer registration. */ @@ -52,11 +111,15 @@ * Sub-classes should override this method to provide * custom 'init' logic. * - * <p>This method is empty, and is provided for convenience - * when concrete service classes do not need to perform - * anything specific for this state change. + * <p>This method calls the processNestedDeployments(di) method. This behaviour + * can overridden by concrete sub-classes. If further initialization + * needs to be done, and you wish to preserve the functionality, be sure + * to call super.init(di) at the end of your implementation. */ - public void init(DeploymentInfo di) throws DeploymentException {} + public void init(DeploymentInfo di) throws DeploymentException + { + processNestedDeployments(di); + } /** * Sub-classes should override this method to provide @@ -97,4 +160,176 @@ * anything specific for this state change. */ public void destroy(DeploymentInfo di) throws DeploymentException {} + + /** + * The <code>processNestedDeployments</code> method searches for any nested and + * deployable elements. Only Directories and Zipped archives are processed, + * and those are delegated to the addDeployableFiles and addDeployableJar + * methods respectively. This method can be overridden for alternate + * behaviour. + */ + protected void processNestedDeployments(DeploymentInfo di) throws DeploymentException + { + if (di.isXML) { + // no nested archives in an xml file + return; + } + if (di.isDirectory) + { + File f = new File(di.url.getFile()); + if (!f.isDirectory()) + { + // something is screwy + throw new DeploymentException("Deploy file incorrectly reported " + + "as a directory: " + di.url); + } + addDeployableFiles(di, f); + } + else + { + // Do we have a jar file jar:<theURL>!/.. + String jarURLString = "njar:"+di.localUrl.toString()+"^/"; + try + { + URL jarURL = new URL(jarURLString); + URLConnection con = jarURL.openConnection(); + JarURLConnection jarConn = (JarURLConnection)con; + JarFile jarFile = jarConn.getJarFile(); + addDeployableJar(di, jarFile); + } + catch (Exception e) + { + log.warn("operation failed; ignoring", e); + //maybe this is not a jar nor a directory... + log.info("deploying non-jar/xml file: " + di.url); + return; + } + } + } + + /** + * This method returns true if the name is a recognized archive file. + * This can be overridden for alternate behaviour. + * + * @param name The "short-name" of the URL. It will have any trailing '/' + * characters removed, and any directory structure has been removed. + * @param url The full url. + * + * @return true iff the name ends in a known archive extension: jar, sar, + * ear, rar, zip, wsr, war, or if the name matches the native + * library conventions. + */ + protected boolean isDeployable(String name, URL url) + { + return name.endsWith(".jar") + || name.endsWith(".sar") + || name.endsWith(".ear") + || name.endsWith(".rar") + || name.endsWith(".zip") + || name.endsWith(".wsr") + || name.endsWith(".war") + || (name.endsWith(nativeSuffix) && name.startsWith(nativePrefix)); + } + + /** + * This method recursively searches the directory structure for any files + * that are deployable (@see isDeployable). If a directory is found to + * be deployable, then its subfiles and subdirectories are not searched. + * + * @param di the DeploymentInfo + * @param dir The root directory to start searching. + */ + protected void addDeployableFiles(DeploymentInfo di, File dir) + throws DeploymentException + { + File[] files = dir.listFiles(); + for (int i = 0; i < files.length; i++) + { + File file = files[i]; + String name = file.getName(); + try + { + URL url = file.toURL(); + if (isDeployable(name, url)) + { + deployUrl(di, url, name); + // we don't want deployable units processed any further + continue; + } + } + catch (MalformedURLException e) + { + log.warn("File name invalid. Ignoring: " + file, e); + } + if (file.isDirectory()) + { + addDeployableFiles(di, file); + } + } + } + + /** + * This method searches the entire jar file for any deployable files + * (@see isDeployable). + * + * @param di the DeploymentInfo + * @param jarFile the jar file to process. + */ + protected void addDeployableJar(DeploymentInfo di, JarFile jarFile) + throws DeploymentException + { + for (Enumeration e = jarFile.entries(); e.hasMoreElements();) + { + JarEntry entry = (JarEntry)e.nextElement(); + String name = entry.getName(); + try + { + URL url = new URL("njar:"+di.localUrl.toString()+"^/"+name); + if (isDeployable(name, url)) { + deployUrl(di, url, name); + } + } + catch (MalformedURLException mue) + { + log.warn("Jar entry invalid. Ignoring: " + name, mue); + } + } + } + + protected void deployUrl(DeploymentInfo di, URL url, String name) + throws DeploymentException + { + try + { + if (name.endsWith(nativeSuffix) && name.startsWith(nativePrefix)) + { + File destFile = new File(tempNativeDir, name); + log.info("Loading native library: " + destFile.toString()); + + File parent = destFile.getParentFile(); + if (!parent.exists()) { + parent.mkdirs(); + } + + InputStream in = new BufferedInputStream(url.openStream()); + OutputStream out = new BufferedOutputStream(new FileOutputStream(destFile)); + Streams.copy(in, out); + out.flush(); + out.close(); + in.close(); + + System.load(destFile.toString()); + } + else + { + DeploymentInfo sub = new DeploymentInfo(url, di); + } + } + catch (Exception ex) + { + log.error("Error in subDeployment with name "+name, ex); + throw new DeploymentException + ("Could not deploy sub deployment "+name+" of deployment "+di.url, ex); + } + } }
_______________________________________________ Jboss-development mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jboss-development