1)Start tomcat 2)Go to Manager. 3)deploy a war file. 4)undeploy it. 5)try to deploy it again and you get message "FAIL - War file "proxy.war" already exists on server". It used to work fine in tomcat 5.0.19. It not fixed in the version 5.0.26-beta.
This works for me. Please don't reopen the report.
Hmm, actually, I tested again, and it now doesn't work anymore. I did countless changes already to fix this issue, and now I'm really really sick of it and tired of mickey mouse OS. As a result, I'm not going to fix this issue. I recommend either using Linux, investigating this issue more (and submit a patch), or convince another developer to look into it.
Remy, I am also encountering this bug with my application. When undeploying it leaves a single jar that cannot be deleted. I've tracked it down to a single class within this jar that is causing the problem. Here is the code, can you think of any reason this class may be causing a problem?: package com.company; // ---------------------------------------------------------------------------- - // StringEncrypter.java // ---------------------------------------------------------------------------- - // CIPHER / GENERATORS import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.KeyGenerator; // KEY SPECIFICATIONS import java.security.spec.KeySpec; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEParameterSpec; // EXCEPTIONS import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.InvalidKeyException; import java.security.spec.InvalidKeySpecException; import javax.crypto.NoSuchPaddingException; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import java.io.UnsupportedEncodingException; import java.io.IOException; /** * ---------------------------------------------------------------------------- - * The following example implements a class for encrypting and decrypting * strings using several Cipher algorithms. The class is created with a key and * can be used repeatedly to encrypt and decrypt strings using that key. * Some of the more popular algorithms are: * Blowfish * DES * DESede * PBEWithMD5AndDES * PBEWithMD5AndTripleDES * TripleDES * ---------------------------------------------------------------------------- - */ public class Encrypter { Cipher ecipher; Cipher dcipher; /** * Constructor used to create this object. Responsible for setting * and initializing this object's encrypter and decrypter Chipher instances * given a Secret Key and algorithm. * @param key Secret Key used to initialize both the encrypter and * decrypter instances. * @param algorithm Which algorithm to use for creating the encrypter and * decrypter instances. */ Encrypter(SecretKey key, String algorithm) { try { ecipher = Cipher.getInstance(algorithm); dcipher = Cipher.getInstance(algorithm); ecipher.init(Cipher.ENCRYPT_MODE, key); dcipher.init(Cipher.DECRYPT_MODE, key); } catch (Exception e) { } } /** * Constructor used to create this object. Responsible for setting * and initializing this object's encrypter and decrypter Chipher instances * given a Pass Phrase and algorithm. * @param passPhrase Pass Phrase used to initialize both the encrypter and * decrypter instances. */ Encrypter(String passPhrase) { // 8-bytes Salt byte[] salt = { (byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32, (byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03 }; // Iteration count int iterationCount = 20; try { KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); SecretKey key = SecretKeyFactory.getInstance ("PBEWithMD5AndDES").generateSecret(keySpec); ecipher = Cipher.getInstance(key.getAlgorithm()); dcipher = Cipher.getInstance(key.getAlgorithm()); // Prepare the parameters to the cipthers AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount); ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec); } catch (Exception e) { } } /** * Takes a single String as an argument and returns an Encrypted version * of that String. * @param str String to be encrypted * @return <code>String</code> Encrypted version of the provided String */ public String encrypt(String str) { try { // Encode the string into bytes using utf-8 byte[] utf8 = str.getBytes("UTF8"); // Encrypt byte[] enc = ecipher.doFinal(utf8); // Encode bytes to base64 to get a string return new sun.misc.BASE64Encoder().encode(enc); } catch (Exception e) { } } public static Encrypter getEncrypter() { return new Encrypter("Any old phrase"); } /** * Takes a encrypted String as an argument, decrypts and returns the * decrypted String. * @param str Encrypted String to be decrypted * @return <code>String</code> Decrypted version of the provided String */ public String decrypt(String str) { try { // Decode base64 to get bytes byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str); // Decrypt byte[] utf8 = dcipher.doFinal(dec); // Decode using utf-8 return new String(utf8, "UTF8"); } catch (Exception e) { } }
This problem won't be resolved in 5.0.x. I'll redo the deployer in the next release so that JARs are locked sometimes (as usual), but we don't care about it (similar to JBoss). Until then, I don't recommend using Windows if you want hot deployment to work reliably (at least not until M$ adds some option to allow certain processes to avoid the file locking "feature" - I understand this is a "useful" feature for the average desktop user, but for server side ...).
> tired of mickey mouse OS The same happened to me on AIX 5 with /webapps on a NFS mounted drive, with NFS lock files hanging around instead of the jars itself, thereby blocking removal of the directory. The really annoying part is that the Ant task claims success: wardeploymanager: [deploy] OK - Anwendung mit Kontext Pfad /bre entfernt [deploy] OK - Anwendung mit Kontext Pfad /bre entfernt [deploy] OK - Anwendung mit Kontext Pfad /bre installiert Isn't there a way to reliably detect that the webapp removal failed (for whatever reason)?
Not using Windows isn't always an option... The changes for 28272 uses the jar URL to see if the context.xml file exists inside the .war. The jar URL connection class caches by default, and leaves a file descriptor open to the jar file. By disabling caching, it doesn't and the jar file can be deleted. --- ManagerServlet.java.orig Thu Jun 17 21:02:56 2004 +++ ManagerServlet.java Sat Jul 24 20:40:52 2004 @@ -27,6 +27,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.net.URL; +import java.net.URLConnection; import java.net.MalformedURLException; import java.util.Iterator; import java.util.jar.JarEntry; @@ -845,7 +846,9 @@ } contextXml = new URL(contextWar + "META-INF/context.xml"); - stream = contextXml.openStream(); + URLConnection jarUrlConnection=contextXml.openConnection(); + jarUrlConnection.setUseCaches(false); + stream = jarUrlConnection.getInputStream();; // WAR contains META-INF/context.xml resource - install deployer.install(new URL(contextWar)); return;
This does not work for me on my linux machine using Tomcat 5.0.19.
I've applied the patch for Tomcat 5.0(.29) -- thanks for submitting it. For Tomcat 5.5, this is not applicable as significant changes have been made to relevant code (both the Manager and the Context). When 5.5.0 is available, test out the "antiJARLocking" attribute and if a bug still exists, file an issue against 5.5.0. Thanks.