1 /* 2 * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package sun.net; 26 27 import java.net.URL; 28 29 /** 30 * ProgressSource represents the source of progress changes. 31 * 32 * @author Stanley Man-Kit Ho 33 */ 34 public class ProgressSource 35 { 36 public enum State { NEW, CONNECTED, UPDATE, DELETE }; 37 38 // URL 39 private URL url; 40 // URL method 41 private String method; 42 // Content type 43 private String contentType; 44 // bytes read 45 private long progress = 0; 46 // last bytes read 47 private long lastProgress = 0; 48 //bytes expected 49 private long expected = -1; 50 // the last thing to happen with this source 51 private State state; 52 // connect flag 53 private boolean connected = false; 54 // threshold for notification 55 private int threshold = 8192; 56 // progress monitor 57 private ProgressMonitor progressMonitor; 58 59 /** 60 * Construct progress source object. 61 */ 62 public ProgressSource(URL url, String method) { 63 this(url, method, -1); 64 } 65 66 /** 67 * Construct progress source object. 68 */ 69 public ProgressSource(URL url, String method, long expected) { 70 this.url = url; 71 this.method = method; 72 this.contentType = "content/unknown"; 73 this.progress = 0; 74 this.lastProgress = 0; 75 this.expected = expected; 76 this.state = State.NEW; 77 this.progressMonitor = ProgressMonitor.getDefault(); 78 this.threshold = progressMonitor.getProgressUpdateThreshold(); 79 } 80 81 public boolean connected() { 82 if (!connected) { 83 connected = true; 84 state = State.CONNECTED; 85 return false; 86 } 87 return true; 88 } 89 90 /** 91 * Close progress source. 92 */ 93 public void close() { 94 state = State.DELETE; 95 } 96 97 /** 98 * Return URL of progress source. 99 */ 100 public URL getURL() { 101 return url; 102 } 103 104 /** 105 * Return method of URL. 106 */ 107 public String getMethod() { 108 return method; 109 } 110 111 /** 112 * Return content type of URL. 113 */ 114 public String getContentType() { 115 return contentType; 116 } 117 118 // Change content type 119 public void setContentType(String ct) { 120 contentType = ct; 121 } 122 123 /** 124 * Return current progress. 125 */ 126 public long getProgress() { 127 return progress; 128 } 129 130 /** 131 * Return expected maximum progress; -1 if expected is unknown. 132 */ 133 public long getExpected() { 134 return expected; 135 } 136 137 /** 138 * Return state. 139 */ 140 public State getState() { 141 return state; 142 } 143 144 /** 145 * Begin progress tracking. 146 */ 147 public void beginTracking() { 148 progressMonitor.registerSource(this); 149 } 150 151 /** 152 * Finish progress tracking. 153 */ 154 public void finishTracking() { 155 progressMonitor.unregisterSource(this); 156 } 157 158 /** 159 * Update progress. 160 */ 161 public void updateProgress(long latestProgress, long expectedProgress) { 162 lastProgress = progress; 163 progress = latestProgress; 164 expected = expectedProgress; 165 166 if (connected() == false) 167 state = State.CONNECTED; 168 else 169 state = State.UPDATE; 170 171 // The threshold effectively divides the progress into 172 // different set of ranges: 173 // 174 // Range 0: 0..threshold-1, 175 // Range 1: threshold .. 2*threshold-1 176 // .... 177 // Range n: n*threshold .. (n+1)*threshold-1 178 // 179 // To determine which range the progress belongs to, it 180 // would be calculated as follow: 181 // 182 // range number = progress / threshold 183 // 184 // Notification should only be triggered when the current 185 // progress and the last progress are in different ranges, 186 // i.e. they have different range numbers. 187 // 188 // Using this range scheme, notification will be generated 189 // only once when the progress reaches each range. 190 // 191 if (lastProgress / threshold != progress / threshold) { 192 progressMonitor.updateProgress(this); 193 } 194 195 // Detect read overrun 196 if (expected != -1) { 197 if (progress >= expected && progress != 0) 198 close(); 199 } 200 } 201 202 public Object clone() throws CloneNotSupportedException { 203 return super.clone(); 204 } 205 206 public String toString() { 207 return getClass().getName() + "[url=" + url + ", method=" + method + ", state=" + state 208 + ", content-type=" + contentType + ", progress=" + progress + ", expected=" + expected + "]"; 209 } 210 } 211