File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\model\FullDuplexHttpChannel.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 package hudson.model;
25
26 import hudson.remoting.Channel;
27 import hudson.remoting.PingThread;
28 import hudson.remoting.Channel.Mode;
29 import hudson.util.ChunkedOutputStream;
30 import hudson.util.ChunkedInputStream;
31 import org.kohsuke.stapler.StaplerRequest;
32 import org.kohsuke.stapler.StaplerResponse;
33
34 import javax.servlet.http.HttpServletResponse;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.OutputStream;
38 import java.util.UUID;
39 import java.util.logging.Level;
40 import java.util.logging.Logger;
41
42 /**
43 * Builds a {@link Channel} on top of two HTTP streams (one used for each direction.)
44 *
45 * @author Kohsuke Kawaguchi
46 */
47 abstract public class FullDuplexHttpChannel {
48 private Channel channel;
49
50 private InputStream upload;
51
52 private final UUID uuid;
53 private final boolean restricted;
54
55 private boolean completed;
56
57 public FullDuplexHttpChannel(UUID uuid, boolean restricted) throws IOException {
58 this.uuid = uuid;
59 this.restricted = restricted;
60 }
61
62 /**
63 * This is where we send the data to the client.
64 *
65 * <p>
66 * If this connection is lost, we'll abort the channel.
67 */
68 public synchronized void download(StaplerRequest req, StaplerResponse rsp) throws InterruptedException, IOException {
69 rsp.setStatus(HttpServletResponse.SC_OK);
70
71 // server->client channel.
72 // this is created first, and this controls the lifespan of the channel
73 rsp.addHeader("Transfer-Encoding", "chunked");
74 OutputStream out = rsp.getOutputStream();
75 if (DIY_CHUNKING) out = new ChunkedOutputStream(out);
76
77 // send something out so that the client will see the HTTP headers
78 out.write("Starting HTTP duplex channel".getBytes());
79 out.flush();
80
81 // wait until we have the other channel
82 while(upload==null)
83 wait();
84
85 try {
86 channel = new Channel("HTTP full-duplex channel " + uuid,
87 Computer.threadPoolForRemoting, Mode.BINARY, upload, out, null, restricted);
88
89 // so that we can detect dead clients, periodically send something
90 PingThread ping = new PingThread(channel) {
91 @Override
92 protected void onDead(Throwable diagnosis) {
93 LOGGER.log(Level.INFO,"Duplex-HTTP session " + uuid + " is terminated",diagnosis);
94 // this will cause the channel to abort and subsequently clean up
95 try {
96 upload.close();
97 } catch (IOException e) {
98 // this can never happen
99 throw new AssertionError(e);
100 }
101 }
102
103 @Override
104 protected void onDead() {
105 onDead(null);
106 }
107 };
108 ping.start();
109 main(channel);
110 channel.join();
111 ping.interrupt();
112 } finally {
113 // publish that we are done
114 completed=true;
115 notify();
116 }
117 }
118
119 protected abstract void main(Channel channel) throws IOException, InterruptedException;
120
121 /**
122 * This is where we receive inputs from the client.
123 */
124 public synchronized void upload(StaplerRequest req, StaplerResponse rsp) throws InterruptedException, IOException {
125 rsp.setStatus(HttpServletResponse.SC_OK);
126 InputStream in = req.getInputStream();
127 if(DIY_CHUNKING) in = new ChunkedInputStream(in);
128
129 // publish the upload channel
130 upload = in;
131 notify();
132
133 // wait until we are done
134 while (!completed)
135 wait();
136 }
137
138 public Channel getChannel() {
139 return channel;
140 }
141
142 private static final Logger LOGGER = Logger.getLogger(FullDuplexHttpChannel.class.getName());
143
144 /**
145 * Set to true if the servlet container doesn't support chunked encoding.
146 */
147 public static boolean DIY_CHUNKING = Boolean.getBoolean("hudson.diyChunking");
148 }
149