001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.ivy.util.url;
019:
020: import java.io.ByteArrayInputStream;
021: import java.io.ByteArrayOutputStream;
022: import java.io.File;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.net.HttpURLConnection;
026: import java.net.URL;
027: import java.net.URLConnection;
028: import java.net.UnknownHostException;
029:
030: import org.apache.ivy.util.CopyProgressListener;
031: import org.apache.ivy.util.FileUtil;
032: import org.apache.ivy.util.Message;
033:
034: /**
035: *
036: */
037: public class BasicURLHandler extends AbstractURLHandler {
038:
039: private static final int BUFFER_SIZE = 64 * 1024;
040:
041: private static class HttpStatus {
042: static final int SC_OK = 200;
043:
044: static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
045: }
046:
047: public BasicURLHandler() {
048: Message.debug("installing "
049: + IvyAuthenticator.INSTANCE.getClass()); // do not remove,
050: // ensure
051: // IvyAuthenticator
052: // class loading!
053: }
054:
055: public URLInfo getURLInfo(URL url) {
056: return getURLInfo(url, 0);
057: }
058:
059: public URLInfo getURLInfo(URL url, int timeout) {
060: URLConnection con = null;
061: try {
062: con = url.openConnection();
063: if (con instanceof HttpURLConnection) {
064: ((HttpURLConnection) con).setRequestMethod("HEAD");
065: int status = ((HttpURLConnection) con)
066: .getResponseCode();
067: if (status == HttpStatus.SC_OK) {
068: return new URLInfo(true, ((HttpURLConnection) con)
069: .getContentLength(), con.getLastModified());
070: }
071: if (status == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) {
072: Message.warn("Your proxy requires authentication.");
073: } else if (String.valueOf(status).startsWith("4")) {
074: Message.verbose("CLIENT ERROR: "
075: + ((HttpURLConnection) con)
076: .getResponseMessage() + " url="
077: + url);
078: } else if (String.valueOf(status).startsWith("5")) {
079: Message.error("SERVER ERROR: "
080: + ((HttpURLConnection) con)
081: .getResponseMessage() + " url="
082: + url);
083: }
084: Message.debug("HTTP response status: " + status
085: + " url=" + url);
086: } else {
087: int contentLength = con.getContentLength();
088: if (contentLength <= 0) {
089: return UNAVAILABLE;
090: } else {
091: return new URLInfo(true, contentLength, con
092: .getLastModified());
093: }
094: }
095: } catch (UnknownHostException e) {
096: Message.warn("Host " + e.getMessage() + " not found. url="
097: + url);
098: Message
099: .info("You probably access the destination server through "
100: + "a proxy server that is not well configured.");
101: } catch (IOException e) {
102: Message.error("Server access Error: " + e.getMessage()
103: + " url=" + url);
104: } finally {
105: disconnect(con);
106: }
107: return UNAVAILABLE;
108: }
109:
110: public InputStream openStream(URL url) throws IOException {
111: URLConnection conn = null;
112: InputStream inStream = null;
113: try {
114: conn = url.openConnection();
115: inStream = conn.getInputStream();
116: ByteArrayOutputStream outStream = new ByteArrayOutputStream();
117:
118: byte[] buffer = new byte[BUFFER_SIZE];
119: int len;
120: while ((len = inStream.read(buffer)) > 0) {
121: outStream.write(buffer, 0, len);
122: }
123: return new ByteArrayInputStream(outStream.toByteArray());
124: } finally {
125: if (inStream != null) {
126: inStream.close();
127: }
128:
129: disconnect(conn);
130: }
131: }
132:
133: public void download(URL src, File dest, CopyProgressListener l)
134: throws IOException {
135: URLConnection srcConn = null;
136: try {
137: srcConn = src.openConnection();
138: int contentLength = srcConn.getContentLength();
139: FileUtil.copy(srcConn.getInputStream(), dest, l);
140: if (dest.length() != contentLength && contentLength != -1) {
141: dest.delete();
142: throw new IOException(
143: "Downloaded file size doesn't match expected Content Length for "
144: + src + ". Please retry.");
145: }
146: } finally {
147: disconnect(srcConn);
148: }
149: }
150:
151: private void disconnect(URLConnection con) {
152: if (con instanceof HttpURLConnection) {
153: ((HttpURLConnection) con).disconnect();
154: } else if (con != null
155: && "sun.net.www.protocol.file.FileURLConnection"
156: .equals(con.getClass().getName())) {
157: // ugly fix for a sun jre bug:
158: // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4257700
159: //
160: // getting header info on the fileurlconnection opens the connection,
161: // which opens a file input stream without closing it.
162: try {
163: con.getInputStream().close();
164: } catch (IOException e) {
165: // ignored
166: }
167: }
168: }
169:
170: }
|