History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/net/httpserver (27 of 18352 files). Show all

Unified · Split

27 files
  1. java/pkg/sun/net/httpserver/AuthFilter.java +86 −0
  2. java/pkg/sun/net/httpserver/ChunkedInputStream.java +176 −0
  3. java/pkg/sun/net/httpserver/ChunkedOutputStream.java +163 −0
  4. java/pkg/sun/net/httpserver/Code.java +109 −0
  5. java/pkg/sun/net/httpserver/ContextList.java +97 −0
  6. java/pkg/sun/net/httpserver/DefaultHttpServerProvider.java +41 −0
  7. java/pkg/sun/net/httpserver/Event.java +46 −0
  8. java/pkg/sun/net/httpserver/ExchangeImpl.java +456 −0
  9. java/pkg/sun/net/httpserver/FixedLengthInputStream.java +82 −0
  10. java/pkg/sun/net/httpserver/FixedLengthOutputStream.java +104 −0
  11. java/pkg/sun/net/httpserver/HttpConnection.java +196 −0
  12. java/pkg/sun/net/httpserver/HttpContextImpl.java +152 −0
  13. java/pkg/sun/net/httpserver/HttpError.java +37 −0
  14. java/pkg/sun/net/httpserver/HttpExchangeImpl.java +120 −0
  15. java/pkg/sun/net/httpserver/HttpServerImpl.java +92 −0
  16. java/pkg/sun/net/httpserver/HttpsExchangeImpl.java +124 −0
  17. java/pkg/sun/net/httpserver/HttpsServerImpl.java +100 −0
  18. java/pkg/sun/net/httpserver/LeftOverInputStream.java +122 −0
  19. java/pkg/sun/net/httpserver/Request.java +402 −0
  20. java/pkg/sun/net/httpserver/SSLStreams.java +662 −0
  21. java/pkg/sun/net/httpserver/ServerConfig.java +175 −0
  22. java/pkg/sun/net/httpserver/ServerImpl.java +870 −0
  23. java/pkg/sun/net/httpserver/StreamClosedException.java +32 −0
  24. java/pkg/sun/net/httpserver/TimeSource.java +30 −0
  25. java/pkg/sun/net/httpserver/UndefLengthOutputStream.java +81 −0
  26. java/pkg/sun/net/httpserver/UnmodifiableHeaders.java +101 −0
  27. java/pkg/sun/net/httpserver/mkfile +33 −0
