001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU General
007: * Public License Version 2 only ("GPL") or the Common Development and Distribution
008: * License("CDDL") (collectively, the "License"). You may not use this file except in
009: * compliance with the License. You can obtain a copy of the License at
010: * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the
011: * License for the specific language governing permissions and limitations under the
012: * License. When distributing the software, include this License Header Notice in
013: * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun
014: * designates this particular file as subject to the "Classpath" exception as
015: * provided by Sun in the GPL Version 2 section of the License file that
016: * accompanied this code. If applicable, add the following below the License Header,
017: * with the fields enclosed by brackets [] replaced by your own identifying
018: * information: "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Contributor(s):
021: *
022: * The Original Software is NetBeans. The Initial Developer of the Original Software
023: * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All
024: * Rights Reserved.
025: *
026: * If you wish your version of this file to be governed by only the CDDL or only the
027: * GPL Version 2, indicate your decision by adding "[Contributor] elects to include
028: * this software in this distribution under the [CDDL or GPL Version 2] license." If
029: * you do not indicate a single choice of license, a recipient has the option to
030: * distribute your version of this file under either the CDDL, the GPL Version 2 or
031: * to extend the choice of license to its licensees as provided above. However, if
032: * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then
033: * the option applies only if the new code is made subject to such option by the
034: * copyright holder.
035: */
036:
037: package org.netbeans.installer.downloader.impl;
038:
039: import java.io.IOException;
040: import java.io.InputStream;
041: import java.io.OutputStream;
042: import java.net.URL;
043: import java.net.URLConnection;
044: import java.util.Date;
045: import org.netbeans.installer.downloader.DownloadConfig;
046: import org.netbeans.installer.downloader.Pumping;
047: import org.netbeans.installer.downloader.connector.URLConnector;
048: import org.netbeans.installer.downloader.dispatcher.Process;
049: import org.netbeans.installer.utils.LogManager;
050: import org.netbeans.installer.utils.StreamUtils;
051:
052: /**
053: * @author Danila_Dugurov
054: */
055: public class Pump implements Process {
056: /////////////////////////////////////////////////////////////////////////////////
057: // Instance
058: final PumpingImpl pumping;
059: URLConnector connector = URLConnector.getConnector();
060:
061: InputStream in;
062: OutputStream out;
063:
064: public Pump(Pumping pumping) {
065: this .pumping = (PumpingImpl) pumping;
066: }
067:
068: public PumpingImpl pumping() {
069: return pumping;
070: }
071:
072: public void init() {
073: }
074:
075: public void run() {
076: if (!initPumping())
077: return;
078: pumping.fireChanges("pumpingUpdate");
079: if (!processPumping())
080: return;
081: }
082:
083: private boolean initPumping() {
084: int attemptCount = 0;
085: while (attemptCount < MAX_ATTEMPT_COUNT) {
086: pumping.changeState(Pumping.State.CONNECTING);
087: try {
088: final URL url = pumping.declaredURL();
089: URLConnection connection = connector
090: .establishConnection(url);
091: in = connection.getInputStream();
092: if (exitOnInterrupt())
093: return false;
094: initPumping(connection);
095: pumping.changeState(Pumping.State.WAITING);
096: return true;
097: } catch (IOException ex) {
098: LogManager.log(ex);
099: attemptCount++;
100: try {
101: pumping.changeState(Pumping.State.WAITING);
102: Thread.sleep(ATTEMPT_TIME_DELAY);
103: } catch (InterruptedException exit) {
104: pumping.changeState(Pumping.State.INTERRUPTED);
105: return false;
106: }
107: } finally {
108: try {
109: if (in != null)
110: in.close();
111: } catch (IOException ignored) {
112: LogManager.log(ignored);
113: }
114: }
115: }
116: pumping.changeState(Pumping.State.FAILED);
117: return false;
118: }
119:
120: private void initPumping(URLConnection connection)
121: throws IOException {
122: final Date lastModif = new Date(connection.getLastModified());
123: final URL realUrl = connection.getURL();
124: final String accept = connection
125: .getHeaderField("Accept-Ranges");
126: final boolean acceptBytes = accept != null ? accept
127: .contains("bytes") : false;
128: final long length = connection.getContentLength();
129: pumping.init(realUrl, length, lastModif, acceptBytes);
130: }
131:
132: private boolean processPumping() {
133: int attemptCount = 0;
134: while (attemptCount < MAX_ATTEMPT_COUNT) {
135: pumping
136: .changeState(org.netbeans.installer.downloader.Pumping.State.CONNECTING);
137: try {
138: final SectionImpl section = pumping.getSection();
139: final URL connectingUrl = pumping.realURL();
140: URLConnection connection = connector
141: .establishConnection(connectingUrl, section
142: .headers());
143: in = connection.getInputStream();
144: if (exitOnInterrupt())
145: return false;
146: out = ChannelUtil.channelFragmentAsStream(pumping
147: .outputFile(), section);
148: pumping.changeState(Pumping.State.PUMPING);
149: StreamUtils.transferData(in, out);
150: if (section.length() > 0) {
151: if (section.offset() != section.start()
152: + section.length()) {
153: attemptCount++;
154: continue;
155: }
156: }
157: pumping.changeState(Pumping.State.FINISHED);
158: return true;
159: } catch (IOException ex) {
160: LogManager.log(ex);
161: if (exitOnInterrupt())
162: return false;
163: attemptCount++;
164: try {
165: pumping.changeState(Pumping.State.WAITING);
166: Thread.sleep(ATTEMPT_TIME_DELAY);
167: } catch (InterruptedException exit) {
168: pumping.changeState(Pumping.State.INTERRUPTED);
169: return false;
170: }
171: } finally {
172: if (in != null)
173: try {
174: in.close();
175: } catch (IOException ignored) {
176: LogManager.log(ignored);
177: }
178: if (out != null)
179: try {
180: out.close();
181: } catch (IOException ignored) {
182: LogManager.log(ignored);
183: }
184: }
185: }
186: pumping.changeState(Pumping.State.FAILED);
187: return false;
188: }
189:
190: private boolean exitOnInterrupt() {
191: if (!Thread.interrupted())
192: return false;
193: pumping.changeState(Pumping.State.INTERRUPTED);
194: return true;
195: }
196:
197: public void terminate() {
198: if (in != null)
199: try {
200: in.close();
201: } catch (IOException ignored) {
202: LogManager.log(ignored);
203: }
204: if (out != null)
205: try {
206: out.close();
207: } catch (IOException ignored) {
208: LogManager.log(ignored);
209: }
210: }
211:
212: /////////////////////////////////////////////////////////////////////////////////
213: // Constants
214: private static final int ATTEMPT_TIME_DELAY = DownloadConfig.REATTEMPT_DELAY;
215: private static final int MAX_ATTEMPT_COUNT = DownloadConfig.ATTEMPT_COUNT;
216: }
|