1.1 --- a/rt/emul/compact/src/main/java/java/net/URLConnection.java Thu Oct 31 10:50:19 2013 +0100
1.2 +++ b/rt/emul/compact/src/main/java/java/net/URLConnection.java Thu Oct 31 11:23:54 2013 +0100
1.3 @@ -28,16 +28,17 @@
1.4 import java.io.IOException;
1.5 import java.io.InputStream;
1.6 import java.io.OutputStream;
1.7 -import java.util.Hashtable;
1.8 +import java.io.PrintStream;
1.9 +import java.util.ArrayList;
1.10 import java.util.Date;
1.11 import java.util.StringTokenizer;
1.12 import java.util.Collections;
1.13 +import java.util.HashMap;
1.14 +import java.util.Hashtable;
1.15 +import java.util.Iterator;
1.16 import java.util.Map;
1.17 import java.util.List;
1.18 -import java.security.Permission;
1.19 -import java.security.AccessController;
1.20 -import sun.security.util.SecurityConstants;
1.21 -import sun.net.www.MessageHeader;
1.22 +import java.util.NoSuchElementException;
1.23
1.24 /**
1.25 * The abstract class <code>URLConnection</code> is the superclass
1.26 @@ -314,7 +315,12 @@
1.27 */
1.28 public static synchronized FileNameMap getFileNameMap() {
1.29 if ((fileNameMap == null) && !fileNameMapLoaded) {
1.30 - fileNameMap = sun.net.www.MimeTable.loadTable();
1.31 + fileNameMap = new FileNameMap() {
1.32 + @Override
1.33 + public String getContentTypeFor(String fileName) {
1.34 + return "text/plain";
1.35 + }
1.36 + };
1.37 fileNameMapLoaded = true;
1.38 }
1.39
1.40 @@ -342,9 +348,7 @@
1.41 * @since 1.2
1.42 */
1.43 public static void setFileNameMap(FileNameMap map) {
1.44 - SecurityManager sm = System.getSecurityManager();
1.45 - if (sm != null) sm.checkSetFactory();
1.46 - fileNameMap = map;
1.47 + throw new SecurityException();
1.48 }
1.49
1.50 /**
1.51 @@ -816,9 +820,9 @@
1.52 * requires network or file I/O and an exception occurs while
1.53 * computing it.
1.54 */
1.55 - public Permission getPermission() throws IOException {
1.56 - return SecurityConstants.ALL_PERMISSION;
1.57 - }
1.58 +// public Permission getPermission() throws IOException {
1.59 +// return SecurityConstants.ALL_PERMISSION;
1.60 +// }
1.61
1.62 /**
1.63 * Returns an input stream that reads from this open connection.
1.64 @@ -1226,14 +1230,7 @@
1.65 * @see SecurityManager#checkSetFactory
1.66 */
1.67 public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
1.68 - if (factory != null) {
1.69 - throw new Error("factory already defined");
1.70 - }
1.71 - SecurityManager security = System.getSecurityManager();
1.72 - if (security != null) {
1.73 - security.checkSetFactory();
1.74 - }
1.75 - factory = fac;
1.76 + throw new SecurityException();
1.77 }
1.78
1.79 private static Hashtable handlers = new Hashtable();
1.80 @@ -1370,9 +1367,8 @@
1.81 * the last one on the returned package list.
1.82 */
1.83 private String getContentHandlerPkgPrefixes() {
1.84 - String packagePrefixList = AccessController.doPrivileged(
1.85 - new sun.security.action.GetPropertyAction(contentPathProp, ""));
1.86 -
1.87 + String packagePrefixList = "";
1.88 +
1.89 if (packagePrefixList != "") {
1.90 packagePrefixList += "|";
1.91 }
1.92 @@ -1795,3 +1791,524 @@
1.93 return uc.getInputStream();
1.94 }
1.95 }
1.96 +
1.97 +/** An RFC 844 or MIME message header. Includes methods
1.98 + for parsing headers from incoming streams, fetching
1.99 + values, setting values, and printing headers.
1.100 + Key values of null are legal: they indicate lines in
1.101 + the header that don't have a valid key, but do have
1.102 + a value (this isn't legal according to the standard,
1.103 + but lines like this are everywhere). */
1.104 +class MessageHeader {
1.105 + private String keys[];
1.106 + private String values[];
1.107 + private int nkeys;
1.108 +
1.109 + public MessageHeader () {
1.110 + grow();
1.111 + }
1.112 +
1.113 + public MessageHeader (InputStream is) throws java.io.IOException {
1.114 + parseHeader(is);
1.115 + }
1.116 +
1.117 + /**
1.118 + * Reset a message header (all key/values removed)
1.119 + */
1.120 + public synchronized void reset() {
1.121 + keys = null;
1.122 + values = null;
1.123 + nkeys = 0;
1.124 + grow();
1.125 + }
1.126 +
1.127 + /**
1.128 + * Find the value that corresponds to this key.
1.129 + * It finds only the first occurrence of the key.
1.130 + * @param k the key to find.
1.131 + * @return null if not found.
1.132 + */
1.133 + public synchronized String findValue(String k) {
1.134 + if (k == null) {
1.135 + for (int i = nkeys; --i >= 0;)
1.136 + if (keys[i] == null)
1.137 + return values[i];
1.138 + } else
1.139 + for (int i = nkeys; --i >= 0;) {
1.140 + if (k.equalsIgnoreCase(keys[i]))
1.141 + return values[i];
1.142 + }
1.143 + return null;
1.144 + }
1.145 +
1.146 + // return the location of the key
1.147 + public synchronized int getKey(String k) {
1.148 + for (int i = nkeys; --i >= 0;)
1.149 + if ((keys[i] == k) ||
1.150 + (k != null && k.equalsIgnoreCase(keys[i])))
1.151 + return i;
1.152 + return -1;
1.153 + }
1.154 +
1.155 + public synchronized String getKey(int n) {
1.156 + if (n < 0 || n >= nkeys) return null;
1.157 + return keys[n];
1.158 + }
1.159 +
1.160 + public synchronized String getValue(int n) {
1.161 + if (n < 0 || n >= nkeys) return null;
1.162 + return values[n];
1.163 + }
1.164 +
1.165 + /** Deprecated: Use multiValueIterator() instead.
1.166 + *
1.167 + * Find the next value that corresponds to this key.
1.168 + * It finds the first value that follows v. To iterate
1.169 + * over all the values of a key use:
1.170 + * <pre>
1.171 + * for(String v=h.findValue(k); v!=null; v=h.findNextValue(k, v)) {
1.172 + * ...
1.173 + * }
1.174 + * </pre>
1.175 + */
1.176 + public synchronized String findNextValue(String k, String v) {
1.177 + boolean foundV = false;
1.178 + if (k == null) {
1.179 + for (int i = nkeys; --i >= 0;)
1.180 + if (keys[i] == null)
1.181 + if (foundV)
1.182 + return values[i];
1.183 + else if (values[i] == v)
1.184 + foundV = true;
1.185 + } else
1.186 + for (int i = nkeys; --i >= 0;)
1.187 + if (k.equalsIgnoreCase(keys[i]))
1.188 + if (foundV)
1.189 + return values[i];
1.190 + else if (values[i] == v)
1.191 + foundV = true;
1.192 + return null;
1.193 + }
1.194 +
1.195 + class HeaderIterator implements Iterator<String> {
1.196 + int index = 0;
1.197 + int next = -1;
1.198 + String key;
1.199 + boolean haveNext = false;
1.200 + Object lock;
1.201 +
1.202 + public HeaderIterator (String k, Object lock) {
1.203 + key = k;
1.204 + this.lock = lock;
1.205 + }
1.206 + public boolean hasNext () {
1.207 + synchronized (lock) {
1.208 + if (haveNext) {
1.209 + return true;
1.210 + }
1.211 + while (index < nkeys) {
1.212 + if (key.equalsIgnoreCase (keys[index])) {
1.213 + haveNext = true;
1.214 + next = index++;
1.215 + return true;
1.216 + }
1.217 + index ++;
1.218 + }
1.219 + return false;
1.220 + }
1.221 + }
1.222 + public String next() {
1.223 + synchronized (lock) {
1.224 + if (haveNext) {
1.225 + haveNext = false;
1.226 + return values [next];
1.227 + }
1.228 + if (hasNext()) {
1.229 + return next();
1.230 + } else {
1.231 + throw new NoSuchElementException ("No more elements");
1.232 + }
1.233 + }
1.234 + }
1.235 + public void remove () {
1.236 + throw new UnsupportedOperationException ("remove not allowed");
1.237 + }
1.238 + }
1.239 +
1.240 + /**
1.241 + * return an Iterator that returns all values of a particular
1.242 + * key in sequence
1.243 + */
1.244 + public Iterator<String> multiValueIterator (String k) {
1.245 + return new HeaderIterator (k, this);
1.246 + }
1.247 +
1.248 + public synchronized Map<String, List<String>> getHeaders() {
1.249 + return getHeaders(null);
1.250 + }
1.251 +
1.252 + public synchronized Map<String, List<String>> getHeaders(String[] excludeList) {
1.253 + return filterAndAddHeaders(excludeList, null);
1.254 + }
1.255 +
1.256 + public synchronized Map<String, List<String>> filterAndAddHeaders(String[] excludeList, Map<String, List<String>> include) {
1.257 + boolean skipIt = false;
1.258 + Map<String, List<String>> m = new HashMap<String, List<String>>();
1.259 + for (int i = nkeys; --i >= 0;) {
1.260 + if (excludeList != null) {
1.261 + // check if the key is in the excludeList.
1.262 + // if so, don't include it in the Map.
1.263 + for (int j = 0; j < excludeList.length; j++) {
1.264 + if ((excludeList[j] != null) &&
1.265 + (excludeList[j].equalsIgnoreCase(keys[i]))) {
1.266 + skipIt = true;
1.267 + break;
1.268 + }
1.269 + }
1.270 + }
1.271 + if (!skipIt) {
1.272 + List<String> l = m.get(keys[i]);
1.273 + if (l == null) {
1.274 + l = new ArrayList<String>();
1.275 + m.put(keys[i], l);
1.276 + }
1.277 + l.add(values[i]);
1.278 + } else {
1.279 + // reset the flag
1.280 + skipIt = false;
1.281 + }
1.282 + }
1.283 +
1.284 + if (include != null) {
1.285 + Iterator entries = include.entrySet().iterator();
1.286 + while (entries.hasNext()) {
1.287 + Map.Entry entry = (Map.Entry)entries.next();
1.288 + List l = (List)m.get(entry.getKey());
1.289 + if (l == null) {
1.290 + l = new ArrayList();
1.291 + m.put((String)entry.getKey(), l);
1.292 + }
1.293 + l.add(entry.getValue());
1.294 + }
1.295 + }
1.296 +
1.297 + for (String key : m.keySet()) {
1.298 + m.put(key, Collections.unmodifiableList(m.get(key)));
1.299 + }
1.300 +
1.301 + return Collections.unmodifiableMap(m);
1.302 + }
1.303 +
1.304 + /** Prints the key-value pairs represented by this
1.305 + header. Also prints the RFC required blank line
1.306 + at the end. Omits pairs with a null key. */
1.307 + public synchronized void print(PrintStream p) {
1.308 + for (int i = 0; i < nkeys; i++)
1.309 + if (keys[i] != null) {
1.310 + p.print(keys[i] +
1.311 + (values[i] != null ? ": "+values[i]: "") + "\r\n");
1.312 + }
1.313 + p.print("\r\n");
1.314 + p.flush();
1.315 + }
1.316 +
1.317 + /** Adds a key value pair to the end of the
1.318 + header. Duplicates are allowed */
1.319 + public synchronized void add(String k, String v) {
1.320 + grow();
1.321 + keys[nkeys] = k;
1.322 + values[nkeys] = v;
1.323 + nkeys++;
1.324 + }
1.325 +
1.326 + /** Prepends a key value pair to the beginning of the
1.327 + header. Duplicates are allowed */
1.328 + public synchronized void prepend(String k, String v) {
1.329 + grow();
1.330 + for (int i = nkeys; i > 0; i--) {
1.331 + keys[i] = keys[i-1];
1.332 + values[i] = values[i-1];
1.333 + }
1.334 + keys[0] = k;
1.335 + values[0] = v;
1.336 + nkeys++;
1.337 + }
1.338 +
1.339 + /** Overwrite the previous key/val pair at location 'i'
1.340 + * with the new k/v. If the index didn't exist before
1.341 + * the key/val is simply tacked onto the end.
1.342 + */
1.343 +
1.344 + public synchronized void set(int i, String k, String v) {
1.345 + grow();
1.346 + if (i < 0) {
1.347 + return;
1.348 + } else if (i >= nkeys) {
1.349 + add(k, v);
1.350 + } else {
1.351 + keys[i] = k;
1.352 + values[i] = v;
1.353 + }
1.354 + }
1.355 +
1.356 +
1.357 + /** grow the key/value arrays as needed */
1.358 +
1.359 + private void grow() {
1.360 + if (keys == null || nkeys >= keys.length) {
1.361 + String[] nk = new String[nkeys + 4];
1.362 + String[] nv = new String[nkeys + 4];
1.363 + if (keys != null)
1.364 + System.arraycopy(keys, 0, nk, 0, nkeys);
1.365 + if (values != null)
1.366 + System.arraycopy(values, 0, nv, 0, nkeys);
1.367 + keys = nk;
1.368 + values = nv;
1.369 + }
1.370 + }
1.371 +
1.372 + /**
1.373 + * Remove the key from the header. If there are multiple values under
1.374 + * the same key, they are all removed.
1.375 + * Nothing is done if the key doesn't exist.
1.376 + * After a remove, the other pairs' order are not changed.
1.377 + * @param k the key to remove
1.378 + */
1.379 + public synchronized void remove(String k) {
1.380 + if(k == null) {
1.381 + for (int i = 0; i < nkeys; i++) {
1.382 + while (keys[i] == null && i < nkeys) {
1.383 + for(int j=i; j<nkeys-1; j++) {
1.384 + keys[j] = keys[j+1];
1.385 + values[j] = values[j+1];
1.386 + }
1.387 + nkeys--;
1.388 + }
1.389 + }
1.390 + } else {
1.391 + for (int i = 0; i < nkeys; i++) {
1.392 + while (k.equalsIgnoreCase(keys[i]) && i < nkeys) {
1.393 + for(int j=i; j<nkeys-1; j++) {
1.394 + keys[j] = keys[j+1];
1.395 + values[j] = values[j+1];
1.396 + }
1.397 + nkeys--;
1.398 + }
1.399 + }
1.400 + }
1.401 + }
1.402 +
1.403 + /** Sets the value of a key. If the key already
1.404 + exists in the header, it's value will be
1.405 + changed. Otherwise a new key/value pair will
1.406 + be added to the end of the header. */
1.407 + public synchronized void set(String k, String v) {
1.408 + for (int i = nkeys; --i >= 0;)
1.409 + if (k.equalsIgnoreCase(keys[i])) {
1.410 + values[i] = v;
1.411 + return;
1.412 + }
1.413 + add(k, v);
1.414 + }
1.415 +
1.416 + /** Set's the value of a key only if there is no
1.417 + * key with that value already.
1.418 + */
1.419 +
1.420 + public synchronized void setIfNotSet(String k, String v) {
1.421 + if (findValue(k) == null) {
1.422 + add(k, v);
1.423 + }
1.424 + }
1.425 +
1.426 + /** Convert a message-id string to canonical form (strips off
1.427 + leading and trailing <>s) */
1.428 + public static String canonicalID(String id) {
1.429 + if (id == null)
1.430 + return "";
1.431 + int st = 0;
1.432 + int len = id.length();
1.433 + boolean substr = false;
1.434 + int c;
1.435 + while (st < len && ((c = id.charAt(st)) == '<' ||
1.436 + c <= ' ')) {
1.437 + st++;
1.438 + substr = true;
1.439 + }
1.440 + while (st < len && ((c = id.charAt(len - 1)) == '>' ||
1.441 + c <= ' ')) {
1.442 + len--;
1.443 + substr = true;
1.444 + }
1.445 + return substr ? id.substring(st, len) : id;
1.446 + }
1.447 +
1.448 + /** Parse a MIME header from an input stream. */
1.449 + public void parseHeader(InputStream is) throws java.io.IOException {
1.450 + synchronized (this) {
1.451 + nkeys = 0;
1.452 + }
1.453 + mergeHeader(is);
1.454 + }
1.455 +
1.456 + /** Parse and merge a MIME header from an input stream. */
1.457 + public void mergeHeader(InputStream is) throws java.io.IOException {
1.458 + if (is == null)
1.459 + return;
1.460 + char s[] = new char[10];
1.461 + int firstc = is.read();
1.462 + while (firstc != '\n' && firstc != '\r' && firstc >= 0) {
1.463 + int len = 0;
1.464 + int keyend = -1;
1.465 + int c;
1.466 + boolean inKey = firstc > ' ';
1.467 + s[len++] = (char) firstc;
1.468 + parseloop:{
1.469 + while ((c = is.read()) >= 0) {
1.470 + switch (c) {
1.471 + case ':':
1.472 + if (inKey && len > 0)
1.473 + keyend = len;
1.474 + inKey = false;
1.475 + break;
1.476 + case '\t':
1.477 + c = ' ';
1.478 + case ' ':
1.479 + inKey = false;
1.480 + break;
1.481 + case '\r':
1.482 + case '\n':
1.483 + firstc = is.read();
1.484 + if (c == '\r' && firstc == '\n') {
1.485 + firstc = is.read();
1.486 + if (firstc == '\r')
1.487 + firstc = is.read();
1.488 + }
1.489 + if (firstc == '\n' || firstc == '\r' || firstc > ' ')
1.490 + break parseloop;
1.491 + /* continuation */
1.492 + c = ' ';
1.493 + break;
1.494 + }
1.495 + if (len >= s.length) {
1.496 + char ns[] = new char[s.length * 2];
1.497 + System.arraycopy(s, 0, ns, 0, len);
1.498 + s = ns;
1.499 + }
1.500 + s[len++] = (char) c;
1.501 + }
1.502 + firstc = -1;
1.503 + }
1.504 + while (len > 0 && s[len - 1] <= ' ')
1.505 + len--;
1.506 + String k;
1.507 + if (keyend <= 0) {
1.508 + k = null;
1.509 + keyend = 0;
1.510 + } else {
1.511 + k = String.copyValueOf(s, 0, keyend);
1.512 + if (keyend < len && s[keyend] == ':')
1.513 + keyend++;
1.514 + while (keyend < len && s[keyend] <= ' ')
1.515 + keyend++;
1.516 + }
1.517 + String v;
1.518 + if (keyend >= len)
1.519 + v = new String();
1.520 + else
1.521 + v = String.copyValueOf(s, keyend, len - keyend);
1.522 + add(k, v);
1.523 + }
1.524 + }
1.525 +
1.526 + public synchronized String toString() {
1.527 + String result = super.toString() + nkeys + " pairs: ";
1.528 + for (int i = 0; i < keys.length && i < nkeys; i++) {
1.529 + result += "{"+keys[i]+": "+values[i]+"}";
1.530 + }
1.531 + return result;
1.532 + }
1.533 +}
1.534 +
1.535 +interface ContentHandlerFactory {
1.536 +
1.537 + public ContentHandler createContentHandler(String contentType);
1.538 +}
1.539 +
1.540 +abstract class ContentHandler {
1.541 + /**
1.542 + * Given a URL connect stream positioned at the beginning of the
1.543 + * representation of an object, this method reads that stream and
1.544 + * creates an object from it.
1.545 + *
1.546 + * @param urlc a URL connection.
1.547 + * @return the object read by the <code>ContentHandler</code>.
1.548 + * @exception IOException if an I/O error occurs while reading the object.
1.549 + */
1.550 + abstract public Object getContent(URLConnection urlc) throws IOException;
1.551 +
1.552 + /**
1.553 + * Given a URL connect stream positioned at the beginning of the
1.554 + * representation of an object, this method reads that stream and
1.555 + * creates an object that matches one of the types specified.
1.556 + *
1.557 + * The default implementation of this method should call getContent()
1.558 + * and screen the return type for a match of the suggested types.
1.559 + *
1.560 + * @param urlc a URL connection.
1.561 + * @param classes an array of types requested
1.562 + * @return the object read by the <code>ContentHandler</code> that is
1.563 + * the first match of the suggested types.
1.564 + * null if none of the requested are supported.
1.565 + * @exception IOException if an I/O error occurs while reading the object.
1.566 + * @since 1.3
1.567 + */
1.568 + public Object getContent(URLConnection urlc, Class[] classes) throws IOException {
1.569 + Object obj = getContent(urlc);
1.570 +
1.571 + for (int i = 0; i < classes.length; i++) {
1.572 + if (classes[i].isInstance(obj)) {
1.573 + return obj;
1.574 + }
1.575 + }
1.576 + return null;
1.577 + }
1.578 +
1.579 +}
1.580 +class UnknownServiceException extends IOException {
1.581 + private static final long serialVersionUID = -4169033248853639508L;
1.582 +
1.583 + /**
1.584 + * Constructs a new <code>UnknownServiceException</code> with no
1.585 + * detail message.
1.586 + */
1.587 + public UnknownServiceException() {
1.588 + }
1.589 +
1.590 + /**
1.591 + * Constructs a new <code>UnknownServiceException</code> with the
1.592 + * specified detail message.
1.593 + *
1.594 + * @param msg the detail message.
1.595 + */
1.596 + public UnknownServiceException(String msg) {
1.597 + super(msg);
1.598 + }
1.599 +}
1.600 +/**
1.601 + * A simple interface which provides a mechanism to map
1.602 + * between a file name and a MIME type string.
1.603 + *
1.604 + * @author Steven B. Byrne
1.605 + * @since JDK1.1
1.606 + */
1.607 +interface FileNameMap {
1.608 +
1.609 + /**
1.610 + * Gets the MIME type for the specified file name.
1.611 + * @param fileName the specified file name
1.612 + * @return a <code>String</code> indicating the MIME
1.613 + * type for the specified file name.
1.614 + */
1.615 + public String getContentTypeFor(String fileName);
1.616 +}