📄 protocol.java
字号:
/* * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */package com.sun.cdc.io.j2me.http;import java.io.IOException;import java.io.InputStream;import java.io.InterruptedIOException;import java.io.OutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.ByteArrayOutputStream;import java.net.URL;import java.net.MalformedURLException;import java.net.Socket;import java.util.Hashtable;import java.util.Enumeration;import javax.microedition.io.StreamConnection;import javax.microedition.io.HttpConnection;import javax.microedition.io.Connector;import com.sun.cdc.io.ConnectionBase;import com.sun.cdc.io.DateParser;import java.net.SocketException;import java.net.UnknownHostException;import java.security.AccessController;import java.security.PrivilegedAction;import javax.microedition.io.ConnectionNotFoundException;/** * This class implements the necessary functionality * for an HTTP connection. */public class Protocol extends ConnectionBase implements HttpConnection { protected String url; protected String protocol; protected String host; private String file; private String ref; private String query; protected int port = 80; protected int responseCode; protected String responseMsg; protected Hashtable reqProperties; protected Hashtable headerFields; private String[] headerFieldNames; private String[] headerFieldValues; protected String method; protected int opens; protected int mode; protected Socket socket; protected boolean connected; /* there should be only one outputstream opened at any time */ protected boolean outputStreamOpened = false; protected boolean requested = false; private boolean closed = false; /* * In/Out Streams used to buffer input and output */ private PrivateInputStream privateIn; protected PrivateOutputStream privateOut; /* * The streams from the underlying socket connection. */ protected StreamConnection streamConnection; protected DataOutputStream streamOutput; protected DataInputStream streamInput; /** Maximum number of persistent connections. */ protected static int maxNumberOfPersistentConnections; /** Connection linger time in the pool, default 60 seconds. */ protected static long connectionLingerTime; protected static StreamConnectionPool connectionPool; static { maxNumberOfPersistentConnections = Integer.parseInt( (String) AccessController.doPrivileged( new sun.security.action.GetPropertyAction( "microedition.maxpersconn", "10"))); connectionLingerTime = Integer.parseInt( (String) AccessController.doPrivileged( new sun.security.action.GetPropertyAction( "microedition.connlinger", "60000"))); createConnectionPool(); } protected static void createConnectionPool() { connectionPool = new StreamConnectionPool( maxNumberOfPersistentConnections, connectionLingerTime); } /* * A shared temporary buffer used in a couple of places */ protected StringBuffer stringbuffer; private String proxyHost = null; private int proxyPort = 80; protected final String httpVersion = "HTTP/1.1"; /** Used when appl calls setRequestProperty("Connection", "close"). */ private boolean ConnectionCloseFlag; private String responseProtocol; /** * create a new instance of this class. * We are initially unconnected. */ public Protocol() { reqProperties = new Hashtable(); headerFields = new Hashtable(); stringbuffer = new StringBuffer(32); opens = 0; connected = false; method = GET; responseCode = -1; protocol = "http"; AccessController.doPrivileged(new PrivilegedAction() { public Object run() { String http_proxy; String profileTemp = System.getProperty("microedition.profiles"); if (profileTemp != null && profileTemp.indexOf("MIDP") != -1) { // We want to look for a MIDP property specifying proxies. http_proxy = System.getProperty("com.sun.midp.io.http.proxy"); } else { // Default to CDC http_proxy = System.getProperty("com.sun.cdc.io.http.proxy"); } parseProxy(http_proxy); return null; } }); } /* * Check permission to connect to the indicated host. * This should be overriden by the MIDP protocol handler * to check the proper MIDP permission. */ protected void checkPermission(String host, int port, String file) { // Check for SecurityManager.checkConnect() java.lang.SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkConnect(host, port); } return; } /* * Check permission when opening an OutputStream. MIDP * versions of the protocol handler should override this * with an empty method. Throw a SecurityException if * the connection is not allowed. */ protected void outputStreamPermissionCheck() { // Check for SecurityManager.checkConnect() java.lang.SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (host != null) { sm.checkConnect(host, port); } else { sm.checkConnect("localhost", port); } } return; } /* * Check permission when opening an InputStream. MIDP * versions of the protocol handler should override this * with an empty method. A SecurityException will be * raised if the connection is not allowed. */ protected void inputStreamPermissionCheck() { // Check for SecurityManager.checkConnect() java.lang.SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (host != null) { sm.checkConnect(host, port); } else { sm.checkConnect("localhost", port); } } return; } private boolean match(String src, String alphabet) { src = src.toLowerCase(); for (int i = 0; i < src.length(); ++i) { if (-1 == alphabet.indexOf(src.charAt(i))) { return false; } } return true; } private void validateHost() { final String ALPHANUM = "0123456789abcdefghijklmnopqrstuvwxyz-"; final String DIGITS = "0123456789"; final String HEX = "abcdef"; final int TLD = -1; if (host.endsWith(".") || host.startsWith(".")) { throw new IllegalArgumentException("Invalid host name: "+host); } int i = 0; int[] ip4addr = new int[4]; int ip4n = 0; boolean ip4 = true; boolean ip6 = host.startsWith("[") && host.endsWith("]"); if (ip6) { // remove [ and ] for IPv6: host = host.substring(1, host.length()-1); ip4 = false; } try { boolean error = false; String sep = ip6 ? ":" : "."; do { int n = host.indexOf(sep, i); // -1 means top-level domain String domain = host.substring(i, n == TLD ? host.length() : n); if (ip6) { if (!match(domain, DIGITS+HEX) && !"".equals(domain)){ error = true; break; } } else { if (domain.equals("") || !match(domain, ALPHANUM) // Minus sign cannot be first or last symbol || domain.startsWith("-") || domain.endsWith("-") // TLD cannot start with a digit || (n == TLD && !ip4 && match(domain.substring(0, 1), DIGITS)) // Only for numbers in IPv4 address || (ip4 && ip4n >= 4)) { error = true; break; } if (ip4 && match(domain, DIGITS+HEX+'x')) { if (match(domain, DIGITS)) { // decimal ip4addr[ip4n] = Integer.parseInt(domain, 10); } else { if (domain.startsWith("0x")) { // hexadecimal ip4addr[ip4n] = Integer.parseInt(domain.substring(2), 16); } else { ip4 = false; } } } else { ip4 = false; } ip4n++; } i = n+1; } while (i != 0); if (error) { throw new IllegalArgumentException("Invalid host name: "+host); } } catch (NumberFormatException e) { throw new IllegalArgumentException("Invalid host name: "+host); } // Check IPv4 address range if (ip4 && ip4n == 4) { for (i = 0; i < 4; ++i) { if (ip4addr[i] < 0 || ip4addr[i] > 255) { throw new IllegalArgumentException( "Invalid host name: " + host); } } } } public void open(String url, int mode, boolean timeouts) throws IOException { open1(url, mode, timeouts); getStreamConnection(); } public void open1(String url, int mode, boolean timeouts) throws IOException { // DEBUG: System.out.println ("open " + url); if (opens > 0) { throw new IOException("already connected"); } opens = 1; closed = false; if (mode != Connector.READ && mode != Connector.WRITE && mode != Connector.READ_WRITE) { throw new IOException("illegal mode: " + mode); } this.url = url; this.mode = mode; parseURL(); validateHost(); // Check permission. The permission method wants the URL checkPermission(host, port, file); } protected void getStreamConnection() throws IOException { if (streamConnection == null) { try { streamConnection = connectSocket(); } catch (UnknownHostException ex) { throw new ConnectionNotFoundException( "Cannot connect to "+host+" on port "+port+": "+ex); } catch (SocketException ex) { throw new ConnectionNotFoundException( "Cannot connect to "+host+" on port "+port+": "+ex); } } } public void close() throws IOException { // DEBUG: System.out.println ("close " + opens + " " + connected ); /* Decrement opens only once - there could be multiple close() calls */ if (!closed) { --opens; closed = true; } if (opens == 0 && (connected || requested)) { disconnect(); } } /* * Open the input stream if it has not already been opened. * @exception IOException is thrown if it has already been * opened for writing */ public InputStream openInputStream() throws IOException { // DEBUG: System.out.println ("open input stream"); inputStreamPermissionCheck(); /* CR 6226615: opening another stream should not throw IOException if (in != null) { throw new IOException("already open"); } */ // If the connection was opened and closed before the // data input stream is accessed, throw an IO exception if (opens == 0) { throw new IOException("connection is closed"); } // Check that the connection was opened for reading if (mode != Connector.READ && mode != Connector.READ_WRITE) { throw new IOException("write-only connection"); } connect(); opens++; privateIn = new PrivateInputStream(); return privateIn; } public DataInputStream openDataInputStream() throws IOException { /* CR 6226615: opening another stream should not throw IOException if (appDataIn != null) { throw new IOException("already open"); } */ openInputStream(); return new DataInputStream(privateIn); } public OutputStream openOutputStream() throws IOException { // Delegate to openDataOutputStream return openDataOutputStream(); } public DataOutputStream openDataOutputStream() throws IOException { outputStreamPermissionCheck(); // DEBUG: System.out.println ("open data output stream"); if (mode != Connector.WRITE && mode != Connector.READ_WRITE) { throw new IOException("read-only connection"); } // If the connection was opened and closed before the // data output stream is accessed, throw an IO exception if (opens == 0) { throw new IOException("connection is closed"); } if (privateIn != null) { throw new IOException( "cannot open output stream while input stream is open"); } /* CR 6226615: opening another stream should not throw IOException if (out != null) { throw new IOException("already open"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -