diff --git a/core/pom.xml b/core/pom.xml index 4cb16854f92640cb1314877bd27d2084df628617..f67057e4e7f622b89ec7cca4c9706ccbf28a4237 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -39,7 +39,7 @@ THE SOFTWARE. true - 1.252 + 1.253-SNAPSHOT 2.5.6.SEC03 2.4.11 @@ -472,9 +472,9 @@ THE SOFTWARE. test - javax.servlet - jstl - 1.1.0 + javax.servlet.jsp.jstl + javax.servlet.jsp.jstl-api + 1.2.1 org.slf4j diff --git a/core/src/main/java/jenkins/slaves/EncryptedSlaveAgentJnlpFile.java b/core/src/main/java/jenkins/slaves/EncryptedSlaveAgentJnlpFile.java index 9d152a68f0fb886d99150a386d5965a90901d70c..6da693205414386139e614939bf17aab0e4e99f5 100644 --- a/core/src/main/java/jenkins/slaves/EncryptedSlaveAgentJnlpFile.java +++ b/core/src/main/java/jenkins/slaves/EncryptedSlaveAgentJnlpFile.java @@ -4,12 +4,12 @@ import hudson.security.AccessControlled; import hudson.security.Permission; import hudson.slaves.SlaveComputer; import hudson.util.Secret; + import hudson.Util; import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.ResponseImpl; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; -import org.kohsuke.stapler.compression.FilterServletOutputStream; import javax.crypto.Cipher; import javax.crypto.SecretKey; @@ -18,12 +18,15 @@ import javax.crypto.spec.SecretKeySpec; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; import javax.servlet.http.HttpServletResponseWrapper; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.security.GeneralSecurityException; import java.security.SecureRandom; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Serves the JNLP file. @@ -35,6 +38,9 @@ import java.security.SecureRandom; * @since 1.560 */ public class EncryptedSlaveAgentJnlpFile implements HttpResponse { + + private static final Logger LOG = Logger.getLogger(EncryptedSlaveAgentJnlpFile.class.getName()); + /** * The object that owns the Jelly view that renders JNLP file. * This is typically a {@link SlaveComputer} and if so we'll use {@link SlaveComputer#getJnlpMac()} @@ -64,13 +70,13 @@ public class EncryptedSlaveAgentJnlpFile implements HttpResponse { } @Override - public void generateResponse(StaplerRequest req, StaplerResponse res, Object node) throws IOException, ServletException { + public void generateResponse(StaplerRequest req, final StaplerResponse res, Object node) throws IOException, ServletException { RequestDispatcher view = req.getView(it, viewName); if ("true".equals(req.getParameter("encrypt"))) { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final CapturingServletOutputStream csos = new CapturingServletOutputStream(); StaplerResponse temp = new ResponseImpl(req.getStapler(), new HttpServletResponseWrapper(res) { @Override public ServletOutputStream getOutputStream() throws IOException { - return new FilterServletOutputStream(baos); + return csos; } @Override public PrintWriter getWriter() throws IOException { throw new IllegalStateException(); @@ -92,7 +98,7 @@ public class EncryptedSlaveAgentJnlpFile implements HttpResponse { try { Cipher c = Secret.getCipher("AES/CFB8/NoPadding"); c.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); - encrypted = c.doFinal(baos.toByteArray()); + encrypted = c.doFinal(csos.getBytes()); } catch (GeneralSecurityException x) { throw new IOException(x); } @@ -104,4 +110,52 @@ public class EncryptedSlaveAgentJnlpFile implements HttpResponse { view.forward(req, res); } } + + + /** + * A {@link ServletOutputStream} that captures all the data rather than writing to a client. + */ + private static class CapturingServletOutputStream extends ServletOutputStream { + + private ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setWriteListener(WriteListener writeListener) { + // we are always ready to write so we just call once to say we are ready. + try { + // should we do this on a separate thread to avoid deadlocaks? + writeListener.onWritePossible(); + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to notify WriteListener.onWritePossible", e); + } + } + + @Override + public void write(int b) throws IOException { + baos.write(b); + } + + @Override + public void write(byte[] b) throws IOException { + baos.write(b); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + baos.write(b, off, len); + } + + /** + * Get the data that has been written to this ServletOutputStream. + * @return the data that has been written to this ServletOutputStream. + */ + byte[] getBytes() { + return baos.toByteArray(); + } + } } diff --git a/pom.xml b/pom.xml index c3a70bb1740e9e8e959aed4db4390d384cf41c49..78e12f42ad1ce12f95585f89fd46872c2840d23a 100644 --- a/pom.xml +++ b/pom.xml @@ -230,6 +230,19 @@ THE SOFTWARE. access-modifier-annotation ${access-modifier-annotation.version} + + + + + + javax.servlet + + servlet-api + [0-SNAPSHOT] + provided + true + + @@ -246,6 +259,12 @@ THE SOFTWARE. test-annotations test + + + javax.servlet + + servlet-api + @@ -324,8 +343,8 @@ THE SOFTWARE. javax.servlet - servlet-api - 2.4 + javax.servlet-api + 3.1.0 org.codehaus.gmaven.runtime diff --git a/war/pom.xml b/war/pom.xml index dace1a2fc1e2595391bd3cd473285858dfa28dea..f89dd396701dcec768448ef33c1c5061f68593b0 100644 --- a/war/pom.xml +++ b/war/pom.xml @@ -61,12 +61,8 @@ THE SOFTWARE. jars that are not needed in war. most of the exclusions should happen in the core, to make IDEs happy, not here. --> - javax.servlet - servlet-api - - - javax.servlet - jsp-api + javax.servlet.jsp + javax.servlet.jsp-api