java/pkg/sun/net/httpserver/AuthFilter.java+86−0
@@ -0,0 +1,86 @@
1/*
2 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import com.sun.net.httpserver.*;
29import java.io.*;
30import java.nio.*;
31import java.nio.channels.*;
32import sun.net.www.MessageHeader;
33import java.util.*;
34import javax.security.auth.*;
35import javax.security.auth.callback.*;
36import javax.security.auth.login.*;
37
38public class AuthFilter extends Filter {
39
40 private Authenticator authenticator;
41
42 public AuthFilter (Authenticator authenticator) {
43 this.authenticator = authenticator;
44 }
45
46 public String description () {
47 return "Authentication filter";
48 }
49
50 public void setAuthenticator (Authenticator a) {
51 authenticator = a;
52 }
53
54 public void consumeInput (HttpExchange t) throws IOException {
55 InputStream i = t.getRequestBody();
56 byte[] b = new byte [4096];
57 while (i.read (b) != -1);
58 i.close ();
59 }
60
61 /**
62 * The filter's implementation, which is invoked by the server
63 */
64 public void doFilter (HttpExchange t, Filter.Chain chain) throws IOException
65 {
66 if (authenticator != null) {
67 Authenticator.Result r = authenticator.authenticate (t);
68 if (r instanceof Authenticator.Success) {
69 Authenticator.Success s = (Authenticator.Success)r;
70 ExchangeImpl e = ExchangeImpl.get (t);
71 e.setPrincipal (s.getPrincipal());
72 chain.doFilter (t);
73 } else if (r instanceof Authenticator.Retry) {
74 Authenticator.Retry ry = (Authenticator.Retry)r;
75 consumeInput (t);
76 t.sendResponseHeaders (ry.getResponseCode(), -1);
77 } else if (r instanceof Authenticator.Failure) {
78 Authenticator.Failure f = (Authenticator.Failure)r;
79 consumeInput (t);
80 t.sendResponseHeaders (f.getResponseCode(), -1);
81 }
82 } else {
83 chain.doFilter (t);
84 }
85 }
86}
java/pkg/sun/net/httpserver/ChunkedInputStream.java+176−0
@@ -0,0 +1,176 @@
1/*
2 * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import java.net.*;
30import com.sun.net.httpserver.*;
31import com.sun.net.httpserver.spi.*;
32
33class ChunkedInputStream extends LeftOverInputStream {
34 ChunkedInputStream (ExchangeImpl t, InputStream src) {
35 super (t, src);
36 }
37
38 private int remaining;
39
40 /* true when a chunk header needs to be read */
41
42 private boolean needToReadHeader = true;
43
44 static char CR = '\r';
45 static char LF = '\n';
46
47 private int numeric (char[] arr, int nchars) throws IOException {
48 assert arr.length >= nchars;
49 int len = 0;
50 for (int i=0; i<nchars; i++) {
51 char c = arr[i];
52 int val=0;
53 if (c>='0' && c <='9') {
54 val = c - '0';
55 } else if (c>='a' && c<= 'f') {
56 val = c - 'a' + 10;
57 } else if (c>='A' && c<= 'F') {
58 val = c - 'A' + 10;
59 } else {
60 throw new IOException ("invalid chunk length");
61 }
62 len = len * 16 + val;
63 }
64 return len;
65 }
66
67 /* read the chunk header line and return the chunk length
68 * any chunk extensions are ignored
69 */
70 private int readChunkHeader () throws IOException {
71 boolean gotCR = false;
72 int c;
73 char[] len_arr = new char [16];
74 int len_size = 0;
75 boolean end_of_len = false;
76
77 while ((c=in.read())!= -1) {
78 char ch = (char) c;
79 if (len_size == len_arr.length -1) {
80 throw new IOException ("invalid chunk header");
81 }
82 if (gotCR) {
83 if (ch == LF) {
84 int l = numeric (len_arr, len_size);
85 return l;
86 } else {
87 gotCR = false;
88 }
89 if (!end_of_len) {
90 len_arr[len_size++] = ch;
91 }
92 } else {
93 if (ch == CR) {
94 gotCR = true;
95 } else if (ch == ';') {
96 end_of_len = true;
97 } else if (!end_of_len) {
98 len_arr[len_size++] = ch;
99 }
100 }
101 }
102 throw new IOException ("end of stream reading chunk header");
103 }
104
105 protected int readImpl (byte[]b, int off, int len) throws IOException {
106 if (eof) {
107 return -1;
108 }
109 if (needToReadHeader) {
110 remaining = readChunkHeader();
111 if (remaining == 0) {
112 eof = true;
113 consumeCRLF();
114 t.getServerImpl().requestCompleted (t.getConnection());
115 return -1;
116 }
117 needToReadHeader = false;
118 }
119 if (len > remaining) {
120 len = remaining;
121 }
122 int n = in.read(b, off, len);
123 if (n > -1) {
124 remaining -= n;
125 }
126 if (remaining == 0) {
127 needToReadHeader = true;
128 consumeCRLF();
129 }
130 return n;
131 }
132
133 private void consumeCRLF () throws IOException {
134 char c;
135 c = (char)in.read(); /* CR */
136 if (c != CR) {
137 throw new IOException ("invalid chunk end");
138 }
139 c = (char)in.read(); /* LF */
140 if (c != LF) {
141 throw new IOException ("invalid chunk end");
142 }
143 }
144
145 /**
146 * returns the number of bytes available to read in the current chunk
147 * which may be less than the real amount, but we'll live with that
148 * limitation for the moment. It only affects potential efficiency
149 * rather than correctness.
150 */
151 public int available () throws IOException {
152 if (eof || closed) {
153 return 0;
154 }
155 int n = in.available();
156 return n > remaining? remaining: n;
157 }
158
159 /* called after the stream is closed to see if bytes
160 * have been read from the underlying channel
161 * and buffered internally
162 */
163 public boolean isDataBuffered () throws IOException {
164 assert eof;
165 return in.available() > 0;
166 }
167
168 public boolean markSupported () {return false;}
169
170 public void mark (int l) {
171 }
172
173 public void reset () throws IOException {
174 throw new IOException ("mark/reset not supported");
175 }
176}
java/pkg/sun/net/httpserver/ChunkedOutputStream.java+163−0
@@ -0,0 +1,163 @@
1/*
2 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import java.net.*;
30import com.sun.net.httpserver.*;
31import com.sun.net.httpserver.spi.*;
32
33/**
34 * a class which allows the caller to write an arbitrary
35 * number of bytes to an underlying stream.
36 * normal close() does not close the underlying stream
37 *
38 * This class is buffered.
39 *
40 * Each chunk is written in one go as :-
41 * abcd\r\nxxxxxxxxxxxxxx\r\n
42 *
43 * abcd is the chunk-size, and xxx is the chunk data
44 * If the length is less than 4 chars (in size) then the buffer
45 * is written with an offset.
46 * Final chunk is:
47 * 0\r\n\r\n
48 */
49
50class ChunkedOutputStream extends FilterOutputStream
51{
52 private boolean closed = false;
53 /* max. amount of user data per chunk */
54 final static int CHUNK_SIZE = 4096;
55 /* allow 4 bytes for chunk-size plus 4 for CRLFs */
56 final static int OFFSET = 6; /* initial <=4 bytes for len + CRLF */
57 private int pos = OFFSET;
58 private int count = 0;
59 private byte[] buf = new byte [CHUNK_SIZE+OFFSET+2];
60 ExchangeImpl t;
61
62 ChunkedOutputStream (ExchangeImpl t, OutputStream src) {
63 super (src);
64 this.t = t;
65 }
66
67 public void write (int b) throws IOException {
68 if (closed) {
69 throw new StreamClosedException ();
70 }
71 buf [pos++] = (byte)b;
72 count ++;
73 if (count == CHUNK_SIZE) {
74 writeChunk();
75 }
76 assert count < CHUNK_SIZE;
77 }
78
79 public void write (byte[]b, int off, int len) throws IOException {
80 if (closed) {
81 throw new StreamClosedException ();
82 }
83 int remain = CHUNK_SIZE - count;
84 if (len > remain) {
85 System.arraycopy (b,off,buf,pos,remain);
86 count = CHUNK_SIZE;
87 writeChunk();
88 len -= remain;
89 off += remain;
90 while (len >= CHUNK_SIZE) {
91 System.arraycopy (b,off,buf,OFFSET,CHUNK_SIZE);
92 len -= CHUNK_SIZE;
93 off += CHUNK_SIZE;
94 count = CHUNK_SIZE;
95 writeChunk();
96 }
97 }
98 if (len > 0) {
99 System.arraycopy (b,off,buf,pos,len);
100 count += len;
101 pos += len;
102 }
103 if (count == CHUNK_SIZE) {
104 writeChunk();
105 }
106 }
107
108 /**
109 * write out a chunk , and reset the pointers
110 * chunk does not have to be CHUNK_SIZE bytes
111 * count must == number of user bytes (<= CHUNK_SIZE)
112 */
113 private void writeChunk () throws IOException {
114 char[] c = Integer.toHexString (count).toCharArray();
115 int clen = c.length;
116 int startByte = 4 - clen;
117 int i;
118 for (i=0; i<clen; i++) {
119 buf[startByte+i] = (byte)c[i];
120 }
121 buf[startByte + (i++)] = '\r';
122 buf[startByte + (i++)] = '\n';
123 buf[startByte + (i++) + count] = '\r';
124 buf[startByte + (i++) + count] = '\n';
125 out.write (buf, startByte, i+count);
126 count = 0;
127 pos = OFFSET;
128 }
129
130 public void close () throws IOException {
131 if (closed) {
132 return;
133 }
134 flush();
135 try {
136 /* write an empty chunk */
137 writeChunk();
138 out.flush();
139 LeftOverInputStream is = t.getOriginalInputStream();
140 if (!is.isClosed()) {
141 is.close();
142 }
143 /* some clients close the connection before empty chunk is sent */
144 } catch (IOException e) {
145
146 } finally {
147 closed = true;
148 }
149
150 WriteFinishedEvent e = new WriteFinishedEvent (t);
151 t.getHttpContext().getServerImpl().addEvent (e);
152 }
153
154 public void flush () throws IOException {
155 if (closed) {
156 throw new StreamClosedException ();
157 }
158 if (count > 0) {
159 writeChunk();
160 }
161 out.flush();
162 }
163}
java/pkg/sun/net/httpserver/Code.java+109−0
@@ -0,0 +1,109 @@
1/*
2 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28class Code {
29
30 public static final int HTTP_CONTINUE = 100;
31 public static final int HTTP_OK = 200;
32 public static final int HTTP_CREATED = 201;
33 public static final int HTTP_ACCEPTED = 202;
34 public static final int HTTP_NOT_AUTHORITATIVE = 203;
35 public static final int HTTP_NO_CONTENT = 204;
36 public static final int HTTP_RESET = 205;
37 public static final int HTTP_PARTIAL = 206;
38 public static final int HTTP_MULT_CHOICE = 300;
39 public static final int HTTP_MOVED_PERM = 301;
40 public static final int HTTP_MOVED_TEMP = 302;
41 public static final int HTTP_SEE_OTHER = 303;
42 public static final int HTTP_NOT_MODIFIED = 304;
43 public static final int HTTP_USE_PROXY = 305;
44 public static final int HTTP_BAD_REQUEST = 400;
45 public static final int HTTP_UNAUTHORIZED = 401;
46 public static final int HTTP_PAYMENT_REQUIRED = 402;
47 public static final int HTTP_FORBIDDEN = 403;
48 public static final int HTTP_NOT_FOUND = 404;
49 public static final int HTTP_BAD_METHOD = 405;
50 public static final int HTTP_NOT_ACCEPTABLE = 406;
51 public static final int HTTP_PROXY_AUTH = 407;
52 public static final int HTTP_CLIENT_TIMEOUT = 408;
53 public static final int HTTP_CONFLICT = 409;
54 public static final int HTTP_GONE = 410;
55 public static final int HTTP_LENGTH_REQUIRED = 411;
56 public static final int HTTP_PRECON_FAILED = 412;
57 public static final int HTTP_ENTITY_TOO_LARGE = 413;
58 public static final int HTTP_REQ_TOO_LONG = 414;
59 public static final int HTTP_UNSUPPORTED_TYPE = 415;
60 public static final int HTTP_INTERNAL_ERROR = 500;
61 public static final int HTTP_NOT_IMPLEMENTED = 501;
62 public static final int HTTP_BAD_GATEWAY = 502;
63 public static final int HTTP_UNAVAILABLE = 503;
64 public static final int HTTP_GATEWAY_TIMEOUT = 504;
65 public static final int HTTP_VERSION = 505;
66
67 static String msg (int code) {
68
69 switch (code) {
70 case HTTP_OK: return " OK";
71 case HTTP_CONTINUE: return " Continue";
72 case HTTP_CREATED: return " Created";
73 case HTTP_ACCEPTED: return " Accepted";
74 case HTTP_NOT_AUTHORITATIVE: return " Non-Authoritative Information";
75 case HTTP_NO_CONTENT: return " No Content";
76 case HTTP_RESET: return " Reset Content";
77 case HTTP_PARTIAL: return " Partial Content";
78 case HTTP_MULT_CHOICE: return " Multiple Choices";
79 case HTTP_MOVED_PERM: return " Moved Permanently";
80 case HTTP_MOVED_TEMP: return " Temporary Redirect";
81 case HTTP_SEE_OTHER: return " See Other";
82 case HTTP_NOT_MODIFIED: return " Not Modified";
83 case HTTP_USE_PROXY: return " Use Proxy";
84 case HTTP_BAD_REQUEST: return " Bad Request";
85 case HTTP_UNAUTHORIZED: return " Unauthorized" ;
86 case HTTP_PAYMENT_REQUIRED: return " Payment Required";
87 case HTTP_FORBIDDEN: return " Forbidden";
88 case HTTP_NOT_FOUND: return " Not Found";
89 case HTTP_BAD_METHOD: return " Method Not Allowed";
90 case HTTP_NOT_ACCEPTABLE: return " Not Acceptable";
91 case HTTP_PROXY_AUTH: return " Proxy Authentication Required";
92 case HTTP_CLIENT_TIMEOUT: return " Request Time-Out";
93 case HTTP_CONFLICT: return " Conflict";
94 case HTTP_GONE: return " Gone";
95 case HTTP_LENGTH_REQUIRED: return " Length Required";
96 case HTTP_PRECON_FAILED: return " Precondition Failed";
97 case HTTP_ENTITY_TOO_LARGE: return " Request Entity Too Large";
98 case HTTP_REQ_TOO_LONG: return " Request-URI Too Large";
99 case HTTP_UNSUPPORTED_TYPE: return " Unsupported Media Type";
100 case HTTP_INTERNAL_ERROR: return " Internal Server Error";
101 case HTTP_NOT_IMPLEMENTED: return " Not Implemented";
102 case HTTP_BAD_GATEWAY: return " Bad Gateway";
103 case HTTP_UNAVAILABLE: return " Service Unavailable";
104 case HTTP_GATEWAY_TIMEOUT: return " Gateway Timeout";
105 case HTTP_VERSION: return " HTTP Version Not Supported";
106 default: return "";
107 }
108 }
109}
java/pkg/sun/net/httpserver/ContextList.java+97−0
@@ -0,0 +1,97 @@
1/*
2 * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.util.*;
29import com.sun.net.httpserver.*;
30import com.sun.net.httpserver.spi.*;
31
32class ContextList {
33
34 final static int MAX_CONTEXTS = 50;
35
36 LinkedList<HttpContextImpl> list = new LinkedList<HttpContextImpl>();
37
38 public synchronized void add (HttpContextImpl ctx) {
39 assert ctx.getPath() != null;
40 list.add (ctx);
41 }
42
43 public synchronized int size () {
44 return list.size();
45 }
46
47 /* initially contexts are located only by protocol:path.
48 * Context with longest prefix matches (currently case-sensitive)
49 */
50 synchronized HttpContextImpl findContext (String protocol, String path) {
51 return findContext (protocol, path, false);
52 }
53
54 synchronized HttpContextImpl findContext (String protocol, String path, boolean exact) {
55 protocol = protocol.toLowerCase();
56 String longest = "";
57 HttpContextImpl lc = null;
58 for (HttpContextImpl ctx: list) {
59 if (!ctx.getProtocol().equals(protocol)) {
60 continue;
61 }
62 String cpath = ctx.getPath();
63 if (exact && !cpath.equals (path)) {
64 continue;
65 } else if (!exact && !path.startsWith(cpath)) {
66 continue;
67 }
68 if (cpath.length() > longest.length()) {
69 longest = cpath;
70 lc = ctx;
71 }
72 }
73 return lc;
74 }
75
76 public synchronized void remove (String protocol, String path)
77 throws IllegalArgumentException
78 {
79 HttpContextImpl ctx = findContext (protocol, path, true);
80 if (ctx == null) {
81 throw new IllegalArgumentException ("cannot remove element from list");
82 }
83 list.remove (ctx);
84 }
85
86 public synchronized void remove (HttpContextImpl context)
87 throws IllegalArgumentException
88 {
89 for (HttpContextImpl ctx: list) {
90 if (ctx.equals (context)) {
91 list.remove (ctx);
92 return;
93 }
94 }
95 throw new IllegalArgumentException ("no such context in list");
96 }
97}
java/pkg/sun/net/httpserver/DefaultHttpServerProvider.java+41−0
@@ -0,0 +1,41 @@
1/*
2 * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.net.*;
29import java.io.*;
30import com.sun.net.httpserver.*;
31import com.sun.net.httpserver.spi.*;
32
33public class DefaultHttpServerProvider extends HttpServerProvider {
34 public HttpServer createHttpServer (InetSocketAddress addr, int backlog) throws IOException {
35 return new HttpServerImpl (addr, backlog);
36 }
37
38 public HttpsServer createHttpsServer (InetSocketAddress addr, int backlog) throws IOException {
39 return new HttpsServerImpl (addr, backlog);
40 }
41}
java/pkg/sun/net/httpserver/Event.java+46−0
@@ -0,0 +1,46 @@
1/*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import com.sun.net.httpserver.*;
29import com.sun.net.httpserver.spi.*;
30
31class Event {
32
33 ExchangeImpl exchange;
34
35 protected Event (ExchangeImpl t) {
36 this.exchange = t;
37 }
38}
39
40class WriteFinishedEvent extends Event {
41 WriteFinishedEvent (ExchangeImpl t) {
42 super (t);
43 assert !t.writefinished;
44 t.writefinished = true;
45 }
46}
java/pkg/sun/net/httpserver/ExchangeImpl.java+456−0
@@ -0,0 +1,456 @@
1/*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import java.net.*;
30import javax.net.ssl.*;
31import java.util.*;
32import java.util.logging.Logger;
33import java.text.*;
34import com.sun.net.httpserver.*;
35
36class ExchangeImpl {
37
38 Headers reqHdrs, rspHdrs;
39 Request req;
40 String method;
41 boolean writefinished;
42 URI uri;
43 HttpConnection connection;
44 long reqContentLen;
45 long rspContentLen;
46 /* raw streams which access the socket directly */
47 InputStream ris;
48 OutputStream ros;
49 Thread thread;
50 /* close the underlying connection when this exchange finished */
51 boolean close;
52 boolean closed;
53 boolean http10 = false;
54
55 /* for formatting the Date: header */
56 private static final String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz";
57 private static final TimeZone gmtTZ = TimeZone.getTimeZone("GMT");
58 private static final ThreadLocal<DateFormat> dateFormat =
59 new ThreadLocal<DateFormat>() {
60 @Override protected DateFormat initialValue() {
61 DateFormat df = new SimpleDateFormat(pattern, Locale.US);
62 df.setTimeZone(gmtTZ);
63 return df;
64 }
65 };
66
67 private static final String HEAD = "HEAD";
68
69 /* streams which take care of the HTTP protocol framing
70 * and are passed up to higher layers
71 */
72 InputStream uis;
73 OutputStream uos;
74 LeftOverInputStream uis_orig; // uis may have be a user supplied wrapper
75 PlaceholderOutputStream uos_orig;
76
77 boolean sentHeaders; /* true after response headers sent */
78 Map<String,Object> attributes;
79 int rcode = -1;
80 HttpPrincipal principal;
81 ServerImpl server;
82
83 ExchangeImpl (
84 String m, URI u, Request req, long len, HttpConnection connection
85 ) throws IOException {
86 this.req = req;
87 this.reqHdrs = req.headers();
88 this.rspHdrs = new Headers();
89 this.method = m;
90 this.uri = u;
91 this.connection = connection;
92 this.reqContentLen = len;
93 /* ros only used for headers, body written directly to stream */
94 this.ros = req.outputStream();
95 this.ris = req.inputStream();
96 server = getServerImpl();
97 server.startExchange();
98 }
99
100 public Headers getRequestHeaders () {
101 return new UnmodifiableHeaders (reqHdrs);
102 }
103
104 public Headers getResponseHeaders () {
105 return rspHdrs;
106 }
107
108 public URI getRequestURI () {
109 return uri;
110 }
111
112 public String getRequestMethod (){
113 return method;
114 }
115
116 public HttpContextImpl getHttpContext (){
117 return connection.getHttpContext();
118 }
119
120 private boolean isHeadRequest() {
121 return HEAD.equals(getRequestMethod());
122 }
123
124 public void close () {
125 if (closed) {
126 return;
127 }
128 closed = true;
129
130 /* close the underlying connection if,
131 * a) the streams not set up yet, no response can be sent, or
132 * b) if the wrapper output stream is not set up, or
133 * c) if the close of the input/outpu stream fails
134 */
135 try {
136 if (uis_orig == null || uos == null) {
137 connection.close();
138 return;
139 }
140 if (!uos_orig.isWrapped()) {
141 connection.close();
142 return;
143 }
144 if (!uis_orig.isClosed()) {
145 uis_orig.close();
146 }
147 uos.close();
148 } catch (IOException e) {
149 connection.close();
150 }
151 }
152
153 public InputStream getRequestBody () {
154 if (uis != null) {
155 return uis;
156 }
157 if (reqContentLen == -1L) {
158 uis_orig = new ChunkedInputStream (this, ris);
159 uis = uis_orig;
160 } else {
161 uis_orig = new FixedLengthInputStream (this, ris, reqContentLen);
162 uis = uis_orig;
163 }
164 return uis;
165 }
166
167 LeftOverInputStream getOriginalInputStream () {
168 return uis_orig;
169 }
170
171 public int getResponseCode () {
172 return rcode;
173 }
174
175 public OutputStream getResponseBody () {
176 /* TODO. Change spec to remove restriction below. Filters
177 * cannot work with this restriction
178 *
179 * if (!sentHeaders) {
180 * throw new IllegalStateException ("headers not sent");
181 * }
182 */
183 if (uos == null) {
184 uos_orig = new PlaceholderOutputStream (null);
185 uos = uos_orig;
186 }
187 return uos;
188 }
189
190
191 /* returns the place holder stream, which is the stream
192 * returned from the 1st call to getResponseBody()
193 * The "real" ouputstream is then placed inside this
194 */
195 PlaceholderOutputStream getPlaceholderResponseBody () {
196 getResponseBody();
197 return uos_orig;
198 }
199
200 public void sendResponseHeaders (int rCode, long contentLen)
201 throws IOException
202 {
203 if (sentHeaders) {
204 throw new IOException ("headers already sent");
205 }
206 this.rcode = rCode;
207 String statusLine = "HTTP/1.1 "+rCode+Code.msg(rCode)+"\r\n";
208 OutputStream tmpout = new BufferedOutputStream (ros);
209 PlaceholderOutputStream o = getPlaceholderResponseBody();
210 tmpout.write (bytes(statusLine, 0), 0, statusLine.length());
211 boolean noContentToSend = false; // assume there is content
212 rspHdrs.set ("Date", dateFormat.get().format (new Date()));
213
214 /* check for response type that is not allowed to send a body */
215
216 if ((rCode>=100 && rCode <200) /* informational */
217 ||(rCode == 204) /* no content */
218 ||(rCode == 304)) /* not modified */
219 {
220 if (contentLen != -1) {
221 Logger logger = server.getLogger();
222 String msg = "sendResponseHeaders: rCode = "+ rCode
223 + ": forcing contentLen = -1";
224 logger.warning (msg);
225 }
226 contentLen = -1;
227 }
228
229 if (isHeadRequest()) {
230 /* HEAD requests should not set a content length by passing it
231 * through this API, but should instead manually set the required
232 * headers.*/
233 if (contentLen >= 0) {
234 final Logger logger = server.getLogger();
235 String msg =
236 "sendResponseHeaders: being invoked with a content length for a HEAD request";
237 logger.warning (msg);
238 }
239 noContentToSend = true;
240 contentLen = 0;
241 } else { /* not a HEAD request */
242 if (contentLen == 0) {
243 if (http10) {
244 o.setWrappedStream (new UndefLengthOutputStream (this, ros));
245 close = true;
246 } else {
247 rspHdrs.set ("Transfer-encoding", "chunked");
248 o.setWrappedStream (new ChunkedOutputStream (this, ros));
249 }
250 } else {
251 if (contentLen == -1) {
252 noContentToSend = true;
253 contentLen = 0;
254 }
255 rspHdrs.set("Content-length", Long.toString(contentLen));
256 o.setWrappedStream (new FixedLengthOutputStream (this, ros, contentLen));
257 }
258 }
259 write (rspHdrs, tmpout);
260 this.rspContentLen = contentLen;
261 tmpout.flush() ;
262 tmpout = null;
263 sentHeaders = true;
264 if (noContentToSend) {
265 WriteFinishedEvent e = new WriteFinishedEvent (this);
266 server.addEvent (e);
267 closed = true;
268 }
269 server.logReply (rCode, req.requestLine(), null);
270 }
271
272 void write (Headers map, OutputStream os) throws IOException {
273 Set<Map.Entry<String,List<String>>> entries = map.entrySet();
274 for (Map.Entry<String,List<String>> entry : entries) {
275 String key = entry.getKey();
276 byte[] buf;
277 List<String> values = entry.getValue();
278 for (String val : values) {
279 int i = key.length();
280 buf = bytes (key, 2);
281 buf[i++] = ':';
282 buf[i++] = ' ';
283 os.write (buf, 0, i);
284 buf = bytes (val, 2);
285 i = val.length();
286 buf[i++] = '\r';
287 buf[i++] = '\n';
288 os.write (buf, 0, i);
289 }
290 }
291 os.write ('\r');
292 os.write ('\n');
293 }
294
295 private byte[] rspbuf = new byte [128]; // used by bytes()
296
297 /**
298 * convert string to byte[], using rspbuf
299 * Make sure that at least "extra" bytes are free at end
300 * of rspbuf. Reallocate rspbuf if not big enough.
301 * caller must check return value to see if rspbuf moved
302 */
303 private byte[] bytes (String s, int extra) {
304 int slen = s.length();
305 if (slen+extra > rspbuf.length) {
306 int diff = slen + extra - rspbuf.length;
307 rspbuf = new byte [2* (rspbuf.length + diff)];
308 }
309 char c[] = s.toCharArray();
310 for (int i=0; i<c.length; i++) {
311 rspbuf[i] = (byte)c[i];
312 }
313 return rspbuf;
314 }
315
316 public InetSocketAddress getRemoteAddress (){
317 Socket s = connection.getChannel().socket();
318 InetAddress ia = s.getInetAddress();
319 int port = s.getPort();
320 return new InetSocketAddress (ia, port);
321 }
322
323 public InetSocketAddress getLocalAddress (){
324 Socket s = connection.getChannel().socket();
325 InetAddress ia = s.getLocalAddress();
326 int port = s.getLocalPort();
327 return new InetSocketAddress (ia, port);
328 }
329
330 public String getProtocol (){
331 String reqline = req.requestLine();
332 int index = reqline.lastIndexOf (' ');
333 return reqline.substring (index+1);
334 }
335
336 public SSLSession getSSLSession () {
337 SSLEngine e = connection.getSSLEngine();
338 if (e == null) {
339 return null;
340 }
341 return e.getSession();
342 }
343
344 public Object getAttribute (String name) {
345 if (name == null) {
346 throw new NullPointerException ("null name parameter");
347 }
348 if (attributes == null) {
349 attributes = getHttpContext().getAttributes();
350 }
351 return attributes.get (name);
352 }
353
354 public void setAttribute (String name, Object value) {
355 if (name == null) {
356 throw new NullPointerException ("null name parameter");
357 }
358 if (attributes == null) {
359 attributes = getHttpContext().getAttributes();
360 }
361 attributes.put (name, value);
362 }
363
364 public void setStreams (InputStream i, OutputStream o) {
365 assert uis != null;
366 if (i != null) {
367 uis = i;
368 }
369 if (o != null) {
370 uos = o;
371 }
372 }
373
374 /**
375 * PP
376 */
377 HttpConnection getConnection () {
378 return connection;
379 }
380
381 ServerImpl getServerImpl () {
382 return getHttpContext().getServerImpl();
383 }
384
385 public HttpPrincipal getPrincipal () {
386 return principal;
387 }
388
389 void setPrincipal (HttpPrincipal principal) {
390 this.principal = principal;
391 }
392
393 static ExchangeImpl get (HttpExchange t) {
394 if (t instanceof HttpExchangeImpl) {
395 return ((HttpExchangeImpl)t).getExchangeImpl();
396 } else {
397 assert t instanceof HttpsExchangeImpl;
398 return ((HttpsExchangeImpl)t).getExchangeImpl();
399 }
400 }
401}
402
403/**
404 * An OutputStream which wraps another stream
405 * which is supplied either at creation time, or sometime later.
406 * If a caller/user tries to write to this stream before
407 * the wrapped stream has been provided, then an IOException will
408 * be thrown.
409 */
410class PlaceholderOutputStream extends java.io.OutputStream {
411
412 OutputStream wrapped;
413
414 PlaceholderOutputStream (OutputStream os) {
415 wrapped = os;
416 }
417
418 void setWrappedStream (OutputStream os) {
419 wrapped = os;
420 }
421
422 boolean isWrapped () {
423 return wrapped != null;
424 }
425
426 private void checkWrap () throws IOException {
427 if (wrapped == null) {
428 throw new IOException ("response headers not sent yet");
429 }
430 }
431
432 public void write(int b) throws IOException {
433 checkWrap();
434 wrapped.write (b);
435 }
436
437 public void write(byte b[]) throws IOException {
438 checkWrap();
439 wrapped.write (b);
440 }
441
442 public void write(byte b[], int off, int len) throws IOException {
443 checkWrap();
444 wrapped.write (b, off, len);
445 }
446
447 public void flush() throws IOException {
448 checkWrap();
449 wrapped.flush();
450 }
451
452 public void close() throws IOException {
453 checkWrap();
454 wrapped.close();
455 }
456}
java/pkg/sun/net/httpserver/FixedLengthInputStream.java+82−0
@@ -0,0 +1,82 @@
1/*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import java.net.*;
30import com.sun.net.httpserver.*;
31import com.sun.net.httpserver.spi.*;
32
33/**
34 * a class which allows the caller to read up to a defined
35 * number of bytes off an underlying stream
36 * close() does not close the underlying stream
37 */
38
39class FixedLengthInputStream extends LeftOverInputStream {
40 private long remaining;
41
42 FixedLengthInputStream (ExchangeImpl t, InputStream src, long len) {
43 super (t, src);
44 this.remaining = len;
45 }
46
47 protected int readImpl (byte[]b, int off, int len) throws IOException {
48
49 eof = (remaining == 0L);
50 if (eof) {
51 return -1;
52 }
53 if (len > remaining) {
54 len = (int)remaining;
55 }
56 int n = in.read(b, off, len);
57 if (n > -1) {
58 remaining -= n;
59 if (remaining == 0) {
60 t.getServerImpl().requestCompleted (t.getConnection());
61 }
62 }
63 return n;
64 }
65
66 public int available () throws IOException {
67 if (eof) {
68 return 0;
69 }
70 int n = in.available();
71 return n < remaining? n: (int)remaining;
72 }
73
74 public boolean markSupported () {return false;}
75
76 public void mark (int l) {
77 }
78
79 public void reset () throws IOException {
80 throw new IOException ("mark/reset not supported");
81 }
82}
java/pkg/sun/net/httpserver/FixedLengthOutputStream.java+104−0
@@ -0,0 +1,104 @@
1/*
2 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import java.net.*;
30import com.sun.net.httpserver.*;
31import com.sun.net.httpserver.spi.*;
32
33/**
34 * a class which allows the caller to write up to a defined
35 * number of bytes to an underlying stream. The caller *must*
36 * write the pre-defined number or else an exception will be thrown
37 * and the whole request aborted.
38 * normal close() does not close the underlying stream
39 */
40
41class FixedLengthOutputStream extends FilterOutputStream
42{
43 private long remaining;
44 private boolean eof = false;
45 private boolean closed = false;
46 ExchangeImpl t;
47
48 FixedLengthOutputStream (ExchangeImpl t, OutputStream src, long len) {
49 super (src);
50 this.t = t;
51 this.remaining = len;
52 }
53
54 public void write (int b) throws IOException {
55 if (closed) {
56 throw new IOException ("stream closed");
57 }
58 eof = (remaining == 0);
59 if (eof) {
60 throw new StreamClosedException();
61 }
62 out.write(b);
63 remaining --;
64 }
65
66 public void write (byte[]b, int off, int len) throws IOException {
67 if (closed) {
68 throw new IOException ("stream closed");
69 }
70 eof = (remaining == 0);
71 if (eof) {
72 throw new StreamClosedException();
73 }
74 if (len > remaining) {
75 // stream is still open, caller can retry
76 throw new IOException ("too many bytes to write to stream");
77 }
78 out.write(b, off, len);
79 remaining -= len;
80 }
81
82 public void close () throws IOException {
83 if (closed) {
84 return;
85 }
86 closed = true;
87 if (remaining > 0) {
88 t.close();
89 throw new IOException ("insufficient bytes written to stream");
90 }
91 flush();
92 eof = true;
93 LeftOverInputStream is = t.getOriginalInputStream();
94 if (!is.isClosed()) {
95 try {
96 is.close();
97 } catch (IOException e) {}
98 }
99 WriteFinishedEvent e = new WriteFinishedEvent (t);
100 t.getHttpContext().getServerImpl().addEvent (e);
101 }
102
103 // flush is a pass-through
104}
java/pkg/sun/net/httpserver/HttpConnection.java+196−0
@@ -0,0 +1,196 @@
1/*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import javax.net.ssl.*;
30import java.nio.channels.*;
31import java.util.logging.Logger;
32import com.sun.net.httpserver.*;
33import com.sun.net.httpserver.spi.*;
34
35/**
36 * encapsulates all the connection specific state for a HTTP/S connection
37 * one of these is hung from the selector attachment and is used to locate
38 * everything from that.
39 */
40class HttpConnection {
41
42 HttpContextImpl context;
43 SSLEngine engine;
44 SSLContext sslContext;
45 SSLStreams sslStreams;
46
47 /* high level streams returned to application */
48 InputStream i;
49
50 /* low level stream that sits directly over channel */
51 InputStream raw;
52 OutputStream rawout;
53
54 SocketChannel chan;
55 SelectionKey selectionKey;
56 String protocol;
57 long time;
58 volatile long creationTime; // time this connection was created
59 volatile long rspStartedTime; // time we started writing the response
60 int remaining;
61 boolean closed = false;
62 Logger logger;
63
64 public enum State {IDLE, REQUEST, RESPONSE};
65 volatile State state;
66
67 public String toString() {
68 String s = null;
69 if (chan != null) {
70 s = chan.toString();
71 }
72 return s;
73 }
74
75 HttpConnection () {
76 }
77
78 void setChannel (SocketChannel c) {
79 chan = c;
80 }
81
82 void setContext (HttpContextImpl ctx) {
83 context = ctx;
84 }
85
86 State getState() {
87 return state;
88 }
89
90 void setState (State s) {
91 state = s;
92 }
93
94 void setParameters (
95 InputStream in, OutputStream rawout, SocketChannel chan,
96 SSLEngine engine, SSLStreams sslStreams, SSLContext sslContext, String protocol,
97 HttpContextImpl context, InputStream raw
98 )
99 {
100 this.context = context;
101 this.i = in;
102 this.rawout = rawout;
103 this.raw = raw;
104 this.protocol = protocol;
105 this.engine = engine;
106 this.chan = chan;
107 this.sslContext = sslContext;
108 this.sslStreams = sslStreams;
109 this.logger = context.getLogger();
110 }
111
112 SocketChannel getChannel () {
113 return chan;
114 }
115
116 synchronized void close () {
117 if (closed) {
118 return;
119 }
120 closed = true;
121 if (logger != null && chan != null) {
122 logger.finest ("Closing connection: " + chan.toString());
123 }
124
125 if (!chan.isOpen()) {
126 ServerImpl.dprint ("Channel already closed");
127 return;
128 }
129 try {
130 /* need to ensure temporary selectors are closed */
131 if (raw != null) {
132 raw.close();
133 }
134 } catch (IOException e) {
135 ServerImpl.dprint (e);
136 }
137 try {
138 if (rawout != null) {
139 rawout.close();
140 }
141 } catch (IOException e) {
142 ServerImpl.dprint (e);
143 }
144 try {
145 if (sslStreams != null) {
146 sslStreams.close();
147 }
148 } catch (IOException e) {
149 ServerImpl.dprint (e);
150 }
151 try {
152 chan.close();
153 } catch (IOException e) {
154 ServerImpl.dprint (e);
155 }
156 }
157
158 /* remaining is the number of bytes left on the lowest level inputstream
159 * after the exchange is finished
160 */
161 void setRemaining (int r) {
162 remaining = r;
163 }
164
165 int getRemaining () {
166 return remaining;
167 }
168
169 SelectionKey getSelectionKey () {
170 return selectionKey;
171 }
172
173 InputStream getInputStream () {
174 return i;
175 }
176
177 OutputStream getRawOutputStream () {
178 return rawout;
179 }
180
181 String getProtocol () {
182 return protocol;
183 }
184
185 SSLEngine getSSLEngine () {
186 return engine;
187 }
188
189 SSLContext getSSLContext () {
190 return sslContext;
191 }
192
193 HttpContextImpl getHttpContext () {
194 return context;
195 }
196}
java/pkg/sun/net/httpserver/HttpContextImpl.java+152−0
@@ -0,0 +1,152 @@
1/*
2 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27import java.io.*;
28import java.util.*;
29import java.util.logging.Logger;
30import com.sun.net.httpserver.*;
31import com.sun.net.httpserver.spi.*;
32
33/**
34 * HttpContext represents a mapping between a protocol (http or https) together with a root URI path
35 * to a {@link HttpHandler} which is invoked to handle requests destined
36 * for the protocol/path on the associated HttpServer.
37 * <p>
38 * HttpContext instances are created by {@link HttpServer#createContext(String,String,HttpHandler,Object)}
39 * <p>
40 */
41class HttpContextImpl extends HttpContext {
42
43 private String path;
44 private String protocol;
45 private HttpHandler handler;
46 private Map<String,Object> attributes = new HashMap<String,Object>();
47 private ServerImpl server;
48 /* system filters, not visible to applications */
49 private LinkedList<Filter> sfilters = new LinkedList<Filter>();
50 /* user filters, set by applications */
51 private LinkedList<Filter> ufilters = new LinkedList<Filter>();
52 private Authenticator authenticator;
53 private AuthFilter authfilter;
54
55 /**
56 * constructor is package private.
57 */
58 HttpContextImpl (String protocol, String path, HttpHandler cb, ServerImpl server) {
59 if (path == null || protocol == null || path.length() < 1 || path.charAt(0) != '/') {
60 throw new IllegalArgumentException ("Illegal value for path or protocol");
61 }
62 this.protocol = protocol.toLowerCase();
63 this.path = path;
64 if (!this.protocol.equals ("http") && !this.protocol.equals ("https")) {
65 throw new IllegalArgumentException ("Illegal value for protocol");
66 }
67 this.handler = cb;
68 this.server = server;
69 authfilter = new AuthFilter(null);
70 sfilters.add (authfilter);
71 }
72
73 /**
74 * returns the handler for this context
75 * @return the HttpHandler for this context
76 */
77 public HttpHandler getHandler () {
78 return handler;
79 }
80
81 public void setHandler (HttpHandler h) {
82 if (h == null) {
83 throw new NullPointerException ("Null handler parameter");
84 }
85 if (handler != null) {
86 throw new IllegalArgumentException ("handler already set");
87 }
88 handler = h;
89 }
90
91 /**
92 * returns the path this context was created with
93 * @return this context's path
94 */
95 public String getPath() {
96 return path;
97 }
98
99 /**
100 * returns the server this context was created with
101 * @return this context's server
102 */
103 public HttpServer getServer () {
104 return server.getWrapper();
105 }
106
107 ServerImpl getServerImpl () {
108 return server;
109 }
110
111 /**
112 * returns the protocol this context was created with
113 * @return this context's path
114 */
115 public String getProtocol() {
116 return protocol;
117 }
118
119 /**
120 * returns a mutable Map, which can be used to pass
121 * configuration and other data to Filter modules
122 * and to the context's exchange handler.
123 * <p>
124 * Every attribute stored in this Map will be visible to
125 * every HttpExchange processed by this context
126 */
127 public Map<String,Object> getAttributes() {
128 return attributes;
129 }
130
131 public List<Filter> getFilters () {
132 return ufilters;
133 }
134
135 List<Filter> getSystemFilters () {
136 return sfilters;
137 }
138
139 public Authenticator setAuthenticator (Authenticator auth) {
140 Authenticator old = authenticator;
141 authenticator = auth;
142 authfilter.setAuthenticator (auth);
143 return old;
144 }
145
146 public Authenticator getAuthenticator () {
147 return authenticator;
148 }
149 Logger getLogger () {
150 return server.getLogger();
151 }
152}
java/pkg/sun/net/httpserver/HttpError.java+37−0
@@ -0,0 +1,37 @@
1/*
2 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28/**
29 * A Http error
30 */
31class HttpError extends RuntimeException {
32 private static final long serialVersionUID = 8769596371344178179L;
33
34 public HttpError (String msg) {
35 super (msg);
36 }
37}
java/pkg/sun/net/httpserver/HttpExchangeImpl.java+120−0
@@ -0,0 +1,120 @@
1/*
2 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import java.nio.*;
30import java.nio.channels.*;
31import java.net.*;
32import javax.net.ssl.*;
33import java.util.*;
34import sun.net.www.MessageHeader;
35import com.sun.net.httpserver.*;
36import com.sun.net.httpserver.spi.*;
37
38class HttpExchangeImpl extends HttpExchange {
39
40 ExchangeImpl impl;
41
42 HttpExchangeImpl (ExchangeImpl impl) {
43 this.impl = impl;
44 }
45
46 public Headers getRequestHeaders () {
47 return impl.getRequestHeaders();
48 }
49
50 public Headers getResponseHeaders () {
51 return impl.getResponseHeaders();
52 }
53
54 public URI getRequestURI () {
55 return impl.getRequestURI();
56 }
57
58 public String getRequestMethod (){
59 return impl.getRequestMethod();
60 }
61
62 public HttpContextImpl getHttpContext (){
63 return impl.getHttpContext();
64 }
65
66 public void close () {
67 impl.close();
68 }
69
70 public InputStream getRequestBody () {
71 return impl.getRequestBody();
72 }
73
74 public int getResponseCode () {
75 return impl.getResponseCode();
76 }
77
78 public OutputStream getResponseBody () {
79 return impl.getResponseBody();
80 }
81
82
83 public void sendResponseHeaders (int rCode, long contentLen)
84 throws IOException
85 {
86 impl.sendResponseHeaders (rCode, contentLen);
87 }
88
89 public InetSocketAddress getRemoteAddress (){
90 return impl.getRemoteAddress();
91 }
92
93 public InetSocketAddress getLocalAddress (){
94 return impl.getLocalAddress();
95 }
96
97 public String getProtocol (){
98 return impl.getProtocol();
99 }
100
101 public Object getAttribute (String name) {
102 return impl.getAttribute (name);
103 }
104
105 public void setAttribute (String name, Object value) {
106 impl.setAttribute (name, value);
107 }
108
109 public void setStreams (InputStream i, OutputStream o) {
110 impl.setStreams (i, o);
111 }
112
113 public HttpPrincipal getPrincipal () {
114 return impl.getPrincipal();
115 }
116
117 ExchangeImpl getExchangeImpl () {
118 return impl;
119 }
120}
java/pkg/sun/net/httpserver/HttpServerImpl.java+92−0
@@ -0,0 +1,92 @@
1/*
2 * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.net.*;
29import java.io.*;
30import java.nio.*;
31import java.security.*;
32import java.nio.channels.*;
33import java.util.*;
34import java.util.concurrent.*;
35import javax.net.ssl.*;
36import com.sun.net.httpserver.*;
37import com.sun.net.httpserver.spi.*;
38
39public class HttpServerImpl extends HttpServer {
40
41 ServerImpl server;
42
43 HttpServerImpl () throws IOException {
44 this (new InetSocketAddress(80), 0);
45 }
46
47 HttpServerImpl (
48 InetSocketAddress addr, int backlog
49 ) throws IOException {
50 server = new ServerImpl (this, "http", addr, backlog);
51 }
52
53 public void bind (InetSocketAddress addr, int backlog) throws IOException {
54 server.bind (addr, backlog);
55 }
56
57 public void start () {
58 server.start();
59 }
60
61 public void setExecutor (Executor executor) {
62 server.setExecutor(executor);
63 }
64
65 public Executor getExecutor () {
66 return server.getExecutor();
67 }
68
69 public void stop (int delay) {
70 server.stop (delay);
71 }
72
73 public HttpContextImpl createContext (String path, HttpHandler handler) {
74 return server.createContext (path, handler);
75 }
76
77 public HttpContextImpl createContext (String path) {
78 return server.createContext (path);
79 }
80
81 public void removeContext (String path) throws IllegalArgumentException {
82 server.removeContext (path);
83 }
84
85 public void removeContext (HttpContext context) throws IllegalArgumentException {
86 server.removeContext (context);
87 }
88
89 public InetSocketAddress getAddress() {
90 return server.getAddress();
91 }
92}
java/pkg/sun/net/httpserver/HttpsExchangeImpl.java+124−0
@@ -0,0 +1,124 @@
1/*
2 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import java.nio.*;
30import java.nio.channels.*;
31import java.net.*;
32import javax.net.ssl.*;
33import java.util.*;
34import sun.net.www.MessageHeader;
35import com.sun.net.httpserver.*;
36import com.sun.net.httpserver.spi.*;
37
38class HttpsExchangeImpl extends HttpsExchange {
39
40 ExchangeImpl impl;
41
42 HttpsExchangeImpl (ExchangeImpl impl) throws IOException {
43 this.impl = impl;
44 }
45
46 public Headers getRequestHeaders () {
47 return impl.getRequestHeaders();
48 }
49
50 public Headers getResponseHeaders () {
51 return impl.getResponseHeaders();
52 }
53
54 public URI getRequestURI () {
55 return impl.getRequestURI();
56 }
57
58 public String getRequestMethod (){
59 return impl.getRequestMethod();
60 }
61
62 public HttpContextImpl getHttpContext (){
63 return impl.getHttpContext();
64 }
65
66 public void close () {
67 impl.close();
68 }
69
70 public InputStream getRequestBody () {
71 return impl.getRequestBody();
72 }
73
74 public int getResponseCode () {
75 return impl.getResponseCode();
76 }
77
78 public OutputStream getResponseBody () {
79 return impl.getResponseBody();
80 }
81
82
83 public void sendResponseHeaders (int rCode, long contentLen)
84 throws IOException
85 {
86 impl.sendResponseHeaders (rCode, contentLen);
87 }
88
89 public InetSocketAddress getRemoteAddress (){
90 return impl.getRemoteAddress();
91 }
92
93 public InetSocketAddress getLocalAddress (){
94 return impl.getLocalAddress();
95 }
96
97 public String getProtocol (){
98 return impl.getProtocol();
99 }
100
101 public SSLSession getSSLSession () {
102 return impl.getSSLSession ();
103 }
104
105 public Object getAttribute (String name) {
106 return impl.getAttribute (name);
107 }
108
109 public void setAttribute (String name, Object value) {
110 impl.setAttribute (name, value);
111 }
112
113 public void setStreams (InputStream i, OutputStream o) {
114 impl.setStreams (i, o);
115 }
116
117 public HttpPrincipal getPrincipal () {
118 return impl.getPrincipal();
119 }
120
121 ExchangeImpl getExchangeImpl () {
122 return impl;
123 }
124}
java/pkg/sun/net/httpserver/HttpsServerImpl.java+100−0
@@ -0,0 +1,100 @@
1/*
2 * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.net.*;
29import java.io.*;
30import java.nio.*;
31import java.security.*;
32import java.nio.channels.*;
33import java.util.*;
34import java.util.concurrent.*;
35import javax.net.ssl.*;
36import com.sun.net.httpserver.*;
37import com.sun.net.httpserver.spi.*;
38
39public class HttpsServerImpl extends HttpsServer {
40
41 ServerImpl server;
42
43 HttpsServerImpl () throws IOException {
44 this (new InetSocketAddress(443), 0);
45 }
46
47 HttpsServerImpl (
48 InetSocketAddress addr, int backlog
49 ) throws IOException {
50 server = new ServerImpl (this, "https", addr, backlog);
51 }
52
53 public void setHttpsConfigurator (HttpsConfigurator config) {
54 server.setHttpsConfigurator (config);
55 }
56
57 public HttpsConfigurator getHttpsConfigurator () {
58 return server.getHttpsConfigurator();
59 }
60
61 public void bind (InetSocketAddress addr, int backlog) throws IOException {
62 server.bind (addr, backlog);
63 }
64
65 public void start () {
66 server.start();
67 }
68
69 public void setExecutor (Executor executor) {
70 server.setExecutor(executor);
71 }
72
73 public Executor getExecutor () {
74 return server.getExecutor();
75 }
76
77 public void stop (int delay) {
78 server.stop (delay);
79 }
80
81 public HttpContextImpl createContext (String path, HttpHandler handler) {
82 return server.createContext (path, handler);
83 }
84
85 public HttpContextImpl createContext (String path) {
86 return server.createContext (path);
87 }
88
89 public void removeContext (String path) throws IllegalArgumentException {
90 server.removeContext (path);
91 }
92
93 public void removeContext (HttpContext context) throws IllegalArgumentException {
94 server.removeContext (context);
95 }
96
97 public InetSocketAddress getAddress() {
98 return server.getAddress();
99 }
100}
java/pkg/sun/net/httpserver/LeftOverInputStream.java+122−0
@@ -0,0 +1,122 @@
1/*
2 * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import com.sun.net.httpserver.*;
30import com.sun.net.httpserver.spi.*;
31
32/**
33 * a (filter) input stream which can tell us if bytes are "left over"
34 * on the underlying stream which can be read (without blocking)
35 * on another instance of this class.
36 *
37 * The class can also report if all bytes "expected" to be read
38 * were read, by the time close() was called. In that case,
39 * bytes may be drained to consume them (by calling drain() ).
40 *
41 * isEOF() returns true, when all expected bytes have been read
42 */
43abstract class LeftOverInputStream extends FilterInputStream {
44 ExchangeImpl t;
45 ServerImpl server;
46 protected boolean closed = false;
47 protected boolean eof = false;
48 byte[] one = new byte [1];
49
50 public LeftOverInputStream (ExchangeImpl t, InputStream src) {
51 super (src);
52 this.t = t;
53 this.server = t.getServerImpl();
54 }
55 /**
56 * if bytes are left over buffered on *the UNDERLYING* stream
57 */
58 public boolean isDataBuffered () throws IOException {
59 assert eof;
60 return super.available() > 0;
61 }
62
63 public void close () throws IOException {
64 if (closed) {
65 return;
66 }
67 closed = true;
68 if (!eof) {
69 eof = drain (ServerConfig.getDrainAmount());
70 }
71 }
72
73 public boolean isClosed () {
74 return closed;
75 }
76
77 public boolean isEOF () {
78 return eof;
79 }
80
81 protected abstract int readImpl (byte[]b, int off, int len) throws IOException;
82
83 public synchronized int read () throws IOException {
84 if (closed) {
85 throw new IOException ("Stream is closed");
86 }
87 int c = readImpl (one, 0, 1);
88 if (c == -1 || c == 0) {
89 return c;
90 } else {
91 return one[0] & 0xFF;
92 }
93 }
94
95 public synchronized int read (byte[]b, int off, int len) throws IOException {
96 if (closed) {
97 throw new IOException ("Stream is closed");
98 }
99 return readImpl (b, off, len);
100 }
101
102 /**
103 * read and discard up to l bytes or "eof" occurs,
104 * (whichever is first). Then return true if the stream
105 * is at eof (ie. all bytes were read) or false if not
106 * (still bytes to be read)
107 */
108 public boolean drain (long l) throws IOException {
109 int bufSize = 2048;
110 byte[] db = new byte [bufSize];
111 while (l > 0) {
112 long len = readImpl (db, 0, bufSize);
113 if (len == -1) {
114 eof = true;
115 return true;
116 } else {
117 l = l - len;
118 }
119 }
120 return false;
121 }
122}
java/pkg/sun/net/httpserver/Request.java+402−0
@@ -0,0 +1,402 @@
1/*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.util.*;
29import java.nio.*;
30import java.net.*;
31import java.io.*;
32import java.nio.channels.*;
33import com.sun.net.httpserver.*;
34import com.sun.net.httpserver.spi.*;
35
36/**
37 */
38class Request {
39
40 final static int BUF_LEN = 2048;
41 final static byte CR = 13;
42 final static byte LF = 10;
43
44 private String startLine;
45 private SocketChannel chan;
46 private InputStream is;
47 private OutputStream os;
48
49 Request (InputStream rawInputStream, OutputStream rawout) throws IOException {
50 this.chan = chan;
51 is = rawInputStream;
52 os = rawout;
53 do {
54 startLine = readLine();
55 if (startLine == null) {
56 return;
57 }
58 /* skip blank lines */
59 } while (startLine == null ? false : startLine.equals (""));
60 }
61
62
63 char[] buf = new char [BUF_LEN];
64 int pos;
65 StringBuffer lineBuf;
66
67 public InputStream inputStream () {
68 return is;
69 }
70
71 public OutputStream outputStream () {
72 return os;
73 }
74
75 /**
76 * read a line from the stream returning as a String.
77 * Not used for reading headers.
78 */
79
80 public String readLine () throws IOException {
81 boolean gotCR = false, gotLF = false;
82 pos = 0; lineBuf = new StringBuffer();
83 while (!gotLF) {
84 int c = is.read();
85 if (c == -1) {
86 return null;
87 }
88 if (gotCR) {
89 if (c == LF) {
90 gotLF = true;
91 } else {
92 gotCR = false;
93 consume (CR);
94 consume (c);
95 }
96 } else {
97 if (c == CR) {
98 gotCR = true;
99 } else {
100 consume (c);
101 }
102 }
103 }
104 lineBuf.append (buf, 0, pos);
105 return new String (lineBuf);
106 }
107
108 private void consume (int c) {
109 if (pos == BUF_LEN) {
110 lineBuf.append (buf);
111 pos = 0;
112 }
113 buf[pos++] = (char)c;
114 }
115
116 /**
117 * returns the request line (first line of a request)
118 */
119 public String requestLine () {
120 return startLine;
121 }
122
123 Headers hdrs = null;
124
125 Headers headers () throws IOException {
126 if (hdrs != null) {
127 return hdrs;
128 }
129 hdrs = new Headers();
130
131 char s[] = new char[10];
132 int len = 0;
133
134 int firstc = is.read();
135
136 // check for empty headers
137 if (firstc == CR || firstc == LF) {
138 int c = is.read();
139 if (c == CR || c == LF) {
140 return hdrs;
141 }
142 s[0] = (char)firstc;
143 len = 1;
144 firstc = c;
145 }
146
147 while (firstc != LF && firstc != CR && firstc >= 0) {
148 int keyend = -1;
149 int c;
150 boolean inKey = firstc > ' ';
151 s[len++] = (char) firstc;
152 parseloop:{
153 while ((c = is.read()) >= 0) {
154 switch (c) {
155 case ':':
156 if (inKey && len > 0)
157 keyend = len;
158 inKey = false;
159 break;
160 case '\t':
161 c = ' ';
162 case ' ':
163 inKey = false;
164 break;
165 case CR:
166 case LF:
167 firstc = is.read();
168 if (c == CR && firstc == LF) {
169 firstc = is.read();
170 if (firstc == CR)
171 firstc = is.read();
172 }
173 if (firstc == LF || firstc == CR || firstc > ' ')
174 break parseloop;
175 /* continuation */
176 c = ' ';
177 break;
178 }
179 if (len >= s.length) {
180 char ns[] = new char[s.length * 2];
181 System.arraycopy(s, 0, ns, 0, len);
182 s = ns;
183 }
184 s[len++] = (char) c;
185 }
186 firstc = -1;
187 }
188 while (len > 0 && s[len - 1] <= ' ')
189 len--;
190 String k;
191 if (keyend <= 0) {
192 k = null;
193 keyend = 0;
194 } else {
195 k = String.copyValueOf(s, 0, keyend);
196 if (keyend < len && s[keyend] == ':')
197 keyend++;
198 while (keyend < len && s[keyend] <= ' ')
199 keyend++;
200 }
201 String v;
202 if (keyend >= len)
203 v = new String();
204 else
205 v = String.copyValueOf(s, keyend, len - keyend);
206 hdrs.add (k,v);
207 len = 0;
208 }
209 return hdrs;
210 }
211
212 /**
213 * Implements blocking reading semantics on top of a non-blocking channel
214 */
215
216 static class ReadStream extends InputStream {
217 SocketChannel channel;
218 ByteBuffer chanbuf;
219 byte[] one;
220 private boolean closed = false, eof = false;
221 ByteBuffer markBuf; /* reads may be satisifed from this buffer */
222 boolean marked;
223 boolean reset;
224 int readlimit;
225 static long readTimeout;
226 ServerImpl server;
227 final static int BUFSIZE = 8 * 1024;
228
229 public ReadStream (ServerImpl server, SocketChannel chan) throws IOException {
230 this.channel = chan;
231 this.server = server;
232 chanbuf = ByteBuffer.allocate (BUFSIZE);
233 chanbuf.clear();
234 one = new byte[1];
235 closed = marked = reset = false;
236 }
237
238 public synchronized int read (byte[] b) throws IOException {
239 return read (b, 0, b.length);
240 }
241
242 public synchronized int read () throws IOException {
243 int result = read (one, 0, 1);
244 if (result == 1) {
245 return one[0] & 0xFF;
246 } else {
247 return -1;
248 }
249 }
250
251 public synchronized int read (byte[] b, int off, int srclen) throws IOException {
252
253 int canreturn, willreturn;
254
255 if (closed)
256 throw new IOException ("Stream closed");
257
258 if (eof) {
259 return -1;
260 }
261
262 assert channel.isBlocking();
263
264 if (off < 0 || srclen < 0|| srclen > (b.length-off)) {
265 throw new IndexOutOfBoundsException ();
266 }
267
268 if (reset) { /* satisfy from markBuf */
269 canreturn = markBuf.remaining ();
270 willreturn = canreturn>srclen ? srclen : canreturn;
271 markBuf.get(b, off, willreturn);
272 if (canreturn == willreturn) {
273 reset = false;
274 }
275 } else { /* satisfy from channel */
276 chanbuf.clear ();
277 if (srclen < BUFSIZE) {
278 chanbuf.limit (srclen);
279 }
280 do {
281 willreturn = channel.read (chanbuf);
282 } while (willreturn == 0);
283 if (willreturn == -1) {
284 eof = true;
285 return -1;
286 }
287 chanbuf.flip ();
288 chanbuf.get(b, off, willreturn);
289
290 if (marked) { /* copy into markBuf */
291 try {
292 markBuf.put (b, off, willreturn);
293 } catch (BufferOverflowException e) {
294 marked = false;
295 }
296 }
297 }
298 return willreturn;
299 }
300
301 public boolean markSupported () {
302 return true;
303 }
304
305 /* Does not query the OS socket */
306 public synchronized int available () throws IOException {
307 if (closed)
308 throw new IOException ("Stream is closed");
309
310 if (eof)
311 return -1;
312
313 if (reset)
314 return markBuf.remaining();
315
316 return chanbuf.remaining();
317 }
318
319 public void close () throws IOException {
320 if (closed) {
321 return;
322 }
323 channel.close ();
324 closed = true;
325 }
326
327 public synchronized void mark (int readlimit) {
328 if (closed)
329 return;
330 this.readlimit = readlimit;
331 markBuf = ByteBuffer.allocate (readlimit);
332 marked = true;
333 reset = false;
334 }
335
336 public synchronized void reset () throws IOException {
337 if (closed )
338 return;
339 if (!marked)
340 throw new IOException ("Stream not marked");
341 marked = false;
342 reset = true;
343 markBuf.flip ();
344 }
345 }
346
347 static class WriteStream extends java.io.OutputStream {
348 SocketChannel channel;
349 ByteBuffer buf;
350 SelectionKey key;
351 boolean closed;
352 byte[] one;
353 ServerImpl server;
354
355 public WriteStream (ServerImpl server, SocketChannel channel) throws IOException {
356 this.channel = channel;
357 this.server = server;
358 assert channel.isBlocking();
359 closed = false;
360 one = new byte [1];
361 buf = ByteBuffer.allocate (4096);
362 }
363
364 public synchronized void write (int b) throws IOException {
365 one[0] = (byte)b;
366 write (one, 0, 1);
367 }
368
369 public synchronized void write (byte[] b) throws IOException {
370 write (b, 0, b.length);
371 }
372
373 public synchronized void write (byte[] b, int off, int len) throws IOException {
374 int l = len;
375 if (closed)
376 throw new IOException ("stream is closed");
377
378 int cap = buf.capacity();
379 if (cap < len) {
380 int diff = len - cap;
381 buf = ByteBuffer.allocate (2*(cap+diff));
382 }
383 buf.clear();
384 buf.put (b, off, len);
385 buf.flip ();
386 int n;
387 while ((n = channel.write (buf)) < l) {
388 l -= n;
389 if (l == 0)
390 return;
391 }
392 }
393
394 public void close () throws IOException {
395 if (closed)
396 return;
397 //server.logStackTrace ("Request.OS.close: isOpen="+channel.isOpen());
398 channel.close ();
399 closed = true;
400 }
401 }
402}
java/pkg/sun/net/httpserver/SSLStreams.java+662−0
@@ -0,0 +1,662 @@
1/*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.net.*;
29import java.nio.*;
30import java.io.*;
31import java.nio.channels.*;
32import java.util.*;
33import java.util.concurrent.*;
34import java.util.concurrent.locks.*;
35import javax.net.ssl.*;
36import javax.net.ssl.SSLEngineResult.*;
37import com.sun.net.httpserver.*;
38import com.sun.net.httpserver.spi.*;
39
40/**
41 * given a non-blocking SocketChannel, it produces
42 * (blocking) streams which encrypt/decrypt the SSL content
43 * and handle the SSL handshaking automatically.
44 */
45
46class SSLStreams {
47
48 SSLContext sslctx;
49 SocketChannel chan;
50 TimeSource time;
51 ServerImpl server;
52 SSLEngine engine;
53 EngineWrapper wrapper;
54 OutputStream os;
55 InputStream is;
56
57 /* held by thread doing the hand-shake on this connection */
58 Lock handshaking = new ReentrantLock();
59
60 SSLStreams (ServerImpl server, SSLContext sslctx, SocketChannel chan) throws IOException {
61 this.server = server;
62 this.time= (TimeSource)server;
63 this.sslctx= sslctx;
64 this.chan= chan;
65 InetSocketAddress addr =
66 (InetSocketAddress)chan.socket().getRemoteSocketAddress();
67 engine = sslctx.createSSLEngine (addr.getHostName(), addr.getPort());
68 engine.setUseClientMode (false);
69 HttpsConfigurator cfg = server.getHttpsConfigurator();
70 configureEngine (cfg, addr);
71 wrapper = new EngineWrapper (chan, engine);
72 }
73
74 private void configureEngine(HttpsConfigurator cfg, InetSocketAddress addr){
75 if (cfg != null) {
76 Parameters params = new Parameters (cfg, addr);
77//BEGIN_TIGER_EXCLUDE
78 cfg.configure (params);
79 SSLParameters sslParams = params.getSSLParameters();
80 if (sslParams != null) {
81 engine.setSSLParameters (sslParams);
82 } else
83//END_TIGER_EXCLUDE
84 {
85 /* tiger compatibility */
86 if (params.getCipherSuites() != null) {
87 try {
88 engine.setEnabledCipherSuites (
89 params.getCipherSuites()
90 );
91 } catch (IllegalArgumentException e) { /* LOG */}
92 }
93 engine.setNeedClientAuth (params.getNeedClientAuth());
94 engine.setWantClientAuth (params.getWantClientAuth());
95 if (params.getProtocols() != null) {
96 try {
97 engine.setEnabledProtocols (
98 params.getProtocols()
99 );
100 } catch (IllegalArgumentException e) { /* LOG */}
101 }
102 }
103 }
104 }
105
106 class Parameters extends HttpsParameters {
107 InetSocketAddress addr;
108 HttpsConfigurator cfg;
109
110 Parameters (HttpsConfigurator cfg, InetSocketAddress addr) {
111 this.addr = addr;
112 this.cfg = cfg;
113 }
114 public InetSocketAddress getClientAddress () {
115 return addr;
116 }
117 public HttpsConfigurator getHttpsConfigurator() {
118 return cfg;
119 }
120//BEGIN_TIGER_EXCLUDE
121 SSLParameters params;
122 public void setSSLParameters (SSLParameters p) {
123 params = p;
124 }
125 SSLParameters getSSLParameters () {
126 return params;
127 }
128//END_TIGER_EXCLUDE
129 }
130
131 /**
132 * cleanup resources allocated inside this object
133 */
134 void close () throws IOException {
135 wrapper.close();
136 }
137
138 /**
139 * return the SSL InputStream
140 */
141 InputStream getInputStream () throws IOException {
142 if (is == null) {
143 is = new InputStream();
144 }
145 return is;
146 }
147
148 /**
149 * return the SSL OutputStream
150 */
151 OutputStream getOutputStream () throws IOException {
152 if (os == null) {
153 os = new OutputStream();
154 }
155 return os;
156 }
157
158 SSLEngine getSSLEngine () {
159 return engine;
160 }
161
162 /**
163 * request the engine to repeat the handshake on this session
164 * the handshake must be driven by reads/writes on the streams
165 * Normally, not necessary to call this.
166 */
167 void beginHandshake() throws SSLException {
168 engine.beginHandshake();
169 }
170
171 class WrapperResult {
172 SSLEngineResult result;
173
174 /* if passed in buffer was not big enough then the
175 * a reallocated buffer is returned here
176 */
177 ByteBuffer buf;
178 }
179
180 int app_buf_size;
181 int packet_buf_size;
182
183 enum BufType {
184 PACKET, APPLICATION
185 };
186
187 private ByteBuffer allocate (BufType type) {
188 return allocate (type, -1);
189 }
190
191 private ByteBuffer allocate (BufType type, int len) {
192 assert engine != null;
193 synchronized (this) {
194 int size;
195 if (type == BufType.PACKET) {
196 if (packet_buf_size == 0) {
197 SSLSession sess = engine.getSession();
198 packet_buf_size = sess.getPacketBufferSize();
199 }
200 if (len > packet_buf_size) {
201 packet_buf_size = len;
202 }
203 size = packet_buf_size;
204 } else {
205 if (app_buf_size == 0) {
206 SSLSession sess = engine.getSession();
207 app_buf_size = sess.getApplicationBufferSize();
208 }
209 if (len > app_buf_size) {
210 app_buf_size = len;
211 }
212 size = app_buf_size;
213 }
214 return ByteBuffer.allocate (size);
215 }
216 }
217
218 /* reallocates the buffer by :-
219 * 1. creating a new buffer double the size of the old one
220 * 2. putting the contents of the old buffer into the new one
221 * 3. set xx_buf_size to the new size if it was smaller than new size
222 *
223 * flip is set to true if the old buffer needs to be flipped
224 * before it is copied.
225 */
226 private ByteBuffer realloc (ByteBuffer b, boolean flip, BufType type) {
227 synchronized (this) {
228 int nsize = 2 * b.capacity();
229 ByteBuffer n = allocate (type, nsize);
230 if (flip) {
231 b.flip();
232 }
233 n.put(b);
234 b = n;
235 }
236 return b;
237 }
238 /**
239 * This is a thin wrapper over SSLEngine and the SocketChannel,
240 * which guarantees the ordering of wraps/unwraps with respect to the underlying
241 * channel read/writes. It handles the UNDER/OVERFLOW status codes
242 * It does not handle the handshaking status codes, or the CLOSED status code
243 * though once the engine is closed, any attempt to read/write to it
244 * will get an exception. The overall result is returned.
245 * It functions synchronously/blocking
246 */
247 class EngineWrapper {
248
249 SocketChannel chan;
250 SSLEngine engine;
251 Object wrapLock, unwrapLock;
252 ByteBuffer unwrap_src, wrap_dst;
253 boolean closed = false;
254 int u_remaining; // the number of bytes left in unwrap_src after an unwrap()
255
256 EngineWrapper (SocketChannel chan, SSLEngine engine) throws IOException {
257 this.chan = chan;
258 this.engine = engine;
259 wrapLock = new Object();
260 unwrapLock = new Object();
261 unwrap_src = allocate(BufType.PACKET);
262 wrap_dst = allocate(BufType.PACKET);
263 }
264
265 void close () throws IOException {
266 }
267
268 /* try to wrap and send the data in src. Handles OVERFLOW.
269 * Might block if there is an outbound blockage or if another
270 * thread is calling wrap(). Also, might not send any data
271 * if an unwrap is needed.
272 */
273 WrapperResult wrapAndSend(ByteBuffer src) throws IOException {
274 return wrapAndSendX(src, false);
275 }
276
277 WrapperResult wrapAndSendX(ByteBuffer src, boolean ignoreClose) throws IOException {
278 if (closed && !ignoreClose) {
279 throw new IOException ("Engine is closed");
280 }
281 Status status;
282 WrapperResult r = new WrapperResult();
283 synchronized (wrapLock) {
284 wrap_dst.clear();
285 do {
286 r.result = engine.wrap (src, wrap_dst);
287 status = r.result.getStatus();
288 if (status == Status.BUFFER_OVERFLOW) {
289 wrap_dst = realloc (wrap_dst, true, BufType.PACKET);
290 }
291 } while (status == Status.BUFFER_OVERFLOW);
292 if (status == Status.CLOSED && !ignoreClose) {
293 closed = true;
294 return r;
295 }
296 if (r.result.bytesProduced() > 0) {
297 wrap_dst.flip();
298 int l = wrap_dst.remaining();
299 assert l == r.result.bytesProduced();
300 while (l>0) {
301 l -= chan.write (wrap_dst);
302 }
303 }
304 }
305 return r;
306 }
307
308 /* block until a complete message is available and return it
309 * in dst, together with the Result. dst may have been re-allocated
310 * so caller should check the returned value in Result
311 * If handshaking is in progress then, possibly no data is returned
312 */
313 WrapperResult recvAndUnwrap(ByteBuffer dst) throws IOException {
314 Status status = Status.OK;
315 WrapperResult r = new WrapperResult();
316 r.buf = dst;
317 if (closed) {
318 throw new IOException ("Engine is closed");
319 }
320 boolean needData;
321 if (u_remaining > 0) {
322 unwrap_src.compact();
323 unwrap_src.flip();
324 needData = false;
325 } else {
326 unwrap_src.clear();
327 needData = true;
328 }
329 synchronized (unwrapLock) {
330 int x;
331 do {
332 if (needData) {
333 do {
334 x = chan.read (unwrap_src);
335 } while (x == 0);
336 if (x == -1) {
337 throw new IOException ("connection closed for reading");
338 }
339 unwrap_src.flip();
340 }
341 r.result = engine.unwrap (unwrap_src, r.buf);
342 status = r.result.getStatus();
343 if (status == Status.BUFFER_UNDERFLOW) {
344 if (unwrap_src.limit() == unwrap_src.capacity()) {
345 /* buffer not big enough */
346 unwrap_src = realloc (
347 unwrap_src, false, BufType.PACKET
348 );
349 } else {
350 /* Buffer not full, just need to read more
351 * data off the channel. Reset pointers
352 * for reading off SocketChannel
353 */
354 unwrap_src.position (unwrap_src.limit());
355 unwrap_src.limit (unwrap_src.capacity());
356 }
357 needData = true;
358 } else if (status == Status.BUFFER_OVERFLOW) {
359 r.buf = realloc (r.buf, true, BufType.APPLICATION);
360 needData = false;
361 } else if (status == Status.CLOSED) {
362 closed = true;
363 r.buf.flip();
364 return r;
365 }
366 } while (status != Status.OK);
367 }
368 u_remaining = unwrap_src.remaining();
369 return r;
370 }
371 }
372
373 /**
374 * send the data in the given ByteBuffer. If a handshake is needed
375 * then this is handled within this method. When this call returns,
376 * all of the given user data has been sent and any handshake has been
377 * completed. Caller should check if engine has been closed.
378 */
379 public WrapperResult sendData (ByteBuffer src) throws IOException {
380 WrapperResult r=null;
381 while (src.remaining() > 0) {
382 r = wrapper.wrapAndSend(src);
383 Status status = r.result.getStatus();
384 if (status == Status.CLOSED) {
385 doClosure ();
386 return r;
387 }
388 HandshakeStatus hs_status = r.result.getHandshakeStatus();
389 if (hs_status != HandshakeStatus.FINISHED &&
390 hs_status != HandshakeStatus.NOT_HANDSHAKING)
391 {
392 doHandshake(hs_status);
393 }
394 }
395 return r;
396 }
397
398 /**
399 * read data thru the engine into the given ByteBuffer. If the
400 * given buffer was not large enough, a new one is allocated
401 * and returned. This call handles handshaking automatically.
402 * Caller should check if engine has been closed.
403 */
404 public WrapperResult recvData (ByteBuffer dst) throws IOException {
405 /* we wait until some user data arrives */
406 WrapperResult r = null;
407 assert dst.position() == 0;
408 while (dst.position() == 0) {
409 r = wrapper.recvAndUnwrap (dst);
410 dst = (r.buf != dst) ? r.buf: dst;
411 Status status = r.result.getStatus();
412 if (status == Status.CLOSED) {
413 doClosure ();
414 return r;
415 }
416
417 HandshakeStatus hs_status = r.result.getHandshakeStatus();
418 if (hs_status != HandshakeStatus.FINISHED &&
419 hs_status != HandshakeStatus.NOT_HANDSHAKING)
420 {
421 doHandshake (hs_status);
422 }
423 }
424 dst.flip();
425 return r;
426 }
427
428 /* we've received a close notify. Need to call wrap to send
429 * the response
430 */
431 void doClosure () throws IOException {
432 try {
433 handshaking.lock();
434 ByteBuffer tmp = allocate(BufType.APPLICATION);
435 WrapperResult r;
436 do {
437 tmp.clear();
438 tmp.flip ();
439 r = wrapper.wrapAndSendX (tmp, true);
440 } while (r.result.getStatus() != Status.CLOSED);
441 } finally {
442 handshaking.unlock();
443 }
444 }
445
446 /* do the (complete) handshake after acquiring the handshake lock.
447 * If two threads call this at the same time, then we depend
448 * on the wrapper methods being idempotent. eg. if wrapAndSend()
449 * is called with no data to send then there must be no problem
450 */
451 void doHandshake (HandshakeStatus hs_status) throws IOException {
452 try {
453 handshaking.lock();
454 ByteBuffer tmp = allocate(BufType.APPLICATION);
455 while (hs_status != HandshakeStatus.FINISHED &&
456 hs_status != HandshakeStatus.NOT_HANDSHAKING)
457 {
458 WrapperResult r = null;
459 switch (hs_status) {
460 case NEED_TASK:
461 Runnable task;
462 while ((task = engine.getDelegatedTask()) != null) {
463 /* run in current thread, because we are already
464 * running an external Executor
465 */
466 task.run();
467 }
468 /* fall thru - call wrap again */
469 case NEED_WRAP:
470 tmp.clear();
471 tmp.flip();
472 r = wrapper.wrapAndSend(tmp);
473 break;
474
475 case NEED_UNWRAP:
476 tmp.clear();
477 r = wrapper.recvAndUnwrap (tmp);
478 if (r.buf != tmp) {
479 tmp = r.buf;
480 }
481 assert tmp.position() == 0;
482 break;
483 }
484 hs_status = r.result.getHandshakeStatus();
485 }
486 } finally {
487 handshaking.unlock();
488 }
489 }
490
491 /**
492 * represents an SSL input stream. Multiple https requests can
493 * be sent over one stream. closing this stream causes an SSL close
494 * input.
495 */
496 class InputStream extends java.io.InputStream {
497
498 ByteBuffer bbuf;
499 boolean closed = false;
500
501 /* this stream eof */
502 boolean eof = false;
503
504 boolean needData = true;
505
506 InputStream () {
507 bbuf = allocate (BufType.APPLICATION);
508 }
509
510 public int read (byte[] buf, int off, int len) throws IOException {
511 if (closed) {
512 throw new IOException ("SSL stream is closed");
513 }
514 if (eof) {
515 return 0;
516 }
517 int available=0;
518 if (!needData) {
519 available = bbuf.remaining();
520 needData = (available==0);
521 }
522 if (needData) {
523 bbuf.clear();
524 WrapperResult r = recvData (bbuf);
525 bbuf = r.buf== bbuf? bbuf: r.buf;
526 if ((available=bbuf.remaining()) == 0) {
527 eof = true;
528 return 0;
529 } else {
530 needData = false;
531 }
532 }
533 /* copy as much as possible from buf into users buf */
534 if (len > available) {
535 len = available;
536 }
537 bbuf.get (buf, off, len);
538 return len;
539 }
540
541 public int available () throws IOException {
542 return bbuf.remaining();
543 }
544
545 public boolean markSupported () {
546 return false; /* not possible with SSLEngine */
547 }
548
549 public void reset () throws IOException {
550 throw new IOException ("mark/reset not supported");
551 }
552
553 public long skip (long s) throws IOException {
554 int n = (int)s;
555 if (closed) {
556 throw new IOException ("SSL stream is closed");
557 }
558 if (eof) {
559 return 0;
560 }
561 int ret = n;
562 while (n > 0) {
563 if (bbuf.remaining() >= n) {
564 bbuf.position (bbuf.position()+n);
565 return ret;
566 } else {
567 n -= bbuf.remaining();
568 bbuf.clear();
569 WrapperResult r = recvData (bbuf);
570 bbuf = r.buf==bbuf? bbuf: r.buf;
571 }
572 }
573 return ret; /* not reached */
574 }
575
576 /**
577 * close the SSL connection. All data must have been consumed
578 * before this is called. Otherwise an exception will be thrown.
579 * [Note. May need to revisit this. not quite the normal close() symantics
580 */
581 public void close () throws IOException {
582 eof = true;
583 engine.closeInbound ();
584 }
585
586 public int read (byte[] buf) throws IOException {
587 return read (buf, 0, buf.length);
588 }
589
590 byte single[] = new byte [1];
591
592 public int read () throws IOException {
593 int n = read (single, 0, 1);
594 if (n == 0) {
595 return -1;
596 } else {
597 return single[0] & 0xFF;
598 }
599 }
600 }
601
602 /**
603 * represents an SSL output stream. plain text data written to this stream
604 * is encrypted by the stream. Multiple HTTPS responses can be sent on
605 * one stream. closing this stream initiates an SSL closure
606 */
607 class OutputStream extends java.io.OutputStream {
608 ByteBuffer buf;
609 boolean closed = false;
610 byte single[] = new byte[1];
611
612 OutputStream() {
613 buf = allocate(BufType.APPLICATION);
614 }
615
616 public void write(int b) throws IOException {
617 single[0] = (byte)b;
618 write (single, 0, 1);
619 }
620
621 public void write(byte b[]) throws IOException {
622 write (b, 0, b.length);
623 }
624 public void write(byte b[], int off, int len) throws IOException {
625 if (closed) {
626 throw new IOException ("output stream is closed");
627 }
628 while (len > 0) {
629 int l = len > buf.capacity() ? buf.capacity() : len;
630 buf.clear();
631 buf.put (b, off, l);
632 len -= l;
633 off += l;
634 buf.flip();
635 WrapperResult r = sendData (buf);
636 if (r.result.getStatus() == Status.CLOSED) {
637 closed = true;
638 if (len > 0) {
639 throw new IOException ("output stream is closed");
640 }
641 }
642 }
643 }
644
645 public void flush() throws IOException {
646 /* no-op */
647 }
648
649 public void close() throws IOException {
650 WrapperResult r=null;
651 engine.closeOutbound();
652 closed = true;
653 HandshakeStatus stat = HandshakeStatus.NEED_WRAP;
654 buf.clear();
655 while (stat == HandshakeStatus.NEED_WRAP) {
656 r = wrapper.wrapAndSend (buf);
657 stat = r.result.getHandshakeStatus();
658 }
659 assert r.result.getStatus() == Status.CLOSED;
660 }
661 }
662}
java/pkg/sun/net/httpserver/ServerConfig.java+175−0
@@ -0,0 +1,175 @@
1/*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import com.sun.net.httpserver.*;
29import com.sun.net.httpserver.spi.*;
30import java.util.logging.Logger;
31import java.security.PrivilegedAction;
32
33/**
34 * Parameters that users will not likely need to set
35 * but are useful for debugging
36 */
37
38class ServerConfig {
39
40 static int clockTick;
41
42 static final int DEFAULT_CLOCK_TICK = 10000 ; // 10 sec.
43
44 /* These values must be a reasonable multiple of clockTick */
45 static final long DEFAULT_IDLE_INTERVAL = 30 ; // 5 min
46 static final int DEFAULT_MAX_IDLE_CONNECTIONS = 200 ;
47
48 static final long DEFAULT_MAX_REQ_TIME = -1; // default: forever
49 static final long DEFAULT_MAX_RSP_TIME = -1; // default: forever
50 static final long DEFAULT_TIMER_MILLIS = 1000;
51
52 static final long DEFAULT_DRAIN_AMOUNT = 64 * 1024;
53
54 static long idleInterval;
55 static long drainAmount; // max # of bytes to drain from an inputstream
56 static int maxIdleConnections;
57
58 // max time a request or response is allowed to take
59 static long maxReqTime;
60 static long maxRspTime;
61 static long timerMillis;
62 static boolean debug = false;
63
64 static {
65
66 idleInterval = ((Long)java.security.AccessController.doPrivileged(
67 new sun.security.action.GetLongAction(
68 "sun.net.httpserver.idleInterval",
69 DEFAULT_IDLE_INTERVAL))).longValue() * 1000;
70
71 clockTick = ((Integer)java.security.AccessController.doPrivileged(
72 new sun.security.action.GetIntegerAction(
73 "sun.net.httpserver.clockTick",
74 DEFAULT_CLOCK_TICK))).intValue();
75
76 maxIdleConnections = ((Integer)java.security.AccessController.doPrivileged(
77 new sun.security.action.GetIntegerAction(
78 "sun.net.httpserver.maxIdleConnections",
79 DEFAULT_MAX_IDLE_CONNECTIONS))).intValue();
80
81 drainAmount = ((Long)java.security.AccessController.doPrivileged(
82 new sun.security.action.GetLongAction(
83 "sun.net.httpserver.drainAmount",
84 DEFAULT_DRAIN_AMOUNT))).longValue();
85
86 maxReqTime = ((Long)java.security.AccessController.doPrivileged(
87 new sun.security.action.GetLongAction(
88 "sun.net.httpserver.maxReqTime",
89 DEFAULT_MAX_REQ_TIME))).longValue();
90
91 maxRspTime = ((Long)java.security.AccessController.doPrivileged(
92 new sun.security.action.GetLongAction(
93 "sun.net.httpserver.maxRspTime",
94 DEFAULT_MAX_RSP_TIME))).longValue();
95
96 timerMillis = ((Long)java.security.AccessController.doPrivileged(
97 new sun.security.action.GetLongAction(
98 "sun.net.httpserver.timerMillis",
99 DEFAULT_TIMER_MILLIS))).longValue();
100
101 debug = ((Boolean)java.security.AccessController.doPrivileged(
102 new sun.security.action.GetBooleanAction(
103 "sun.net.httpserver.debug"))).booleanValue();
104 }
105
106
107 static void checkLegacyProperties (final Logger logger) {
108
109 // legacy properties that are no longer used
110 // print a warning to logger if they are set.
111
112 java.security.AccessController.doPrivileged(
113 new PrivilegedAction<Void>() {
114 public Void run () {
115 if (System.getProperty("sun.net.httpserver.readTimeout")
116 !=null)
117 {
118 logger.warning ("sun.net.httpserver.readTimeout "+
119 "property is no longer used. "+
120 "Use sun.net.httpserver.maxReqTime instead."
121 );
122 }
123 if (System.getProperty("sun.net.httpserver.writeTimeout")
124 !=null)
125 {
126 logger.warning ("sun.net.httpserver.writeTimeout "+
127 "property is no longer used. Use "+
128 "sun.net.httpserver.maxRspTime instead."
129 );
130 }
131 if (System.getProperty("sun.net.httpserver.selCacheTimeout")
132 !=null)
133 {
134 logger.warning ("sun.net.httpserver.selCacheTimeout "+
135 "property is no longer used."
136 );
137 }
138 return null;
139 }
140 }
141 );
142 }
143
144 static boolean debugEnabled () {
145 return debug;
146 }
147
148 static long getIdleInterval () {
149 return idleInterval;
150 }
151
152 static int getClockTick () {
153 return clockTick;
154 }
155
156 static int getMaxIdleConnections () {
157 return maxIdleConnections;
158 }
159
160 static long getDrainAmount () {
161 return drainAmount;
162 }
163
164 static long getMaxReqTime () {
165 return maxReqTime;
166 }
167
168 static long getMaxRspTime () {
169 return maxRspTime;
170 }
171
172 static long getTimerMillis () {
173 return timerMillis;
174 }
175}
java/pkg/sun/net/httpserver/ServerImpl.java+870−0
@@ -0,0 +1,870 @@
1/*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.net.*;
29import java.io.*;
30import java.nio.*;
31import java.security.*;
32import java.nio.channels.*;
33import java.util.*;
34import java.util.concurrent.*;
35import java.util.logging.Logger;
36import java.util.logging.Level;
37import javax.net.ssl.*;
38import com.sun.net.httpserver.*;
39import com.sun.net.httpserver.spi.*;
40import sun.net.httpserver.HttpConnection.State;
41
42/**
43 * Provides implementation for both HTTP and HTTPS
44 */
45class ServerImpl implements TimeSource {
46
47 private String protocol;
48 private boolean https;
49 private Executor executor;
50 private HttpsConfigurator httpsConfig;
51 private SSLContext sslContext;
52 private ContextList contexts;
53 private InetSocketAddress address;
54 private ServerSocketChannel schan;
55 private Selector selector;
56 private SelectionKey listenerKey;
57 private Set<HttpConnection> idleConnections;
58 private Set<HttpConnection> allConnections;
59 /* following two are used to keep track of the times
60 * when a connection/request is first received
61 * and when we start to send the response
62 */
63 private Set<HttpConnection> reqConnections;
64 private Set<HttpConnection> rspConnections;
65 private List<Event> events;
66 private Object lolock = new Object();
67 private volatile boolean finished = false;
68 private volatile boolean terminating = false;
69 private boolean bound = false;
70 private boolean started = false;
71 private volatile long time; /* current time */
72 private volatile long subticks = 0;
73 private volatile long ticks; /* number of clock ticks since server started */
74 private HttpServer wrapper;
75
76 final static int CLOCK_TICK = ServerConfig.getClockTick();
77 final static long IDLE_INTERVAL = ServerConfig.getIdleInterval();
78 final static int MAX_IDLE_CONNECTIONS = ServerConfig.getMaxIdleConnections();
79 final static long TIMER_MILLIS = ServerConfig.getTimerMillis ();
80 final static long MAX_REQ_TIME=getTimeMillis(ServerConfig.getMaxReqTime());
81 final static long MAX_RSP_TIME=getTimeMillis(ServerConfig.getMaxRspTime());
82 final static boolean timer1Enabled = MAX_REQ_TIME != -1 || MAX_RSP_TIME != -1;
83
84 private Timer timer, timer1;
85 private Logger logger;
86
87 ServerImpl (
88 HttpServer wrapper, String protocol, InetSocketAddress addr, int backlog
89 ) throws IOException {
90
91 this.protocol = protocol;
92 this.wrapper = wrapper;
93 this.logger = Logger.getLogger ("com.sun.net.httpserver");
94 ServerConfig.checkLegacyProperties (logger);
95 https = protocol.equalsIgnoreCase ("https");
96 this.address = addr;
97 contexts = new ContextList();
98 schan = ServerSocketChannel.open();
99 if (addr != null) {
100 ServerSocket socket = schan.socket();
101 socket.bind (addr, backlog);
102 bound = true;
103 }
104 selector = Selector.open ();
105 schan.configureBlocking (false);
106 listenerKey = schan.register (selector, SelectionKey.OP_ACCEPT);
107 dispatcher = new Dispatcher();
108 idleConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
109 allConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
110 reqConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
111 rspConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
112 time = System.currentTimeMillis();
113 timer = new Timer ("server-timer", true);
114 timer.schedule (new ServerTimerTask(), CLOCK_TICK, CLOCK_TICK);
115 if (timer1Enabled) {
116 timer1 = new Timer ("server-timer1", true);
117 timer1.schedule (new ServerTimerTask1(),TIMER_MILLIS,TIMER_MILLIS);
118 logger.config ("HttpServer timer1 enabled period in ms: "+TIMER_MILLIS);
119 logger.config ("MAX_REQ_TIME: "+MAX_REQ_TIME);
120 logger.config ("MAX_RSP_TIME: "+MAX_RSP_TIME);
121 }
122 events = new LinkedList<Event>();
123 logger.config ("HttpServer created "+protocol+" "+ addr);
124 }
125
126 public void bind (InetSocketAddress addr, int backlog) throws IOException {
127 if (bound) {
128 throw new BindException ("HttpServer already bound");
129 }
130 if (addr == null) {
131 throw new NullPointerException ("null address");
132 }
133 ServerSocket socket = schan.socket();
134 socket.bind (addr, backlog);
135 bound = true;
136 }
137
138 public void start () {
139 if (!bound || started || finished) {
140 throw new IllegalStateException ("server in wrong state");
141 }
142 if (executor == null) {
143 executor = new DefaultExecutor();
144 }
145 Thread t = new Thread (dispatcher);
146 started = true;
147 t.start();
148 }
149
150 public void setExecutor (Executor executor) {
151 if (started) {
152 throw new IllegalStateException ("server already started");
153 }
154 this.executor = executor;
155 }
156
157 private static class DefaultExecutor implements Executor {
158 public void execute (Runnable task) {
159 task.run();
160 }
161 }
162
163 public Executor getExecutor () {
164 return executor;
165 }
166
167 public void setHttpsConfigurator (HttpsConfigurator config) {
168 if (config == null) {
169 throw new NullPointerException ("null HttpsConfigurator");
170 }
171 if (started) {
172 throw new IllegalStateException ("server already started");
173 }
174 this.httpsConfig = config;
175 sslContext = config.getSSLContext();
176 }
177
178 public HttpsConfigurator getHttpsConfigurator () {
179 return httpsConfig;
180 }
181
182 public void stop (int delay) {
183 if (delay < 0) {
184 throw new IllegalArgumentException ("negative delay parameter");
185 }
186 terminating = true;
187 try { schan.close(); } catch (IOException e) {}
188 selector.wakeup();
189 long latest = System.currentTimeMillis() + delay * 1000;
190 while (System.currentTimeMillis() < latest) {
191 delay();
192 if (finished) {
193 break;
194 }
195 }
196 finished = true;
197 selector.wakeup();
198 synchronized (allConnections) {
199 for (HttpConnection c : allConnections) {
200 c.close();
201 }
202 }
203 allConnections.clear();
204 idleConnections.clear();
205 timer.cancel();
206 if (timer1Enabled) {
207 timer1.cancel();
208 }
209 }
210
211 Dispatcher dispatcher;
212
213 public synchronized HttpContextImpl createContext (String path, HttpHandler handler) {
214 if (handler == null || path == null) {
215 throw new NullPointerException ("null handler, or path parameter");
216 }
217 HttpContextImpl context = new HttpContextImpl (protocol, path, handler, this);
218 contexts.add (context);
219 logger.config ("context created: " + path);
220 return context;
221 }
222
223 public synchronized HttpContextImpl createContext (String path) {
224 if (path == null) {
225 throw new NullPointerException ("null path parameter");
226 }
227 HttpContextImpl context = new HttpContextImpl (protocol, path, null, this);
228 contexts.add (context);
229 logger.config ("context created: " + path);
230 return context;
231 }
232
233 public synchronized void removeContext (String path) throws IllegalArgumentException {
234 if (path == null) {
235 throw new NullPointerException ("null path parameter");
236 }
237 contexts.remove (protocol, path);
238 logger.config ("context removed: " + path);
239 }
240
241 public synchronized void removeContext (HttpContext context) throws IllegalArgumentException {
242 if (!(context instanceof HttpContextImpl)) {
243 throw new IllegalArgumentException ("wrong HttpContext type");
244 }
245 contexts.remove ((HttpContextImpl)context);
246 logger.config ("context removed: " + context.getPath());
247 }
248
249 public InetSocketAddress getAddress() {
250 return (InetSocketAddress)schan.socket().getLocalSocketAddress();
251 }
252
253 Selector getSelector () {
254 return selector;
255 }
256
257 void addEvent (Event r) {
258 synchronized (lolock) {
259 events.add (r);
260 selector.wakeup();
261 }
262 }
263
264 /* main server listener task */
265
266 class Dispatcher implements Runnable {
267
268 private void handleEvent (Event r) {
269 ExchangeImpl t = r.exchange;
270 HttpConnection c = t.getConnection();
271 try {
272 if (r instanceof WriteFinishedEvent) {
273
274 int exchanges = endExchange();
275 if (terminating && exchanges == 0) {
276 finished = true;
277 }
278 responseCompleted (c);
279 LeftOverInputStream is = t.getOriginalInputStream();
280 if (!is.isEOF()) {
281 t.close = true;
282 }
283 if (t.close || idleConnections.size() >= MAX_IDLE_CONNECTIONS) {
284 c.close();
285 allConnections.remove (c);
286 } else {
287 if (is.isDataBuffered()) {
288 /* don't re-enable the interestops, just handle it */
289 requestStarted (c);
290 handle (c.getChannel(), c);
291 } else {
292 connsToRegister.add (c);
293 }
294 }
295 }
296 } catch (IOException e) {
297 logger.log (
298 Level.FINER, "Dispatcher (1)", e
299 );
300 c.close();
301 }
302 }
303
304 final LinkedList<HttpConnection> connsToRegister =
305 new LinkedList<HttpConnection>();
306
307 void reRegister (HttpConnection c) {
308 /* re-register with selector */
309 try {
310 SocketChannel chan = c.getChannel();
311 chan.configureBlocking (false);
312 SelectionKey key = chan.register (selector, SelectionKey.OP_READ);
313 key.attach (c);
314 c.selectionKey = key;
315 c.time = getTime() + IDLE_INTERVAL;
316 idleConnections.add (c);
317 } catch (IOException e) {
318 dprint(e);
319 logger.log(Level.FINER, "Dispatcher(8)", e);
320 c.close();
321 }
322 }
323
324 public void run() {
325 while (!finished) {
326 try {
327 ListIterator<HttpConnection> li =
328 connsToRegister.listIterator();
329 for (HttpConnection c : connsToRegister) {
330 reRegister(c);
331 }
332 connsToRegister.clear();
333
334 List<Event> list = null;
335 selector.select(1000);
336 synchronized (lolock) {
337 if (events.size() > 0) {
338 list = events;
339 events = new LinkedList<Event>();
340 }
341 }
342
343 if (list != null) {
344 for (Event r: list) {
345 handleEvent (r);
346 }
347 }
348
349 /* process the selected list now */
350
351 Set<SelectionKey> selected = selector.selectedKeys();
352 Iterator<SelectionKey> iter = selected.iterator();
353 while (iter.hasNext()) {
354 SelectionKey key = iter.next();
355 iter.remove ();
356 if (key.equals (listenerKey)) {
357 if (terminating) {
358 continue;
359 }
360 SocketChannel chan = schan.accept();
361 if (chan == null) {
362 continue; /* cancel something ? */
363 }
364 chan.configureBlocking (false);
365 SelectionKey newkey = chan.register (selector, SelectionKey.OP_READ);
366 HttpConnection c = new HttpConnection ();
367 c.selectionKey = newkey;
368 c.setChannel (chan);
369 newkey.attach (c);
370 requestStarted (c);
371 allConnections.add (c);
372 } else {
373 try {
374 if (key.isReadable()) {
375 boolean closed;
376 SocketChannel chan = (SocketChannel)key.channel();
377 HttpConnection conn = (HttpConnection)key.attachment();
378
379 key.cancel();
380 chan.configureBlocking (true);
381 if (idleConnections.remove(conn)) {
382 // was an idle connection so add it
383 // to reqConnections set.
384 requestStarted (conn);
385 }
386 handle (chan, conn);
387 } else {
388 assert false;
389 }
390 } catch (CancelledKeyException e) {
391 handleException(key, null);
392 } catch (IOException e) {
393 handleException(key, e);
394 }
395 }
396 }
397 // call the selector just to process the cancelled keys
398 selector.selectNow();
399 } catch (IOException e) {
400 logger.log (Level.FINER, "Dispatcher (4)", e);
401 } catch (Exception e) {
402 e.printStackTrace();
403 logger.log (Level.FINER, "Dispatcher (7)", e);
404 }
405 }
406 }
407
408 private void handleException (SelectionKey key, Exception e) {
409 HttpConnection conn = (HttpConnection)key.attachment();
410 if (e != null) {
411 logger.log (Level.FINER, "Dispatcher (2)", e);
412 }
413 closeConnection(conn);
414 }
415
416 public void handle (SocketChannel chan, HttpConnection conn)
417 throws IOException
418 {
419 try {
420 Exchange t = new Exchange (chan, protocol, conn);
421 executor.execute (t);
422 } catch (HttpError e1) {
423 logger.log (Level.FINER, "Dispatcher (4)", e1);
424 closeConnection(conn);
425 } catch (IOException e) {
426 logger.log (Level.FINER, "Dispatcher (5)", e);
427 closeConnection(conn);
428 }
429 }
430 }
431
432 static boolean debug = ServerConfig.debugEnabled ();
433
434 static synchronized void dprint (String s) {
435 if (debug) {
436 System.out.println (s);
437 }
438 }
439
440 static synchronized void dprint (Exception e) {
441 if (debug) {
442 System.out.println (e);
443 e.printStackTrace();
444 }
445 }
446
447 Logger getLogger () {
448 return logger;
449 }
450
451 private void closeConnection(HttpConnection conn) {
452 conn.close();
453 allConnections.remove(conn);
454 switch (conn.getState()) {
455 case REQUEST:
456 reqConnections.remove(conn);
457 break;
458 case RESPONSE:
459 rspConnections.remove(conn);
460 break;
461 case IDLE:
462 idleConnections.remove(conn);
463 break;
464 }
465 assert !reqConnections.remove(conn);
466 assert !rspConnections.remove(conn);
467 assert !idleConnections.remove(conn);
468 }
469
470 /* per exchange task */
471
472 class Exchange implements Runnable {
473 SocketChannel chan;
474 HttpConnection connection;
475 HttpContextImpl context;
476 InputStream rawin;
477 OutputStream rawout;
478 String protocol;
479 ExchangeImpl tx;
480 HttpContextImpl ctx;
481 boolean rejected = false;
482
483 Exchange (SocketChannel chan, String protocol, HttpConnection conn) throws IOException {
484 this.chan = chan;
485 this.connection = conn;
486 this.protocol = protocol;
487 }
488
489 public void run () {
490 /* context will be null for new connections */
491 context = connection.getHttpContext();
492 boolean newconnection;
493 SSLEngine engine = null;
494 String requestLine = null;
495 SSLStreams sslStreams = null;
496 try {
497 if (context != null ) {
498 this.rawin = connection.getInputStream();
499 this.rawout = connection.getRawOutputStream();
500 newconnection = false;
501 } else {
502 /* figure out what kind of connection this is */
503 newconnection = true;
504 if (https) {
505 if (sslContext == null) {
506 logger.warning ("SSL connection received. No https contxt created");
507 throw new HttpError ("No SSL context established");
508 }
509 sslStreams = new SSLStreams (ServerImpl.this, sslContext, chan);
510 rawin = sslStreams.getInputStream();
511 rawout = sslStreams.getOutputStream();
512 engine = sslStreams.getSSLEngine();
513 connection.sslStreams = sslStreams;
514 } else {
515 rawin = new BufferedInputStream(
516 new Request.ReadStream (
517 ServerImpl.this, chan
518 ));
519 rawout = new Request.WriteStream (
520 ServerImpl.this, chan
521 );
522 }
523 connection.raw = rawin;
524 connection.rawout = rawout;
525 }
526 Request req = new Request (rawin, rawout);
527 requestLine = req.requestLine();
528 if (requestLine == null) {
529 /* connection closed */
530 closeConnection(connection);
531 return;
532 }
533 int space = requestLine.indexOf (' ');
534 if (space == -1) {
535 reject (Code.HTTP_BAD_REQUEST,
536 requestLine, "Bad request line");
537 return;
538 }
539 String method = requestLine.substring (0, space);
540 int start = space+1;
541 space = requestLine.indexOf(' ', start);
542 if (space == -1) {
543 reject (Code.HTTP_BAD_REQUEST,
544 requestLine, "Bad request line");
545 return;
546 }
547 String uriStr = requestLine.substring (start, space);
548 URI uri = new URI (uriStr);
549 start = space+1;
550 String version = requestLine.substring (start);
551 Headers headers = req.headers();
552 String s = headers.getFirst ("Transfer-encoding");
553 long clen = 0L;
554 if (s !=null && s.equalsIgnoreCase ("chunked")) {
555 clen = -1L;
556 } else {
557 s = headers.getFirst ("Content-Length");
558 if (s != null) {
559 clen = Long.parseLong(s);
560 }
561 if (clen == 0) {
562 requestCompleted (connection);
563 }
564 }
565 ctx = contexts.findContext (protocol, uri.getPath());
566 if (ctx == null) {
567 reject (Code.HTTP_NOT_FOUND,
568 requestLine, "No context found for request");
569 return;
570 }
571 connection.setContext (ctx);
572 if (ctx.getHandler() == null) {
573 reject (Code.HTTP_INTERNAL_ERROR,
574 requestLine, "No handler for context");
575 return;
576 }
577 tx = new ExchangeImpl (
578 method, uri, req, clen, connection
579 );
580 String chdr = headers.getFirst("Connection");
581 Headers rheaders = tx.getResponseHeaders();
582
583 if (chdr != null && chdr.equalsIgnoreCase ("close")) {
584 tx.close = true;
585 }
586 if (version.equalsIgnoreCase ("http/1.0")) {
587 tx.http10 = true;
588 if (chdr == null) {
589 tx.close = true;
590 rheaders.set ("Connection", "close");
591 } else if (chdr.equalsIgnoreCase ("keep-alive")) {
592 rheaders.set ("Connection", "keep-alive");
593 int idle=(int)ServerConfig.getIdleInterval()/1000;
594 int max=(int)ServerConfig.getMaxIdleConnections();
595 String val = "timeout="+idle+", max="+max;
596 rheaders.set ("Keep-Alive", val);
597 }
598 }
599
600 if (newconnection) {
601 connection.setParameters (
602 rawin, rawout, chan, engine, sslStreams,
603 sslContext, protocol, ctx, rawin
604 );
605 }
606 /* check if client sent an Expect 100 Continue.
607 * In that case, need to send an interim response.
608 * In future API may be modified to allow app to
609 * be involved in this process.
610 */
611 String exp = headers.getFirst("Expect");
612 if (exp != null && exp.equalsIgnoreCase ("100-continue")) {
613 logReply (100, requestLine, null);
614 sendReply (
615 Code.HTTP_CONTINUE, false, null
616 );
617 }
618 /* uf is the list of filters seen/set by the user.
619 * sf is the list of filters established internally
620 * and which are not visible to the user. uc and sc
621 * are the corresponding Filter.Chains.
622 * They are linked together by a LinkHandler
623 * so that they can both be invoked in one call.
624 */
625 List<Filter> sf = ctx.getSystemFilters();
626 List<Filter> uf = ctx.getFilters();
627
628 Filter.Chain sc = new Filter.Chain(sf, ctx.getHandler());
629 Filter.Chain uc = new Filter.Chain(uf, new LinkHandler (sc));
630
631 /* set up the two stream references */
632 tx.getRequestBody();
633 tx.getResponseBody();
634 if (https) {
635 uc.doFilter (new HttpsExchangeImpl (tx));
636 } else {
637 uc.doFilter (new HttpExchangeImpl (tx));
638 }
639
640 } catch (IOException e1) {
641 logger.log (Level.FINER, "ServerImpl.Exchange (1)", e1);
642 closeConnection(connection);
643 } catch (NumberFormatException e3) {
644 reject (Code.HTTP_BAD_REQUEST,
645 requestLine, "NumberFormatException thrown");
646 } catch (URISyntaxException e) {
647 reject (Code.HTTP_BAD_REQUEST,
648 requestLine, "URISyntaxException thrown");
649 } catch (Exception e4) {
650 logger.log (Level.FINER, "ServerImpl.Exchange (2)", e4);
651 closeConnection(connection);
652 }
653 }
654
655 /* used to link to 2 or more Filter.Chains together */
656
657 class LinkHandler implements HttpHandler {
658 Filter.Chain nextChain;
659
660 LinkHandler (Filter.Chain nextChain) {
661 this.nextChain = nextChain;
662 }
663
664 public void handle (HttpExchange exchange) throws IOException {
665 nextChain.doFilter (exchange);
666 }
667 }
668
669 void reject (int code, String requestStr, String message) {
670 rejected = true;
671 logReply (code, requestStr, message);
672 sendReply (
673 code, false, "<h1>"+code+Code.msg(code)+"</h1>"+message
674 );
675 closeConnection(connection);
676 }
677
678 void sendReply (
679 int code, boolean closeNow, String text)
680 {
681 try {
682 StringBuilder builder = new StringBuilder (512);
683 builder.append ("HTTP/1.1 ")
684 .append (code).append (Code.msg(code)).append ("\r\n");
685
686 if (text != null && text.length() != 0) {
687 builder.append ("Content-Length: ")
688 .append (text.length()).append ("\r\n")
689 .append ("Content-Type: text/html\r\n");
690 } else {
691 builder.append ("Content-Length: 0\r\n");
692 text = "";
693 }
694 if (closeNow) {
695 builder.append ("Connection: close\r\n");
696 }
697 builder.append ("\r\n").append (text);
698 String s = builder.toString();
699 byte[] b = s.getBytes("ISO8859_1");
700 rawout.write (b);
701 rawout.flush();
702 if (closeNow) {
703 closeConnection(connection);
704 }
705 } catch (IOException e) {
706 logger.log (Level.FINER, "ServerImpl.sendReply", e);
707 closeConnection(connection);
708 }
709 }
710
711 }
712
713 void logReply (int code, String requestStr, String text) {
714 if (!logger.isLoggable(Level.FINE)) {
715 return;
716 }
717 if (text == null) {
718 text = "";
719 }
720 String r;
721 if (requestStr.length() > 80) {
722 r = requestStr.substring (0, 80) + "<TRUNCATED>";
723 } else {
724 r = requestStr;
725 }
726 String message = r + " [" + code + " " +
727 Code.msg(code) + "] ("+text+")";
728 logger.fine (message);
729 }
730
731 long getTicks() {
732 return ticks;
733 }
734
735 public long getTime() {
736 return time;
737 }
738
739 void delay () {
740 Thread.yield();
741 try {
742 Thread.sleep (200);
743 } catch (InterruptedException e) {}
744 }
745
746 private int exchangeCount = 0;
747
748 synchronized void startExchange () {
749 exchangeCount ++;
750 }
751
752 synchronized int endExchange () {
753 exchangeCount --;
754 assert exchangeCount >= 0;
755 return exchangeCount;
756 }
757
758 HttpServer getWrapper () {
759 return wrapper;
760 }
761
762 void requestStarted (HttpConnection c) {
763 c.creationTime = getTime();
764 c.setState (State.REQUEST);
765 reqConnections.add (c);
766 }
767
768 // called after a request has been completely read
769 // by the server. This stops the timer which would
770 // close the connection if the request doesn't arrive
771 // quickly enough. It then starts the timer
772 // that ensures the client reads the response in a timely
773 // fashion.
774
775 void requestCompleted (HttpConnection c) {
776 assert c.getState() == State.REQUEST;
777 reqConnections.remove (c);
778 c.rspStartedTime = getTime();
779 rspConnections.add (c);
780 c.setState (State.RESPONSE);
781 }
782
783 // called after response has been sent
784 void responseCompleted (HttpConnection c) {
785 assert c.getState() == State.RESPONSE;
786 rspConnections.remove (c);
787 c.setState (State.IDLE);
788 }
789
790 /**
791 * TimerTask run every CLOCK_TICK ms
792 */
793 class ServerTimerTask extends TimerTask {
794 public void run () {
795 LinkedList<HttpConnection> toClose = new LinkedList<HttpConnection>();
796 time = System.currentTimeMillis();
797 ticks ++;
798 synchronized (idleConnections) {
799 for (HttpConnection c : idleConnections) {
800 if (c.time <= time) {
801 toClose.add (c);
802 }
803 }
804 for (HttpConnection c : toClose) {
805 idleConnections.remove (c);
806 allConnections.remove (c);
807 c.close();
808 }
809 }
810 }
811 }
812
813 class ServerTimerTask1 extends TimerTask {
814
815 // runs every TIMER_MILLIS
816 public void run () {
817 LinkedList<HttpConnection> toClose = new LinkedList<HttpConnection>();
818 time = System.currentTimeMillis();
819 synchronized (reqConnections) {
820 if (MAX_REQ_TIME != -1) {
821 for (HttpConnection c : reqConnections) {
822 if (c.creationTime + TIMER_MILLIS + MAX_REQ_TIME <= time) {
823 toClose.add (c);
824 }
825 }
826 for (HttpConnection c : toClose) {
827 logger.log (Level.FINE, "closing: no request: " + c);
828 reqConnections.remove (c);
829 allConnections.remove (c);
830 c.close();
831 }
832 }
833 }
834 toClose = new LinkedList<HttpConnection>();
835 synchronized (rspConnections) {
836 if (MAX_RSP_TIME != -1) {
837 for (HttpConnection c : rspConnections) {
838 if (c.rspStartedTime + TIMER_MILLIS +MAX_RSP_TIME <= time) {
839 toClose.add (c);
840 }
841 }
842 for (HttpConnection c : toClose) {
843 logger.log (Level.FINE, "closing: no response: " + c);
844 rspConnections.remove (c);
845 allConnections.remove (c);
846 c.close();
847 }
848 }
849 }
850 }
851 }
852
853 void logStackTrace (String s) {
854 logger.finest (s);
855 StringBuilder b = new StringBuilder ();
856 StackTraceElement[] e = Thread.currentThread().getStackTrace();
857 for (int i=0; i<e.length; i++) {
858 b.append (e[i].toString()).append("\n");
859 }
860 logger.finest (b.toString());
861 }
862
863 static long getTimeMillis(long secs) {
864 if (secs == -1) {
865 return -1;
866 } else {
867 return secs * 1000;
868 }
869 }
870}
java/pkg/sun/net/httpserver/StreamClosedException.java+32−0
@@ -0,0 +1,32 @@
1/*
2 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29
30class StreamClosedException extends IOException {
31 private static final long serialVersionUID = -4485921499356327937L;
32}
java/pkg/sun/net/httpserver/TimeSource.java+30−0
@@ -0,0 +1,30 @@
1/*
2 * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28interface TimeSource {
29 public long getTime();
30}
java/pkg/sun/net/httpserver/UndefLengthOutputStream.java+81−0
@@ -0,0 +1,81 @@
1/*
2 * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import java.net.*;
30import com.sun.net.httpserver.*;
31import com.sun.net.httpserver.spi.*;
32
33/**
34 * a class which allows the caller to write an indefinite
35 * number of bytes to an underlying stream , but without using
36 * chunked encoding. Used for http/1.0 clients only
37 * The underlying connection needs to be closed afterwards.
38 */
39
40class UndefLengthOutputStream extends FilterOutputStream
41{
42 private boolean closed = false;
43 ExchangeImpl t;
44
45 UndefLengthOutputStream (ExchangeImpl t, OutputStream src) {
46 super (src);
47 this.t = t;
48 }
49
50 public void write (int b) throws IOException {
51 if (closed) {
52 throw new IOException ("stream closed");
53 }
54 out.write(b);
55 }
56
57 public void write (byte[]b, int off, int len) throws IOException {
58 if (closed) {
59 throw new IOException ("stream closed");
60 }
61 out.write(b, off, len);
62 }
63
64 public void close () throws IOException {
65 if (closed) {
66 return;
67 }
68 closed = true;
69 flush();
70 LeftOverInputStream is = t.getOriginalInputStream();
71 if (!is.isClosed()) {
72 try {
73 is.close();
74 } catch (IOException e) {}
75 }
76 WriteFinishedEvent e = new WriteFinishedEvent (t);
77 t.getHttpContext().getServerImpl().addEvent (e);
78 }
79
80 // flush is a pass-through
81}
java/pkg/sun/net/httpserver/UnmodifiableHeaders.java+101−0
@@ -0,0 +1,101 @@
1/*
2 * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.util.*;
29import com.sun.net.httpserver.*;
30
31class UnmodifiableHeaders extends Headers {
32
33 Headers map;
34
35 UnmodifiableHeaders(Headers map) {
36 this.map = map;
37 }
38
39 public int size() {return map.size();}
40
41 public boolean isEmpty() {return map.isEmpty();}
42
43 public boolean containsKey(Object key) {
44 return map.containsKey (key);
45 }
46
47 public boolean containsValue(Object value) {
48 return map.containsValue(value);
49 }
50
51 public List<String> get(Object key) {
52 return map.get(key);
53 }
54
55 public String getFirst (String key) {
56 return map.getFirst(key);
57 }
58
59
60 public List<String> put(String key, List<String> value) {
61 return map.put (key, value);
62 }
63
64 public void add (String key, String value) {
65 throw new UnsupportedOperationException ("unsupported operation");
66 }
67
68 public void set (String key, String value) {
69 throw new UnsupportedOperationException ("unsupported operation");
70 }
71
72 public List<String> remove(Object key) {
73 throw new UnsupportedOperationException ("unsupported operation");
74 }
75
76 public void putAll(Map<? extends String,? extends List<String>> t) {
77 throw new UnsupportedOperationException ("unsupported operation");
78 }
79
80 public void clear() {
81 throw new UnsupportedOperationException ("unsupported operation");
82 }
83
84 public Set<String> keySet() {
85 return Collections.unmodifiableSet (map.keySet());
86 }
87
88 public Collection<List<String>> values() {
89 return Collections.unmodifiableCollection(map.values());
90 }
91
92 /* TODO check that contents of set are not modifable : security */
93
94 public Set<Map.Entry<String, List<String>>> entrySet() {
95 return Collections.unmodifiableSet (map.entrySet());
96 }
97
98 public boolean equals(Object o) {return map.equals(o);}
99
100 public int hashCode() {return map.hashCode();}
101 }
java/pkg/sun/net/httpserver/mkfile+33−0
@@ -0,0 +1,33 @@
1<../../../../../mkconfig
2
3TARG=\
4 AuthFilter.dis\
5 ChunkedInputStream.dis\
6 ChunkedOutputStream.dis\
7 Code.dis\
8 ContextList.dis\
9 DefaultHttpServerProvider.dis\
10 Event.dis\
11 ExchangeImpl.dis\
12 FixedLengthInputStream.dis\
13 FixedLengthOutputStream.dis\
14 HttpConnection.dis\
15 HttpContextImpl.dis\
16 HttpError.dis\
17 HttpExchangeImpl.dis\
18 HttpServerImpl.dis\
19 HttpsExchangeImpl.dis\
20 HttpsServerImpl.dis\
21 LeftOverInputStream.dis\
22 Request.dis\
23 ServerConfig.dis\
24 ServerImpl.dis\
25 SSLStreams.dis\
26 StreamClosedException.dis\
27 TimeSource.dis\
28 UndefLengthOutputStream.dis\
29 UnmodifiableHeaders.dis\
30
31DISBIN=$ROOT/java/dis/java/java/sun/net/httpserver
32
33<$ROOT/mkfiles/mkjava