You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2005/12/01 07:04:00 UTC
svn commit: r350181 [89/198] - in
/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core: ./ depends/
depends/files/ depends/jars/ depends/libs/ depends/libs/linux.IA32/
depends/libs/win.IA32/ depends/oss/ depends/oss/linux.IA32/
depends/oss/win.I...
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/FtpURLConnection.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/FtpURLConnection.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/FtpURLConnection.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/FtpURLConnection.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,378 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.oti.net.www.protocol.ftp;
+
+
+import java.io.BufferedInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketPermission;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.Permission;
+
+import com.ibm.oti.net.www.MimeTable;
+import com.ibm.oti.util.Msg;
+
+public class FtpURLConnection extends URLConnection {
+
+ Socket controlSocket, dataSocket;
+
+ ServerSocket acceptSocket;
+
+ InputStream ctrlInput, inputStream;
+
+ OutputStream ctrlOutput;
+
+ private String replyCode, hostName;
+
+ int dataPort;
+
+ private static final int FTP_PORT = 21;
+
+ private String PASSWORD = "";
+
+ private String USERNAME = "anonymous";
+
+ // FTP Reply Constants
+ private static final int FTP_DATAOPEN = 125;
+
+ private static final int FTP_OPENDATA = 150;
+
+ private static final int FTP_OK = 200;
+
+ private static final int FTP_USERREADY = 220;
+
+ private static final int FTP_TRANSFEROK = 226;
+
+ //private static final int FTP_PASV = 227;
+
+ private static final int FTP_LOGGEDIN = 230;
+
+ private static final int FTP_FILEOK = 250;
+
+ private static final int FTP_PASWD = 331;
+
+ //private static final int FTP_DATAERROR = 451;
+
+ //private static final int FTP_ERROR = 500;
+
+ private static final int FTP_NOTFOUND = 550;
+
+ /**
+ * FtpURLConnection constructor comment.
+ *
+ * @param url
+ * java.net.URL
+ */
+ protected FtpURLConnection(URL url) {
+ super(url);
+ hostName = url.getHost();
+ String parse = url.getUserInfo();
+ if (parse != null) {
+ int split = parse.indexOf(':');
+ if (split >= 0) {
+ USERNAME = parse.substring(0, split);
+ PASSWORD = parse.substring(split + 1);
+ } else
+ USERNAME = parse;
+ }
+ }
+
+ /* Change the server directory to that specfied in the URL */
+ private void cd() throws IOException {
+ int idx = url.getFile().lastIndexOf('/');
+
+ if (idx > 0) {
+ String dir = url.getFile().substring(0, idx);
+ write("CWD " + dir + "\r\n");
+ int reply = getReply();
+ if (reply != FTP_FILEOK && dir.length() > 0 && dir.charAt(0) == '/') {
+ write("CWD " + dir.substring(1) + "\r\n");
+ reply = getReply();
+ }
+ if (reply != FTP_FILEOK)
+ throw new IOException(Msg.getString("K0094"));
+ }
+ }
+
+ /**
+ * Establishes the connection to the resource specified by this
+ * <code>URL</code>
+ *
+ * @see #connected
+ * @see java.io.IOException
+ * @see URLStreamHandler
+ */
+ public void connect() throws IOException {
+ int port = url.getPort();
+ if (port <= 0)
+ port = FTP_PORT;
+ controlSocket = new Socket(hostName, port);
+ connected = true;
+ ctrlOutput = controlSocket.getOutputStream();
+ ctrlInput = controlSocket.getInputStream();
+ login();
+ setType();
+ if (!getDoInput())
+ cd();
+
+ try {
+ acceptSocket = new ServerSocket(0);
+ dataPort = acceptSocket.getLocalPort();
+ /* Cannot set REUSEADDR so we need to send a PORT comannd */
+ port();
+ acceptSocket.setSoTimeout(3000);
+ if (getDoInput())
+ getFile();
+ else
+ sendFile();
+ dataSocket = acceptSocket.accept();
+ acceptSocket.close();
+ } catch (InterruptedIOException e) {
+ throw new IOException(Msg.getString("K0095"));
+ }
+ if (getDoInput())
+ inputStream = new FtpURLInputStream(new BufferedInputStream(
+ dataSocket.getInputStream()), controlSocket);
+
+ }
+
+ /*
+ * Answers the content type of the resource. Just takes a guess based on the
+ * name.
+ */
+ public String getContentType() {
+ String result = guessContentTypeFromName(url.getFile());
+ if (result == null)
+ return MimeTable.UNKNOWN;
+ return result;
+ }
+
+ private void getFile() throws IOException {
+ int reply;
+ String file = url.getFile();
+ write("RETR " + file + "\r\n");
+ reply = getReply();
+ if (reply == FTP_NOTFOUND && file.length() > 0 && file.charAt(0) == '/') {
+ write("RETR " + file.substring(1) + "\r\n");
+ reply = getReply();
+ }
+ if (!(reply == FTP_OPENDATA || reply == FTP_TRANSFEROK))
+ throw new FileNotFoundException(Msg.getString("K0096", reply));
+ }
+
+ /**
+ * Creates a input stream for writing to this URL Connection.
+ *
+ * @return InputStream The input stream to write to
+ * @exception IOException
+ * Cannot read from URL ro error creating InputStream
+ *
+ * @see #getContent()
+ * @see #getOutputStream()
+ * @see java.io.InputStream
+ * @see java.io.IOException
+ *
+ */
+
+ public InputStream getInputStream() throws IOException {
+ if (!connected)
+ connect();
+ return inputStream;
+ }
+
+ /**
+ * Answers the permission object (in this case, SocketPermission) with the
+ * host and the port number as the target name and "resolve, connect" as the
+ * action list.
+ *
+ * @return java.security.Permission the permission object required for this
+ * connection
+ * @exception java.io.IOException
+ * thrown when an IO exception occurs during the creation of
+ * the permission object.
+ */
+ public Permission getPermission() throws IOException {
+ int port = url.getPort();
+ if (port <= 0)
+ port = FTP_PORT;
+ return new SocketPermission(hostName + ":" + port, "connect, resolve");
+ }
+
+ /**
+ * Creates a output stream for writing to this URL Connection.
+ *
+ * @return OutputStream The output stream to write to
+ * @exception IOException
+ * Thrown when the OutputStream could not be created
+ *
+ * @see #getContent()
+ * @see #getInputStream()
+ * @see java.io.IOException
+ *
+ */
+
+ public OutputStream getOutputStream() throws IOException {
+ if (!connected)
+ connect();
+ return dataSocket.getOutputStream();
+ }
+
+ private int getReply() throws IOException {
+ byte[] code = new byte[3];
+ ctrlInput.read(code, 0, code.length);
+ replyCode = new String(code, "ISO8859_1");
+ boolean multiline = false;
+ if (ctrlInput.read() == '-')
+ multiline = true;
+ readLine(); /* Skip the rest of the first line */
+ if (multiline)
+ while (readMultiLine()) {/* Read all of a multiline reply */
+ }
+ return Integer.parseInt(new String(code, "ISO8859_1"));
+ }
+
+ private void login() throws IOException {
+ int reply;
+ reply = getReply();
+ if (reply == FTP_USERREADY) {
+ } else {
+ throw new IOException(Msg.getString("K0097", url.getHost()));
+ }
+ write("USER " + USERNAME + "\r\n");
+ reply = getReply();
+ if (reply == FTP_PASWD || reply == FTP_LOGGEDIN) {
+ } else {
+ throw new IOException(Msg.getString("K0098", url.getHost()));
+ }
+ if (reply == FTP_PASWD) {
+ write("PASS " + PASSWORD + "\r\n");
+ reply = getReply();
+ if (!(reply == FTP_OK || reply == FTP_USERREADY || reply == FTP_LOGGEDIN))
+ throw new IOException(Msg.getString("K0098", url.getHost()));
+ }
+ }
+
+ private void port() throws IOException {
+ write("PORT "
+ + controlSocket.getLocalAddress().getHostAddress().replace('.',
+ ',') + ',' + (dataPort >> 8) + ',' + (dataPort & 255)
+ + "\r\n");
+ if (getReply() != FTP_OK)
+ throw new IOException(Msg.getString("K0099"));
+ }
+
+ /* Read a line of text and return it for posible parsing */
+ private String readLine() throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int c;
+ while ((c = ctrlInput.read()) != '\n') {
+ sb.append((char) c);
+ }
+ return sb.toString();
+ }
+
+ private boolean readMultiLine() throws IOException {
+ String line = readLine();
+ if (line.length() < 4)
+ return true;
+ if (line.substring(0, 3).equals(replyCode)
+ && (line.charAt(3) == (char) 32))
+ return false;
+ return true;
+ }
+
+ /*
+ * Issue the STOR command to the server with the file as the parameter
+ */
+ private void sendFile() throws IOException {
+ int reply;
+ write("STOR "
+ + url.getFile().substring(url.getFile().lastIndexOf('/') + 1,
+ url.getFile().length()) + "\r\n");
+ reply = getReply();
+ if (!(reply == FTP_OPENDATA || reply == FTP_OK || reply == FTP_DATAOPEN))
+ throw new IOException(Msg.getString("K009a"));
+ }
+
+ /**
+ * Set the flag if this <code>URLConnection</code> supports input (read).
+ * It cannot be set after the connection is made. FtpURLConnections cannot
+ * support both input and output
+ *
+ * @param newValue
+ * boolean
+ *
+ * @exception IllegalAccessError
+ * Exception thrown when this method attempts to change the
+ * flag after connected
+ *
+ * @see #doInput
+ * @see #getDoInput()
+ * @see java.lang.IllegalAccessError
+ * @see #setDoInput(boolean)
+ */
+ public void setDoInput(boolean newValue) {
+ if (connected) {
+ throw new IllegalAccessError();
+ }
+ this.doInput = newValue;
+ this.doOutput = !newValue;
+ }
+
+ /**
+ * Set the flag if this <code>URLConnection</code> supports output(read).
+ * It cannot be set after the connection is made.\ FtpURLConnections cannot
+ * support both input and output.
+ *
+ * @param newValue
+ * boolean
+ *
+ * @exception IllegalAccessError
+ * Exception thrown when this method attempts to change the
+ * flag after connected
+ *
+ * @see #doOutput
+ * @see java.lang.IllegalAccessError
+ * @see #setDoOutput(boolean)
+ */
+ public void setDoOutput(boolean newValue) {
+ if (connected) {
+ throw new IllegalAccessError();
+ }
+ this.doOutput = newValue;
+ this.doInput = !newValue;
+ }
+
+ /*
+ Set the type of the file transfer. Only Image is suported
+ */
+ private void setType() throws IOException {
+ write("TYPE I\r\n");
+ if (getReply() != FTP_OK)
+ throw new IOException(Msg.getString("K009b"));
+ }
+
+ private void write(String command) throws IOException {
+ ctrlOutput.write(command.getBytes("ISO8859_1"));
+ }
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/FtpURLInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/FtpURLInputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/FtpURLInputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/FtpURLInputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,79 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.oti.net.www.protocol.ftp;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+
+/**
+ * This class associates a given inputStream with a control socket. This ensures
+ * the control socket Object stays live while the stream is in use
+ */
+class FtpURLInputStream extends InputStream {
+
+ InputStream is; // Actual input stream
+
+ java.net.Socket controlSocket;
+
+ public FtpURLInputStream(InputStream is, Socket controlSocket) {
+ this.is = is;
+ this.controlSocket = controlSocket;
+ }
+
+ public int read() throws IOException {
+ return is.read();
+ }
+
+ public int read(byte[] buf, int off, int nbytes) throws IOException {
+ return is.read(buf, off, nbytes);
+ }
+
+ public synchronized void reset() throws IOException {
+ is.reset();
+ }
+
+ public synchronized void mark(int limit) {
+ is.mark(limit);
+ }
+
+ public boolean markSupported() {
+ return is.markSupported();
+ }
+
+ public void close() {
+ try {
+ is.close();
+ } catch (Exception e) {
+ // ignored
+ }
+ try {
+ controlSocket.close();
+ } catch (Exception e) {
+ //ignored
+ }
+ }
+
+ public int available() throws IOException {
+ return is.available();
+ }
+
+ public long skip(long sbytes) throws IOException {
+ return is.skip(sbytes);
+ }
+
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/Handler.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/Handler.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/Handler.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/ftp/Handler.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,37 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.oti.net.www.protocol.ftp;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+
+public class Handler extends java.net.URLStreamHandler {
+ /**
+ * Open a URLConnection on the given URL.
+ */
+ protected URLConnection openConnection(URL u) throws IOException {
+ return new FtpURLConnection(u);
+ }
+
+ /**
+ * Return the default port.
+ */
+ protected int getDefaultPort() {
+ return 21;
+ }
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/Handler.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/Handler.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/Handler.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/Handler.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,48 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.oti.net.www.protocol.http;
+
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.io.IOException;
+import java.net.URLStreamHandler;
+
+/**
+ * This is the handler that manages all transactions between the client and a HTTP remote server.
+ *
+ */
+public class Handler extends URLStreamHandler {
+
+/**
+ * Answers a connection to the HTTP server specified by this <code>URL</code>.
+ *
+ * @param u the URL to which the connection is pointing to
+ * @return a connection to the resource pointed by this url.
+ *
+ * @thows IOException if this handler fails to establish a connection
+ */
+protected URLConnection openConnection(URL u) throws IOException {
+ return new HttpURLConnection(u, getDefaultPort());
+}
+
+/**
+ * Return the default port.
+ */
+protected int getDefaultPort() {
+ return 80;
+}
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/Header.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/Header.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/Header.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/Header.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,203 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.oti.net.www.protocol.http;
+
+
+import java.util.*;
+
+/**
+ * The general structure for request / reponse header. It is essentially constructed by
+ * hashtable with key indexed in a vector for position lookup.
+ *
+ */
+
+public class Header implements Cloneable{
+ /**
+ * The default amount of fields for a header
+ */
+ private static final int incCapacity = 20;
+
+ /* we use the non-synchronized ArrayList and HashMap instead of
+ * the synchronized Vector and Hashtable
+ */
+ private ArrayList props = new ArrayList(incCapacity);
+ private HashMap keyTable = new HashMap(incCapacity);
+ private String statusLine;
+
+/**
+ * A generic header structure. Used mostly for request / response header.
+ * The key/value pair of the header may be inserted for later use. The key
+ * is stored in an array for indexed slot access.
+ *
+ *
+ */
+public Header() {}
+
+public Object clone(){
+ try {
+ Header clone = (Header) super.clone();
+
+ clone.props = (ArrayList) props.clone();
+ HashMap cloneTable = clone.keyTable = new HashMap(incCapacity);
+ Iterator entries = keyTable.entrySet().iterator();
+ while(entries.hasNext()) {
+ Map.Entry next = (Map.Entry) entries.next();
+ cloneTable.put(next.getKey(), ((LinkedList) next.getValue()).clone());
+ }
+ return clone;
+ } catch (CloneNotSupportedException e) {return null;}
+}
+/**
+ * Add a field with the specified value.
+ *
+ *
+ * @param key java.lang.String
+ * @param value java.lang.String
+ */
+public void add(String key, String value) {
+ if(key == null) {
+ throw new NullPointerException();
+ }
+ LinkedList list = (LinkedList) keyTable.get(key);
+ if(list == null) {
+ list = new LinkedList();
+ keyTable.put(key.toLowerCase(), list);
+ }
+ list.add(value);
+ props.add(key);
+ props.add(value);
+}
+/**
+ * Set a field with the specified value. If the field is not found, it is
+ * added. If the field is found, the existing value(s) are overwritten.
+ *
+ *
+ * @param key java.lang.String
+ * @param value java.lang.String
+ */
+public void set(String key, String value) {
+ if(key == null) {
+ throw new NullPointerException();
+ }
+ LinkedList list = (LinkedList) keyTable.get(key);
+ if(list == null) {
+ add(key, value);
+ }
+ else {
+ list.clear();
+ list.add(value);
+ for(int i=0; i<props.size(); i+=2) {
+ String propKey = (String) props.get(i);
+ if(propKey != null && key.equals(propKey)) {
+ props.set(i+1, value);
+ }
+ }
+ }
+}
+
+/**
+ * Provides an unmodifiable map with all String header names mapped to their String values.
+ * The map keys are Strings and the values are unmodifiable Lists of Strings.
+ * @return an unmodifiable map of the headers
+ *
+ * @since 1.4
+ */
+public Map getFieldMap() {
+ Map result = new HashMap(keyTable.size());
+ Iterator iterator = keyTable.entrySet().iterator();
+ while(iterator.hasNext()) {
+ Map.Entry next = (Map.Entry) iterator.next();
+ result.put(next.getKey(), Collections.unmodifiableList((LinkedList) next.getValue()));
+ }
+ return Collections.unmodifiableMap(result);
+}
+
+/**
+ * Answers the element at <code>pos</code>, null if no such element exist.
+ *
+ * @return java.lang.String the value of the key
+ * @param pos int the position to look for
+ */
+public String get(int pos) {
+ if (pos >= 0 && pos < props.size() / 2) {
+ return (String) props.get(pos * 2 + 1);
+ }
+ return null;
+}
+/**
+ * Answers the key of this header at <code>pos</code>, null if there are fewer keys in the header
+ *
+ *
+ * @return java.lang.String the key the desired position
+ * @param pos int the position to look for
+ */
+public String getKey(int pos) {
+ if (pos >= 0 && pos < props.size() / 2) {
+ return (String) props.get(pos * 2);
+ }
+ return null;
+}
+/**
+ * Answers the value corresponding to the specified key, null if no such key exists.
+ *
+ *
+ * @return java.lang.String
+ * @param key java.lang.String
+ */
+public String get(String key) {
+ LinkedList result = (LinkedList) keyTable.get(key.toLowerCase());
+ if(result == null) {
+ return null;
+ }
+ return (String) result.getLast();
+}
+
+/**
+ * Answers the number of keys stored in this header
+ *
+ *
+ * @return int
+ */
+public int length() {
+ return props.size() / 2;
+}
+
+/**
+ * Sets the status line in the header
+ * request example: GET / HTTP/1.1
+ * response example: HTTP/1.1 200 OK
+ * @param statusLine
+ */
+public void setStatusLine(String statusLine) {
+ this.statusLine = statusLine;
+ //we add the status line to the list of headers so that it is accessible
+ //from java.net.HttpURLConnection.getResponseCode()
+ //which calls com.ibm.oti.net.www.protocol.http.HttpURLConnection.getHeaderField(0) to get it
+ props.add(0, null);
+ props.add(1, statusLine);
+}
+
+/**
+ * Gets the status line in the header
+ * request example: GET / HTTP/1.1
+ * response example: HTTP/1.1 200 OK
+ * @return the status line
+ */
+public String getStatusLine() {
+ return statusLine;
+}
+
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/HttpURLConnection.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/HttpURLConnection.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/HttpURLConnection.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/http/HttpURLConnection.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,1006 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.oti.net.www.protocol.http;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.ByteArrayOutputStream;
+import java.net.*;
+import java.util.*;
+import java.security.AccessController;
+import com.ibm.oti.util.PriviAction;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.text.SimpleDateFormat;
+
+/**
+ * This subclass extends <code>HttpURLConnection</code> which in turns extends <code>URLConnection</code>
+ * This is the actual class that "does the work", such as connecting, sending request and getting the content from
+ * the remote server.
+ *
+ */
+
+public class HttpURLConnection extends java.net.HttpURLConnection {
+ int httpVersion = 1; // Assume HTTP/1.1
+ private final int defaultPort;
+ InputStream is;
+ private InputStream uis;
+ OutputStream socketOut;
+ private HttpOutputStream os;
+ private boolean sentRequest = false;
+ boolean sendChunked = false;
+ private String proxyName;
+ private int hostPort = -1;
+ private int readTimeout = -1;
+
+ // default request header
+ private static Header defaultReqHeader = new Header();
+
+ // request header that will be sent to the server
+ private Header reqHeader;
+
+ // response header received from the server
+ private Header resHeader;
+
+ private class LimitedInputStream extends InputStream {
+ int bytesRemaining;
+ public LimitedInputStream(int length) {
+ bytesRemaining = length;
+ }
+ public void close() throws IOException {
+ bytesRemaining = 0;
+ closeSocket();
+ }
+ public int available() throws IOException {
+ int result = is.available();
+ if (result > bytesRemaining) return bytesRemaining;
+ return result;
+ }
+ public int read() throws IOException {
+ if (bytesRemaining <= 0) return -1;
+ int result = is.read();
+ bytesRemaining--;
+ return result;
+ }
+ public int read(byte[] buf, int offset, int length) throws IOException {
+ if (buf == null) throw new NullPointerException();
+ // avoid int overflow
+ if (offset < 0 || length < 0 || offset > buf.length || buf.length - offset < length)
+ throw new ArrayIndexOutOfBoundsException();
+ if (bytesRemaining <= 0) return -1;
+ if (length > bytesRemaining) length = bytesRemaining;
+ int result = is.read(buf, offset, length);
+ if (result > 0) bytesRemaining -= result;
+ return result;
+ }
+ public long skip(int amount) throws IOException {
+ if (bytesRemaining <= 0) return -1;
+ if (amount > bytesRemaining) amount = bytesRemaining;
+ long result = is.skip(amount);
+ if (result > 0) bytesRemaining -= result;
+ return result;
+ }
+ }
+
+ private class ChunkedInputStream extends InputStream {
+ int bytesRemaining = -1;
+ boolean atEnd = false;
+ public ChunkedInputStream() throws IOException {
+ readChunkSize();
+ }
+ public void close() throws IOException {
+ atEnd = true;
+ closeSocket();
+ }
+ public int available() throws IOException {
+ int result = is.available();
+ if (result > bytesRemaining) return bytesRemaining;
+ return result;
+ }
+ private void readChunkSize() throws IOException {
+ if (atEnd) return;
+ if (bytesRemaining == 0) readln(); // read CR/LF
+ String size = readln();
+ int index = size.indexOf(";");
+ if (index >= 0) size = size.substring(0, index);
+ bytesRemaining = Integer.parseInt(size.trim(), 16);
+ if (bytesRemaining == 0) {
+ atEnd = true;
+ readHeaders();
+ }
+ }
+ public int read() throws IOException {
+ if (bytesRemaining <= 0) readChunkSize();
+ if (atEnd) return -1;
+ bytesRemaining--;
+ return is.read();
+ }
+ public int read(byte[] buf, int offset, int length) throws IOException {
+ if (buf == null) throw new NullPointerException();
+ // avoid int overflow
+ if (offset < 0 || length < 0 || offset > buf.length || buf.length - offset < length)
+ throw new ArrayIndexOutOfBoundsException();
+ if (bytesRemaining <= 0) readChunkSize();
+ if (atEnd) return -1;
+ if (length > bytesRemaining) length = bytesRemaining;
+ int result = is.read(buf, offset, length);
+ if (result > 0) bytesRemaining -= result;
+ return result;
+ }
+ public long skip(int amount) throws IOException {
+ if (atEnd) return -1;
+ if (bytesRemaining <= 0) readChunkSize();
+ if (amount > bytesRemaining) amount = bytesRemaining;
+ long result = is.skip(amount);
+ if (result > 0) bytesRemaining -= result;
+ return result;
+ }
+ }
+
+ private class HttpOutputStream extends OutputStream {
+ static final int MAX = 1024;
+ ByteArrayOutputStream cache = new ByteArrayOutputStream(MAX+7);
+ boolean writeToSocket, closed = false;
+ int limit;
+ public HttpOutputStream() {
+ limit = -1;
+ }
+ public HttpOutputStream(int limit) {
+ writeToSocket = true;
+ this.limit = limit;
+ }
+ private void output(String output) throws IOException {
+ socketOut.write(output.getBytes("ISO8859_1"));
+ }
+ private void sendCache(boolean close) throws IOException {
+ int size = cache.size();
+ if (size > 0 || close) {
+ if (limit < 0) {
+ if (size > 0) {
+ output(Integer.toHexString(size) + "\r\n");
+ cache.write('\r'); cache.write('\n');
+ }
+ if (close) {
+ cache.write('0');
+ cache.write('\r'); cache.write('\n');
+ cache.write('\r'); cache.write('\n');
+ }
+ }
+ socketOut.write(cache.toByteArray());
+ cache.reset();
+ }
+ }
+ public synchronized void flush() throws IOException {
+ if (closed) throw new IOException(com.ibm.oti.util.Msg.getString("K0059"));
+ if (writeToSocket) {
+ sendCache(false);
+ socketOut.flush();
+ }
+ }
+ public synchronized void close() throws IOException {
+ if (closed) return;
+ closed = true;
+ if (writeToSocket) {
+ if (limit > 0) throw new IOException(com.ibm.oti.util.Msg.getString("K00a4"));
+ sendCache(closed);
+ }
+ }
+ public synchronized void write(int data) throws IOException {
+ if (closed) throw new IOException(com.ibm.oti.util.Msg.getString("K0059"));
+ if (limit >= 0) {
+ if (limit == 0) throw new IOException(com.ibm.oti.util.Msg.getString("K00b2"));
+ limit--;
+ }
+ cache.write(data);
+ if (writeToSocket && cache.size() >= MAX)
+ sendCache(false);
+ }
+ public synchronized void write(byte[] buffer, int offset, int count) throws IOException {
+ if (closed) throw new IOException(com.ibm.oti.util.Msg.getString("K0059"));
+ if (buffer==null) throw new NullPointerException();
+ // avoid int overflow
+ if (offset < 0 || count < 0 || offset > buffer.length || buffer.length - offset < count)
+ throw new ArrayIndexOutOfBoundsException(com.ibm.oti.util.Msg.getString("K002f"));
+
+ if (limit >= 0) {
+ if (count > limit) throw new IOException(com.ibm.oti.util.Msg.getString("K00b2"));
+ limit -= count;
+ }
+ if (!writeToSocket || cache.size() + count < MAX) {
+ cache.write(buffer, offset, count);
+ } else {
+ if (limit < 0)
+ output(Integer.toHexString(count + cache.size()) + "\r\n");
+ socketOut.write(cache.toByteArray());
+ cache.reset();
+ socketOut.write(buffer, offset, count);
+ if (limit < 0) output("\r\n");
+ }
+ }
+ synchronized int size() {
+ return cache.size();
+ }
+ synchronized byte[] toByteArray() {
+ return cache.toByteArray();
+ }
+ boolean isCached() {
+ return !writeToSocket;
+ }
+ boolean isChunked() {
+ return writeToSocket && limit == -1;
+ }
+ }
+
+/**
+ * Creates a instance of the <code>HttpURLConnection</code>
+ * using default port 80.
+ * @param url URL The URL this connection is connecting
+ */
+protected HttpURLConnection(URL url) {
+ this(url, 80);
+}
+
+/**
+ * Creates a instance of the <code>HttpURLConnection</code>
+ * @param url URL The URL this connection is connecting
+ * @param port int The default connection port
+ */
+protected HttpURLConnection(URL url, int port) {
+ super(url);
+ defaultPort = port;
+
+ reqHeader = (Header)defaultReqHeader.clone();
+
+}
+/**
+ * Establishes the connection to the remote HTTP server
+ *
+ * Any methods that requires a valid connection to the resource will call this method implicitly.
+ * After the connection is established, <code>connected</code> is set to true.
+ *
+ *
+ * @see #connected
+ * @see java.io.IOException
+ * @see URLStreamHandler
+ */
+public void connect() throws java.io.IOException {
+ if (connected) return;
+ Socket socket = new Socket(getHostAddress(), getHostPort());
+ if (readTimeout >= 0) socket.setSoTimeout(readTimeout);
+ connected = true;
+ socketOut = socket.getOutputStream();
+ is = new java.io.BufferedInputStream(socket.getInputStream());
+}
+
+/**
+ * Sets the read timeout for the http connection.
+ *
+ *
+ * @param value the read timeout value. Must be >= 0
+ *
+ * @see java.net.Socket#setSoTimeout
+ */
+public void setReadTimeout(int value) {
+ if (value < 0)
+ throw new IllegalArgumentException(com.ibm.oti.util.Msg.getString("K0036"));
+ readTimeout = value;
+}
+
+/**
+ * Closes the connection with the HTTP server
+ *
+ *
+ * @see URLConnection#connect()
+ */
+public void disconnect() {
+ try {closeSocket();} catch (IOException e) {}
+}
+
+void closeSocket() throws IOException {
+ if (is != null)
+ is.close();
+}
+
+void endRequest() throws IOException {
+ if (os != null)
+ os.close();
+ sentRequest = false;
+}
+
+/**
+ * Answers the default value for the field specified by <code>field</code>,
+ * null if there's no such a field.
+ *
+ *
+ */
+public static String getDefaultRequestProperty(String field) {
+ return defaultReqHeader.get(field);
+}
+/**
+ * Answers an input stream from the server in the case of error such as the requested
+ * file (txt, htm, html) is not found on the remote server.
+ * <p>
+ * If the content type is not what stated above, <code>FileNotFoundException</code>
+ * is thrown.
+ *
+ * @return java.io.InputStream the error input stream returned by the server.
+ */
+public InputStream getErrorStream() {
+ if (connected && method != "HEAD" && responseCode >= HTTP_BAD_REQUEST)
+ return uis;
+ return null;
+}
+/**
+ * Answers the value of the field at position <code>pos<code>.
+ * Answers <code>null</code> if there is fewer than <code>pos</code> fields
+ * in the response header.
+ *
+ *
+ * @return java.lang.String The value of the field
+ * @param pos int the position of the field from the top
+ *
+ * @see #getHeaderField(String)
+ * @see #getHeaderFieldKey
+ */
+public String getHeaderField(int pos) {
+ try {
+ getInputStream();
+ return resHeader.get(pos);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+/**
+ * Answers the value of the field corresponding to the <code>key</code>
+ * Answers <code>null</code> if there is no such field.
+ *
+ * If there are multiple fields with that key, the last field value is returned.
+ *
+ *
+ * @return java.lang.String The value of the header field
+ * @param key java.lang.String the name of the header field
+ *
+ * @see #getHeaderField(int)
+ * @see #getHeaderFieldKey
+ */
+public String getHeaderField(String key) {
+ try {
+ getInputStream();
+ return resHeader.get(key);
+ } catch (IOException e) {
+ return null;
+ }
+}
+/**
+ * This method answers the header field at position <code>pos</code> from the response header,
+ * null if there is fewer fields than <code>pos</code>.
+ *
+ *
+ * @return java.lang.String
+ * @param pos int
+ *
+ * @see #getHeaderField(String)
+ * @see #getHeaderField(int)
+ */
+public String getHeaderFieldKey(int pos) {
+ try {
+ getInputStream();
+ return resHeader.getKey(pos);
+ } catch (IOException e) {
+ return null;
+ }
+}
+
+/**
+ * Provides an unmodifiable map of the connection header values. The map keys are the String
+ * header field names. Each map value is a list of the header field values associated with
+ * that key name.
+ *
+ * @return the mapping of header field names to values
+ *
+ * @since 1.4
+ */
+public Map getHeaderFields() {
+ return resHeader.getFieldMap();
+}
+
+/**
+ * Provides an unmodifiable map of the request properties. The map keys are Strings, the map
+ * values are each a List of Strings, with each request property name mapped to its corresponding property values.
+ *
+ * @return the mapping of request property names to values
+ *
+ * @since 1.4
+ */
+public Map getRequestProperties() {
+ return reqHeader.getFieldMap();
+}
+
+/**
+ * Creates an input stream for reading from this URL Connection.
+ *
+ *
+ * @return InputStream The input stream to read from
+ * @exception UnknownServiceException Exception thrown when reading to URL isn't supported
+ *
+ * @see #getContent()
+ * @see #getOutputStream()
+ * @see java.io.InputStream
+ * @see java.io.IOException
+ */
+public InputStream getInputStream() throws IOException {
+ if (!doInput)
+ throw new ProtocolException(com.ibm.oti.util.Msg.getString("K008d"));
+
+ doRequest();
+
+ // if the requested file does not exist, throw an exception
+ //formerly the Error page from the server was returned
+ //if the requested file was text/html
+ //this has changed to return FileNotFoundException for all file types
+ if (responseCode >= HTTP_BAD_REQUEST)
+ throw new java.io.FileNotFoundException(url.toString());
+
+ return uis;
+}
+
+private InputStream getContentStream() throws IOException {
+ if (uis != null) return uis;
+
+ String encoding = resHeader.get("Transfer-Encoding");
+ if (encoding != null && encoding.toLowerCase().equals("chunked"))
+ return uis = new ChunkedInputStream();
+
+ String sLength = resHeader.get("Content-Length");
+ if (sLength != null) {
+ try {
+ int length = Integer.parseInt(sLength);
+ return uis = new LimitedInputStream(length);
+ } catch (NumberFormatException e) {}
+ }
+ return uis = is;
+}
+/**
+ * Creates an output stream for writing to this URL Connection.
+ * <code>UnknownServiceException</code> will be thrown if this url denies write access
+ *
+ *
+ * @return OutputStream The output stream to write to
+ * @exception UnknownServiceException thrown when writing to URL is not supported
+ *
+ * @see #getContent()
+ * @see #getInputStream()
+ * @see java.io.IOException
+ *
+ */
+public OutputStream getOutputStream() throws IOException {
+ if (!doOutput)
+ throw new ProtocolException(com.ibm.oti.util.Msg.getString("K008e"));
+
+ // you can't write after you read
+ if (sentRequest)
+ throw new ProtocolException(com.ibm.oti.util.Msg.getString("K0090"));
+
+ if (os != null) return os;
+
+ // they are requesting a stream to write to. This implies a POST method
+ if (method == "GET")
+ setRequestMethod("POST");
+ // If the request method is neither PUT or POST, then you're not writing
+ if (method != "PUT" && method != "POST")
+ throw new ProtocolException(com.ibm.oti.util.Msg.getString("K008f", method));
+
+ int limit = -1;
+ String contentLength = reqHeader.get("Content-Length");
+ if (contentLength != null) limit = Integer.parseInt(contentLength);
+
+ String encoding = reqHeader.get("Transfer-Encoding");
+ if (httpVersion > 0 && encoding != null) {
+ encoding = encoding.toLowerCase();
+ if ("chunked".equals(encoding)) {
+ sendChunked = true;
+ limit = -1;
+ }
+ }
+ if ((httpVersion > 0 && sendChunked) || limit >= 0) {
+ os = new HttpOutputStream(limit);
+ doRequest();
+ return os;
+ }
+ return os = new HttpOutputStream();
+
+}
+/**
+ * Answers the permission required to make the connection
+ *
+ *
+ * @return java.security.Permission the connection required to make the connection.
+ * @exception java.io.IOException
+ * thrown if an IO exception occurs while computing the permission.
+ */
+public java.security.Permission getPermission() throws java.io.IOException {
+ return new SocketPermission(getHostName() + ":" + getHostPort(), "connect, resolve");
+}
+/**
+ * Answers the value corresponds to the field in the request Header,
+ * null if no such field exists
+ *
+ *
+ * @return java.lang.String The field to look up
+ *
+ * @see #getDefaultRequestProperty
+ * @see #setDefaultRequestProperty
+ * @see #setRequestProperty
+ */
+public String getRequestProperty(String field) {
+ if (connected) throw new IllegalAccessError(com.ibm.oti.util.Msg.getString("K0091"));
+ return reqHeader.get(field);
+}
+/**
+ * Answers a line read from the input stream. Does not include the \n
+ *
+ *
+ * @return java.lang.String
+ */
+String readln() throws IOException {
+ boolean lastCr = false;
+ StringBuffer result = new StringBuffer(80);
+ int c = is.read();
+ if (c < 0) return null;
+ while (c != '\n') {
+ if (lastCr) {
+ result.append('\r');
+ lastCr = false;
+ }
+ if (c == '\r') lastCr = true;
+ else result.append((char)c);
+ c = is.read();
+ if (c < 0) break;
+ }
+ return result.toString();
+}
+
+private String requestString() {
+ if (usingProxy() || proxyName != null) {
+ return url.toString();
+ }
+ String file = url.getFile();
+ if (file == null || file.length() == 0)
+ file = "/";
+ return file;
+}
+/**
+ * Sends the request header to the remote HTTP server
+ * Not all of them are guaranteed to have any effect on the content the
+ * server will return, depending on if the server supports that field.
+ *
+ *
+ * Examples : Accept: text/*, text/html, text/html;level=1,
+ * Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
+ */
+private boolean sendRequest() throws java.io.IOException {
+ byte[] request = createRequest();
+
+ // make sure we have a connection
+ if (!connected) connect();
+ // send out the HTTP request
+ socketOut.write(request);
+ sentRequest = true;
+ // send any output to the socket (i.e. POST data)
+ if (os != null && os.isCached()) {
+ socketOut.write(os.toByteArray());
+ }
+ if (os == null || os.isCached()) {
+ readServerResponse();
+ return true;
+ }
+ return false;
+}
+
+void readServerResponse() throws IOException {
+ socketOut.flush();
+ do {
+ responseCode = -1;
+ responseMessage = null;
+ resHeader = new Header();
+ String line = readln();
+ // Add the response, it may contain ':' which we ignore
+ if (line != null) {
+ resHeader.setStatusLine(line.trim());
+ readHeaders();
+ }
+ } while (getResponseCode() == 100);
+
+ if (method == "HEAD" || (responseCode >= 100 && responseCode < 200) ||
+ responseCode == HTTP_NO_CONTENT || responseCode == HTTP_NOT_MODIFIED)
+ {
+ closeSocket();
+ uis = new LimitedInputStream(0);
+ }
+}
+
+/**
+ * Answers the reponse code returned by the remote HTTP server
+ *
+ *
+ * @return int the response code, -1 if no valid response code
+ * @exception java.io.IOException thrown when there is a IO error during the retrieval.
+ *
+ * @see #getResponseMessage()
+ */
+public int getResponseCode() throws IOException {
+ // Response Code Sample : "HTTP/1.0 200 OK"
+
+ // Call connect() first since getHeaderField() doesn't return exceptions
+ doRequest();
+ if (responseCode != -1) return responseCode;
+ String response = resHeader.getStatusLine();
+ if (response == null || !response.startsWith("HTTP/"))
+ return -1;
+ response.trim();
+ int mark = response.indexOf(" ") + 1;
+ if (mark == 0) return -1;
+ if (response.charAt(mark - 2) != '1')
+ httpVersion = 0;
+ int last = mark + 3;
+ if (last > response.length()) last = response.length();
+ responseCode = Integer.parseInt(response.substring(mark, last));
+ if (last + 1 <= response.length())
+ responseMessage = response.substring(last + 1);
+ return responseCode;
+}
+
+void readHeaders() throws IOException {
+ // parse the result headers until the first blank line
+ String line;
+ while (((line = readln())!=null) && (line.length() > 1)) {
+ // Header parsing
+ int idx;
+ if ((idx = line.indexOf(":")) < 0)
+ resHeader.add("", line.trim());
+ else
+ resHeader.add(line.substring(0, idx), line.substring(idx + 1).trim());
+ }
+}
+
+private byte[] createRequest() throws IOException {
+ StringBuffer output = new StringBuffer(256);
+ output.append(method);
+ output.append(' ');
+ output.append(requestString());
+ output.append(' ');
+ output.append("HTTP/1.");
+ if (httpVersion == 0) output.append("0\r\n");
+ else output.append("1\r\n");
+ if (reqHeader.get("User-Agent") == null) {
+ output.append("User-Agent: ");
+ String agent = getSystemProperty("http.agent");
+ if (agent == null) {
+ output.append("Java");
+ output.append(getSystemProperty("java.version"));
+ } else {
+ output.append(agent);
+ }
+ output.append("\r\n");
+ }
+ if (reqHeader.get("Host") == null) {
+ output.append("Host: ");
+ output.append(url.getHost());
+ int port = url.getPort();
+ if (port > 0 && port != defaultPort) {
+ output.append(':');
+ output.append(Integer.toString(port));
+ }
+ output.append("\r\n");
+ }
+ if (httpVersion > 0 && reqHeader.get("Connection") == null)
+ output.append("Connection: close\r\n");
+
+ // if we are doing output make sure the approprate headers are sent
+ if (os != null) {
+ if (reqHeader.get("Content-Type") == null)
+ output.append("Content-Type: application/x-www-form-urlencoded\r\n");
+ if (os.isCached()) {
+ if (reqHeader.get("Content-Length") == null) {
+ output.append("Content-Length: ");
+ output.append(Integer.toString(os.size()));
+ output.append("\r\n");
+ }
+ } else if (os.isChunked())
+ output.append("Transfer-Encoding: chunked\r\n");
+ }
+
+ // then the user-specified request headers, if any
+ for (int i = 0; i < reqHeader.length(); i++) {
+ String key = reqHeader.getKey(i);
+ if (key != null) {
+ String lKey = key.toLowerCase();
+ if ((os != null && !os.isChunked()) || (!lKey.equals("transfer-encoding") &&
+ !lKey.equals("content-length")))
+ {
+ output.append(key);
+ output.append(": ");
+ /* duplicates are allowed under certain conditions
+ * see http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
+ */
+ output.append(reqHeader.get(i));
+ output.append("\r\n");
+ }
+ }
+ }
+ // end the headers
+ output.append("\r\n");
+ return output.toString().getBytes("ISO8859_1");
+}
+
+/**
+ * Sets the default request header fields to be sent to the remote server. This does
+ * not affect the current URL Connection, only newly created ones.
+ *
+ * @param field java.lang.String The name of the field to be changed
+ * @param value java.lang.String The new value of the field
+ */
+public static void setDefaultRequestProperty(String field, String value) {
+ defaultReqHeader.add(field, value);
+}
+/**
+ * A slightly different implementation from this parent's <code>setIfModifiedSince()</code>
+ * Since this HTTP impl supports IfModifiedSince as one of the header field, the request header
+ * is updated with the new value.
+ *
+ *
+ * @param newValue the number of millisecond since epoch
+ *
+ * @exception IllegalAccessError thrown when this method attempts to change the flag
+ * after connected
+ */
+public void setIfModifiedSince(long newValue) throws IllegalAccessError {
+ super.setIfModifiedSince(newValue);
+ // convert from millisecond since epoch to date string
+ SimpleDateFormat sdf = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
+ sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
+ String date = sdf.format(new java.util.Date(newValue));
+ reqHeader.add("If-Modified-Since", date);
+}
+/**
+ * Sets the value of the request header field <code> field </code> to <code>newValue</code>
+ * Only the current URL Connection is affected. It can only be called before the connection is made
+ * This method must be overridden by protocols which support the value of the fields.
+ *
+ *
+ * @param field java.lang.String the name of field to be set
+ * @param newValue java.lang.String the new value for this field
+ *
+ * @see #getDefaultRequestProperty
+ * @see #setDefaultRequestProperty
+ * @see #getRequestProperty
+ */
+public void setRequestProperty(String field, String newValue) {
+ if (connected) {
+ throw new IllegalAccessError(com.ibm.oti.util.Msg.getString("K0092"));
+ }
+ if(field == null) {
+ throw new NullPointerException();
+ }
+ reqHeader.set(field, newValue);
+}
+
+/**
+ * Adds the given request property. Will not overwrite any existing properties associated
+ * with the given field name.
+ *
+ * @param field the request property field name
+ * @param value the property value
+ *
+ * @since 1.4
+ */
+public void addRequestProperty(String field, String value) {
+ if (connected) {
+ throw new IllegalAccessError(com.ibm.oti.util.Msg.getString("K0092"));
+ }
+ if(field == null) {
+ throw new NullPointerException();
+ }
+ reqHeader.add(field, value);
+}
+
+/**
+ * Get the connection port. This is either the URL's port or the
+ * proxy port if a proxy port has been set.
+ */
+private int getHostPort() {
+ if (hostPort != -1) return hostPort;
+ String portString = getSystemPropertyOrAlternative("http.proxyPort", "proxyPort");
+ if (portString != null && usingProxy()) {
+ hostPort = Integer.parseInt(portString);
+ } else {
+ hostPort = url.getPort();
+ }
+
+ if (hostPort < 0) hostPort = defaultPort;
+ return hostPort;
+}
+
+/**
+ * Get the InetAddress of the connection machine. This is either
+ * the address given in the URL or the address of the proxy
+ * server.
+ */
+private InetAddress getHostAddress() throws IOException {
+ return InetAddress.getByName(getHostName());
+}
+
+/**
+ * Get the hostname of the connection machine. This is either
+ * the name given in the URL or the name of the proxy
+ * server.
+ */
+private String getHostName() {
+ if (proxyName != null) {
+ return proxyName;
+ }
+ if (usingProxy()) {
+ proxyName = getSystemPropertyOrAlternative("http.proxyHost", "proxyHost");
+ return proxyName;
+ }
+ return url.getHost();
+}
+
+private String getSystemPropertyOrAlternative(final String key, final String alternativeKey) {
+ String value = getSystemProperty(key);
+ if (value == null) { // For backward compatibility.
+ value = getSystemProperty(alternativeKey);
+ }
+ return value;
+}
+
+private String getSystemProperty(final String property) {
+ return (String)AccessController.doPrivileged(new PriviAction(property));
+}
+
+/**
+ * Answer whether the connection should use a proxy server.
+ *
+ * Need to check both proxy* and http.proxy* because of change between JDK 1.0 and JDK 1.1
+ */
+public boolean usingProxy() {
+ // First check whether the user explicitly set whether to use a proxy.
+ String proxySet = getSystemProperty("http.proxySet");
+ if (proxySet != null) return proxySet.toLowerCase().equals("true");
+
+ proxySet = getSystemProperty("proxySet");
+ if (proxySet != null) return proxySet.toLowerCase().equals("true");
+
+ // The user didn't explicitly set whether to use a proxy. Answer true if the user specified a proxyHost.
+ if (getSystemProperty("http.proxyHost") != null) return true;
+ return getSystemProperty("proxyHost") != null;
+}
+
+/**
+ * Handles an HTTP request along with its redirects and authentication
+ *
+ *
+ */
+void doRequest() throws java.io.IOException {
+ // do nothing if we've already sent the request
+ if (sentRequest) {
+ // If necessary, finish the request by
+ // closing the uncached output stream.
+ if (resHeader == null && os != null) {
+ os.close();
+ readServerResponse();
+ getContentStream();
+ }
+ return;
+ }
+
+ int redirect = 0;
+ while(true) {
+ // send the request and process the results
+ if (!sendRequest()) return;
+
+ // authorization failed ?
+ if (responseCode == HTTP_UNAUTHORIZED) { // keep asking for username/password until authorized
+ String challenge = resHeader.get("WWW-Authenticate");
+ if (challenge == null) break;
+ int idx = challenge.indexOf(" ");
+ String scheme = challenge.substring(0, idx);
+ int realm = challenge.indexOf("realm=\"") + 7;
+ String prompt = null;
+ if (realm != -1) {
+ int end = challenge.indexOf('"', realm);
+ if (end != -1) prompt = challenge.substring(realm, end);
+ }
+
+ // the following will use the user-defined authenticator to get the password
+ PasswordAuthentication pa =
+ Authenticator.requestPasswordAuthentication(getHostAddress(),
+ getHostPort(),
+ url.getProtocol(),
+ prompt,
+ scheme);
+ if (pa == null) break;
+ // drop everything and reconnect, might not be required for HTTP/1.1
+ endRequest();
+ closeSocket();
+ connected = false;
+ // base64 encode the username and password
+ byte[] bytes = (pa.getUserName() + ":" + new String(pa.getPassword())).getBytes("ISO8859_1");
+ String encoded = new String(com.ibm.oti.util.BASE64Encoder.encode(bytes), "ISO8859_1");
+ setRequestProperty("Authorization", scheme + " " + encoded);
+ continue;
+ }
+
+ // See if there is a server redirect to the URL, but only handle 1 level of
+ // URL redirection from the server to avoid being caught in an infinite loop
+ if (getInstanceFollowRedirects()) {
+ if ((responseCode == HTTP_MULT_CHOICE || responseCode == HTTP_MOVED_PERM ||
+ responseCode == HTTP_MOVED_TEMP || responseCode == HTTP_SEE_OTHER ||
+ responseCode == HTTP_USE_PROXY) && os == null) {
+
+ if (++redirect > 4)
+ throw new ProtocolException(com.ibm.oti.util.Msg.getString("K0093"));
+ String location = getHeaderField("Location");
+ if (location != null) {
+ // start over
+ if (responseCode == HTTP_USE_PROXY) {
+ int start = 0;
+ if(location.startsWith(url.getProtocol() + ':'))
+ start = url.getProtocol().length() + 1;
+ if(location.startsWith("//", start))
+ start += 2;
+ setProxy(location.substring(start));
+ }
+ else {
+ url = new URL(url, location);
+ //update the port
+ hostPort = -1;
+ }
+ endRequest();
+ closeSocket();
+ connected = false;
+ continue;
+ }
+ }
+ }
+
+ break;
+ }
+
+ // Cache the content stream and read the first chunked header
+ getContentStream();
+}
+
+private void setProxy(String proxy) {
+ int index = proxy.indexOf(':');
+ if (index == -1) {
+ proxyName = proxy;
+ hostPort = defaultPort;
+ } else {
+ proxyName = proxy.substring(0, index);
+ String port = proxy.substring(index + 1);
+ try {
+ hostPort = Integer.parseInt(port);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(com.ibm.oti.util.Msg.getString("K00af", port));
+ }
+ if (hostPort < 0 || hostPort > 65535)
+ throw new IllegalArgumentException(com.ibm.oti.util.Msg.getString("K00b0"));
+ }
+}
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/jar/Handler.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/jar/Handler.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/jar/Handler.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/jar/Handler.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,94 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.oti.net.www.protocol.jar;
+
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+import com.ibm.oti.util.Msg;
+
+public class Handler extends URLStreamHandler {
+ /**
+ * Answers a connection to the jar file pointed by this <code>URL</code>
+ * in the file system
+ *
+ * @return java.net.URLConnection A connection to the resource pointed by
+ * this url.
+ * @param u
+ * java.net.URL The URL to which the connection is pointing to
+ *
+ * @thows IOException thrown if an IO error occurs when this method tries to
+ * establish connection.
+ */
+ protected URLConnection openConnection(URL u) throws IOException {
+ return new JarURLConnection(u);
+ }
+
+ /**
+ *
+ * @param url
+ * URL the context URL
+ * @param spec
+ * java.lang.String the spec string
+ * @param start
+ * int the location to start parsing from
+ * @param limit
+ * int the location where parsing ends
+ */
+ protected void parseURL(URL url, String spec, int start, int limit) {
+ String file = url.getFile();
+ if (file == null)
+ file = "";
+ if (limit > start)
+ spec = spec.substring(start, limit);
+ else
+ spec = "";
+ if (spec.indexOf("!/") == -1 && (file.indexOf("!/") == -1))
+ throw new NullPointerException(Msg.getString("K01b6"));
+ if (spec.charAt(0) == '/')// File is absolute
+ file = file.substring(0, file.indexOf('!') + 1) + spec;
+ else
+ file = file.substring(0, file.lastIndexOf('/') + 1) + spec;
+ try {
+ // check that the embedded url is valid
+ new URL(file);
+ } catch (MalformedURLException e) {
+ throw new NullPointerException(e.toString());
+ }
+ setURL(url, "jar", "", -1, null, null, file, null, null);
+ }
+
+ /**
+ * Build and return the externalized string representation of url.
+ *
+ * @return String the externalized string representation of url
+ * @param url
+ * a URL
+ */
+ protected String toExternalForm(URL url) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("jar:");
+ sb.append(url.getFile());
+ String ref = url.getRef();
+ if (ref != null)
+ sb.append(ref);
+ return sb.toString();
+ }
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/jar/JarURLConnection.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/jar/JarURLConnection.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/jar/JarURLConnection.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/protocol/jar/JarURLConnection.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,390 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ibm.oti.net.www.protocol.jar;
+
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.TreeSet;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.zip.ZipFile;
+
+import com.ibm.oti.util.Msg;
+import com.ibm.oti.vm.VM;
+
+/**
+ * This subclass extends <code>URLConnection</code>.
+ * <p>
+ *
+ * This class is responsible for connecting and retrieving resources from a Jar
+ * file which can be anywhere that can be refered to by an URL.
+ *
+ */
+public class JarURLConnection extends java.net.JarURLConnection {
+ static Hashtable jarCache = new Hashtable();
+
+ InputStream jarInput;
+
+ private JarFile jarFile;
+
+ private JarEntry jarEntry;
+
+ ReferenceQueue cacheQueue = new ReferenceQueue();
+
+ static TreeSet lru = new TreeSet(new LRUComparitor());
+
+ static int Limit;
+ static {
+ Limit = ((Integer) AccessController
+ .doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return Integer.getInteger("jar.cacheSize", 500);
+ }
+ })).intValue();
+ VM.closeJars();
+ }
+
+ static final class CacheEntry extends WeakReference {
+ Object key;
+
+ CacheEntry(Object jar, String key, ReferenceQueue queue) {
+ super(jar, queue);
+ this.key = key;
+ }
+ }
+
+ static final class LRUKey {
+ JarFile jar;
+
+ long ts;
+
+ LRUKey(JarFile file, long time) {
+ jar = file;
+ ts = time;
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ return jar == ((LRUKey) obj).jar;
+ }
+ }
+
+ static final class LRUComparitor implements Comparator {
+ LRUComparitor() {
+ }
+
+ /**
+ * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+ */
+ public int compare(Object o1, Object o2) {
+ if (((LRUKey) o1).ts > ((LRUKey) o2).ts) {
+ return 1;
+ }
+ return ((LRUKey) o1).ts == ((LRUKey) o2).ts ? 0 : -1;
+ }
+
+ /**
+ * @param o1
+ * an object to compare
+ * @param o2
+ * an object to compare
+ * @return <code>true</code> if the objects are equal,
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object o1, Object o2) {
+ return o1.equals(o2);
+ }
+ }
+
+ /**
+ * @param url
+ * the URL of the JAR
+ * @throws java.net.MalformedURLException
+ * if the URL is malformed
+ */
+ public JarURLConnection(java.net.URL url)
+ throws java.net.MalformedURLException {
+ super(url);
+ }
+
+ /**
+ * @see java.net.URLConnection#connect()
+ */
+ public void connect() throws IOException {
+ jarFileURLConnection = getJarFileURL().openConnection();
+ findJarFile(); // ensure the file can be found
+ findJarEntry(); // ensure the entry, if any, can be found
+ connected = true;
+ }
+
+ /**
+ * Answers the Jar file refered by this <code>URLConnection</code>
+ *
+ * @return the JAR file referenced by this connection
+ *
+ * @throws IOException
+ * thrown if an IO error occurs while connecting to the
+ * resource.
+ */
+ public JarFile getJarFile() throws IOException {
+ if (!connected)
+ connect();
+ return jarFile;
+ }
+
+ /**
+ * Answers the Jar file refered by this <code>URLConnection</code>
+ *
+ * @throws IOException
+ * if an IO error occurs while connecting to the resource.
+ */
+ private void findJarFile() throws IOException {
+ URL jarFileURL = getJarFileURL();
+ if (jarFileURL.getProtocol().equals("file")) {
+ String fileName = jarFileURL.getFile();
+ String host = jarFileURL.getHost();
+ if (host != null && host.length() > 0)
+ fileName = "//" + host + fileName;
+ jarFile = openJarFile(fileName, fileName, false);
+ return;
+ }
+
+ final String externalForm = jarFileURLConnection.getURL()
+ .toExternalForm();
+ jarFile = (JarFile) AccessController
+ .doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ try {
+ return openJarFile(null, externalForm, false);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ });
+ if (jarFile != null)
+ return;
+
+ // Build a temp jar file
+ final InputStream is = jarFileURLConnection.getInputStream();
+ try {
+ jarFile = (JarFile) AccessController
+ .doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ try {
+ File tempJar = File.createTempFile("hyjar_",
+ ".tmp", null);
+ FileOutputStream fos = new FileOutputStream(
+ tempJar);
+ byte[] buf = new byte[4096];
+ int nbytes = 0;
+ while ((nbytes = is.read(buf)) > -1)
+ fos.write(buf, 0, nbytes);
+ fos.close();
+ String path = tempJar.getPath();
+ return openJarFile(path, externalForm, true);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ });
+ } finally {
+ is.close();
+ }
+ if (jarFile == null)
+ throw new IOException();
+ }
+
+ JarFile openJarFile(String fileString, String key, boolean temp)
+ throws IOException {
+ CacheEntry entry;
+ while ((entry = (CacheEntry) cacheQueue.poll()) != null)
+ jarCache.remove(entry.key);
+ entry = (CacheEntry) jarCache.get(key);
+ JarFile jar = null;
+ if (entry != null)
+ jar = (JarFile) entry.get();
+ if (jar == null && fileString != null) {
+ int flags = ZipFile.OPEN_READ + (temp ? ZipFile.OPEN_DELETE : 0);
+ jar = new JarFile(new File(fileString), true, flags);
+ jarCache.put(key, new CacheEntry(jar, key, cacheQueue));
+ } else {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkPermission(getPermission());
+ if (temp)
+ lru.remove(new LRUKey(jar, 0));
+ }
+ if (temp) {
+ lru.add(new LRUKey(jar, new Date().getTime()));
+ if (lru.size() > Limit)
+ lru.remove(lru.first());
+ }
+ return jar;
+ }
+
+ /**
+ * Answers the JarEntry of the entry referenced by this
+ * <code>URLConnection</code>.
+ *
+ * @return java.util.jar.JarEntry the JarEntry referenced
+ *
+ * @throws IOException
+ * if an IO error occurs while getting the entry
+ */
+ public JarEntry getJarEntry() throws IOException {
+ if (!connected)
+ connect();
+ return jarEntry;
+
+ }
+
+ /**
+ * Look up the JarEntry of the entry referenced by this
+ * <code>URLConnection</code>.
+ */
+ private void findJarEntry() throws IOException {
+ if (getEntryName() == null)
+ return;
+ jarEntry = jarFile.getJarEntry(getEntryName());
+ if (jarEntry == null)
+ throw new FileNotFoundException(getEntryName());
+ }
+
+ /**
+ * Creates an input stream for reading from this URL Connection.
+ *
+ * @return the input stream
+ *
+ * @throws IOException
+ * if an IO error occurs while connecting to the resource.
+ */
+ public InputStream getInputStream() throws IOException {
+ if (!connected)
+ connect();
+ if (jarInput != null)
+ return jarInput;
+ if (jarEntry == null)
+ throw new IOException(Msg.getString("K00fc"));
+ return jarInput = jarFile.getInputStream(jarEntry);
+ }
+
+ /**
+ * Answers the content type of the resource. Test cases reveal that only if
+ * the URL is refering to a Jar file, that this method answers a non-null
+ * value - x-java/jar.
+ *
+ * @return the content type
+ */
+ public String getContentType() {
+ // it could also return "x-java/jar" which jdk returns but here, we get
+ // it from the URLConnection
+ try {
+ if (url.getFile().endsWith("!/"))
+ return getJarFileURL().openConnection().getContentType();
+ } catch (IOException ioe) {
+ }
+ // if there is an Jar Entry, get the content type from the name
+ return guessContentTypeFromName(url.getFile());
+ }
+
+ /**
+ * Answers the content length of the resource. Test cases reveal that if the
+ * URL is refering to a Jar file, this method answers a content-length
+ * returned by URLConnection. If not, it will return -1.
+ *
+ * @return the content length
+ */
+ public int getContentLength() {
+ try {
+ if (url.getFile().endsWith("!/"))
+ return getJarFileURL().openConnection().getContentLength();
+ } catch (IOException e) {
+ }
+ return -1;
+ }
+
+ /**
+ * Answers the object pointed by this <code>URL</code>. If this
+ * URLConnection is pointing to a Jar File (no Jar Entry), this method will
+ * return a <code>JarFile</code> If there is a Jar Entry, it will return
+ * the object corresponding to the Jar entry content type.
+ *
+ * @return a non-null object
+ *
+ * @throws IOException
+ * if an IO error occured
+ *
+ * @see ContentHandler
+ * @see ContentHandlerFactory
+ * @see java.io.IOException
+ * @see #setContentHandlerFactory(ContentHandlerFactory)
+ */
+ public Object getContent() throws java.io.IOException {
+ if (!connected)
+ connect();
+ // if there is no Jar Entry, return a JarFile
+ if (jarEntry == null)
+ return jarFile;
+ return super.getContent();
+ }
+
+ /**
+ * Answers the permission, in this case the subclass, FilePermission object
+ * which represents the permission necessary for this URLConnection to
+ * establish the connection.
+ *
+ * @return the permission required for this URLConnection.
+ *
+ * @throws IOException
+ * thrown when an IO exception occurs while creating the
+ * permission.
+ */
+ public java.security.Permission getPermission() throws IOException {
+ if (jarFileURLConnection != null)
+ return jarFileURLConnection.getPermission();
+ return getJarFileURL().openConnection().getPermission();
+ }
+
+ /**
+ * Closes the cached files.
+ */
+ public static void closeCachedFiles() {
+ java.util.Enumeration elemEnum = jarCache.elements();
+ while (elemEnum.hasMoreElements()) {
+ try {
+ ZipFile zip = (ZipFile) ((CacheEntry) elemEnum.nextElement())
+ .get();
+ if (zip != null)
+ zip.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/types.properties
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/types.properties?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/types.properties (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/com/ibm/oti/net/www/types.properties Wed Nov 30 21:29:27 2005
@@ -0,0 +1,20 @@
+/*[INCLUDE-IF mJava14]*/
+#
+# Licensed Materials - Property of IBM,
+# (c) Copyright IBM Corp. 1998, 2004 All Rights Reserved
+#
+
+#
+# This file can be used to alter or augment the default
+# mapping between file extensions and MIME types. It uses
+# the standard properties file format as shown below.
+#
+
+# Text types.
+text=text/plain
+txt=text/plain
+htm=text/html
+html=text/html
+gif=image/gif
+jpg=image/jpeg
+png=image/png