mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8297976: Remove sun.net.ProgressMonitor and related classes
8240275: Occasional errors in HttpURLConnection due to race with GC Reviewed-by: jpai, dfuchs, michaelm
This commit is contained in:
parent
085f96cb1a
commit
27bbe7be2c
14 changed files with 313 additions and 894 deletions
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code 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 in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package sun.net;
|
|
||||||
|
|
||||||
import java.util.EventObject;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ProgressEvent represents an progress event in monitering network input stream.
|
|
||||||
*
|
|
||||||
* @author Stanley Man-Kit Ho
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("serial") // never serialized
|
|
||||||
public class ProgressEvent extends EventObject {
|
|
||||||
// URL of the stream
|
|
||||||
private URL url;
|
|
||||||
// content type of the stream
|
|
||||||
private String contentType;
|
|
||||||
// method associated with URL
|
|
||||||
private String method;
|
|
||||||
// bytes read
|
|
||||||
private long progress;
|
|
||||||
// bytes expected
|
|
||||||
private long expected;
|
|
||||||
// the last thing to happen
|
|
||||||
private ProgressSource.State state;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a ProgressEvent object.
|
|
||||||
*/
|
|
||||||
public ProgressEvent(ProgressSource source, URL url, String method, String contentType, ProgressSource.State state, long progress, long expected) {
|
|
||||||
super(source);
|
|
||||||
this.url = url;
|
|
||||||
this.method = method;
|
|
||||||
this.contentType = contentType;
|
|
||||||
this.progress = progress;
|
|
||||||
this.expected = expected;
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return URL related to the progress.
|
|
||||||
*/
|
|
||||||
public URL getURL()
|
|
||||||
{
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return method associated with URL.
|
|
||||||
*/
|
|
||||||
public String getMethod()
|
|
||||||
{
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return content type of the URL.
|
|
||||||
*/
|
|
||||||
public String getContentType()
|
|
||||||
{
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return current progress value.
|
|
||||||
*/
|
|
||||||
public long getProgress()
|
|
||||||
{
|
|
||||||
return progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return expected maximum progress value; -1 if expected is unknown.
|
|
||||||
*/
|
|
||||||
public long getExpected() {
|
|
||||||
return expected;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return state.
|
|
||||||
*/
|
|
||||||
public ProgressSource.State getState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return getClass().getName() + "[url=" + url + ", method=" + method + ", state=" + state
|
|
||||||
+ ", content-type=" + contentType + ", progress=" + progress + ", expected=" + expected + "]";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code 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 in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package sun.net;
|
|
||||||
|
|
||||||
import java.util.EventListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ProgressListener is an interface to be implemented by parties
|
|
||||||
* interested to be notified of progress in network input stream.
|
|
||||||
*
|
|
||||||
* @author Stanley Man-Kit Ho
|
|
||||||
*/
|
|
||||||
public interface ProgressListener extends EventListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Start progress.
|
|
||||||
*/
|
|
||||||
public void progressStart(ProgressEvent evt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update progress.
|
|
||||||
*/
|
|
||||||
public void progressUpdate(ProgressEvent evt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finish progress.
|
|
||||||
*/
|
|
||||||
public void progressFinish(ProgressEvent evt);
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code 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 in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package sun.net;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ProgressMeteringPolicy is an interface for determining progress metering policy.
|
|
||||||
*
|
|
||||||
* @author Stanley Man-Kit Ho
|
|
||||||
*/
|
|
||||||
public interface ProgressMeteringPolicy
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Return true if metering should be turned on for a particular network input stream.
|
|
||||||
*/
|
|
||||||
public boolean shouldMeterInput(URL url, String method);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return update notification threshold.
|
|
||||||
*/
|
|
||||||
public int getProgressUpdateThreshold();
|
|
||||||
}
|
|
|
@ -1,246 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code 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 in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.net;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ProgressMonitor is a class for monitoring progress in network input stream.
|
|
||||||
*
|
|
||||||
* @author Stanley Man-Kit Ho
|
|
||||||
*/
|
|
||||||
public class ProgressMonitor
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Return default ProgressMonitor.
|
|
||||||
*/
|
|
||||||
public static synchronized ProgressMonitor getDefault() {
|
|
||||||
return pm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change default ProgressMonitor implementation.
|
|
||||||
*/
|
|
||||||
public static synchronized void setDefault(ProgressMonitor m) {
|
|
||||||
if (m != null)
|
|
||||||
pm = m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change progress metering policy.
|
|
||||||
*/
|
|
||||||
public static synchronized void setMeteringPolicy(ProgressMeteringPolicy policy) {
|
|
||||||
if (policy != null)
|
|
||||||
meteringPolicy = policy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a snapshot of the ProgressSource list
|
|
||||||
*/
|
|
||||||
public ArrayList<ProgressSource> getProgressSources() {
|
|
||||||
ArrayList<ProgressSource> snapshot = new ArrayList<>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
synchronized(progressSourceList) {
|
|
||||||
for (ProgressSource pi : progressSourceList) {
|
|
||||||
// Clone ProgressSource and add to snapshot
|
|
||||||
snapshot.add((ProgressSource)pi.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(CloneNotSupportedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return snapshot;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return update notification threshold
|
|
||||||
*/
|
|
||||||
public synchronized int getProgressUpdateThreshold() {
|
|
||||||
return meteringPolicy.getProgressUpdateThreshold();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if metering should be turned on
|
|
||||||
* for a particular URL input stream.
|
|
||||||
*/
|
|
||||||
public boolean shouldMeterInput(URL url, String method) {
|
|
||||||
return meteringPolicy.shouldMeterInput(url, method);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register progress source when progress is began.
|
|
||||||
*/
|
|
||||||
public void registerSource(ProgressSource pi) {
|
|
||||||
|
|
||||||
synchronized(progressSourceList) {
|
|
||||||
if (progressSourceList.contains(pi))
|
|
||||||
return;
|
|
||||||
|
|
||||||
progressSourceList.add(pi);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify only if there is at least one listener
|
|
||||||
if (progressListenerList.size() > 0)
|
|
||||||
{
|
|
||||||
// Notify progress listener if there is progress change
|
|
||||||
ArrayList<ProgressListener> listeners;
|
|
||||||
|
|
||||||
// Copy progress listeners to another list to avoid holding locks
|
|
||||||
synchronized(progressListenerList) {
|
|
||||||
listeners = new ArrayList<>(progressListenerList);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fire event on each progress listener
|
|
||||||
for (ProgressListener pl : listeners) {
|
|
||||||
ProgressEvent pe = new ProgressEvent(pi, pi.getURL(), pi.getMethod(), pi.getContentType(), pi.getState(), pi.getProgress(), pi.getExpected());
|
|
||||||
pl.progressStart(pe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregister progress source when progress is finished.
|
|
||||||
*/
|
|
||||||
public void unregisterSource(ProgressSource pi) {
|
|
||||||
|
|
||||||
synchronized(progressSourceList) {
|
|
||||||
// Return if ProgressEvent does not exist
|
|
||||||
if (progressSourceList.contains(pi) == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Close entry and remove from map
|
|
||||||
pi.close();
|
|
||||||
progressSourceList.remove(pi);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify only if there is at least one listener
|
|
||||||
if (progressListenerList.size() > 0)
|
|
||||||
{
|
|
||||||
// Notify progress listener if there is progress change
|
|
||||||
ArrayList<ProgressListener> listeners;
|
|
||||||
|
|
||||||
// Copy progress listeners to another list to avoid holding locks
|
|
||||||
synchronized(progressListenerList) {
|
|
||||||
listeners = new ArrayList<>(progressListenerList);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fire event on each progress listener
|
|
||||||
for (ProgressListener pl : listeners) {
|
|
||||||
ProgressEvent pe = new ProgressEvent(pi, pi.getURL(), pi.getMethod(), pi.getContentType(), pi.getState(), pi.getProgress(), pi.getExpected());
|
|
||||||
pl.progressFinish(pe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Progress source is updated.
|
|
||||||
*/
|
|
||||||
public void updateProgress(ProgressSource pi) {
|
|
||||||
|
|
||||||
synchronized (progressSourceList) {
|
|
||||||
if (progressSourceList.contains(pi) == false)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify only if there is at least one listener
|
|
||||||
if (progressListenerList.size() > 0)
|
|
||||||
{
|
|
||||||
// Notify progress listener if there is progress change
|
|
||||||
ArrayList<ProgressListener> listeners;
|
|
||||||
|
|
||||||
// Copy progress listeners to another list to avoid holding locks
|
|
||||||
synchronized(progressListenerList) {
|
|
||||||
listeners = new ArrayList<>(progressListenerList);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fire event on each progress listener
|
|
||||||
for (ProgressListener pl : listeners) {
|
|
||||||
ProgressEvent pe = new ProgressEvent(pi, pi.getURL(), pi.getMethod(), pi.getContentType(), pi.getState(), pi.getProgress(), pi.getExpected());
|
|
||||||
pl.progressUpdate(pe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add progress listener in progress monitor.
|
|
||||||
*/
|
|
||||||
public void addProgressListener(ProgressListener l) {
|
|
||||||
synchronized(progressListenerList) {
|
|
||||||
progressListenerList.add(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove progress listener from progress monitor.
|
|
||||||
*/
|
|
||||||
public void removeProgressListener(ProgressListener l) {
|
|
||||||
synchronized(progressListenerList) {
|
|
||||||
progressListenerList.remove(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metering policy
|
|
||||||
private static ProgressMeteringPolicy meteringPolicy = new DefaultProgressMeteringPolicy();
|
|
||||||
|
|
||||||
// Default implementation
|
|
||||||
private static ProgressMonitor pm = new ProgressMonitor();
|
|
||||||
|
|
||||||
// ArrayList for outstanding progress sources
|
|
||||||
private ArrayList<ProgressSource> progressSourceList = new ArrayList<ProgressSource>();
|
|
||||||
|
|
||||||
// ArrayList for progress listeners
|
|
||||||
private ArrayList<ProgressListener> progressListenerList = new ArrayList<ProgressListener>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default progress metering policy.
|
|
||||||
*/
|
|
||||||
class DefaultProgressMeteringPolicy implements ProgressMeteringPolicy {
|
|
||||||
/**
|
|
||||||
* Return true if metering should be turned on for a particular network input stream.
|
|
||||||
*/
|
|
||||||
public boolean shouldMeterInput(URL url, String method)
|
|
||||||
{
|
|
||||||
// By default, no URL input stream is metered for
|
|
||||||
// performance reason.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return update notification threshold.
|
|
||||||
*/
|
|
||||||
public int getProgressUpdateThreshold() {
|
|
||||||
// 8K - same as default I/O buffer size
|
|
||||||
return 8192;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,210 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code 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 in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package sun.net;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ProgressSource represents the source of progress changes.
|
|
||||||
*
|
|
||||||
* @author Stanley Man-Kit Ho
|
|
||||||
*/
|
|
||||||
public class ProgressSource
|
|
||||||
{
|
|
||||||
public enum State { NEW, CONNECTED, UPDATE, DELETE };
|
|
||||||
|
|
||||||
// URL
|
|
||||||
private URL url;
|
|
||||||
// URL method
|
|
||||||
private String method;
|
|
||||||
// Content type
|
|
||||||
private String contentType;
|
|
||||||
// bytes read
|
|
||||||
private long progress = 0;
|
|
||||||
// last bytes read
|
|
||||||
private long lastProgress = 0;
|
|
||||||
//bytes expected
|
|
||||||
private long expected = -1;
|
|
||||||
// the last thing to happen with this source
|
|
||||||
private State state;
|
|
||||||
// connect flag
|
|
||||||
private boolean connected = false;
|
|
||||||
// threshold for notification
|
|
||||||
private int threshold = 8192;
|
|
||||||
// progress monitor
|
|
||||||
private ProgressMonitor progressMonitor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct progress source object.
|
|
||||||
*/
|
|
||||||
public ProgressSource(URL url, String method) {
|
|
||||||
this(url, method, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct progress source object.
|
|
||||||
*/
|
|
||||||
public ProgressSource(URL url, String method, long expected) {
|
|
||||||
this.url = url;
|
|
||||||
this.method = method;
|
|
||||||
this.contentType = "content/unknown";
|
|
||||||
this.progress = 0;
|
|
||||||
this.lastProgress = 0;
|
|
||||||
this.expected = expected;
|
|
||||||
this.state = State.NEW;
|
|
||||||
this.progressMonitor = ProgressMonitor.getDefault();
|
|
||||||
this.threshold = progressMonitor.getProgressUpdateThreshold();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean connected() {
|
|
||||||
if (!connected) {
|
|
||||||
connected = true;
|
|
||||||
state = State.CONNECTED;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close progress source.
|
|
||||||
*/
|
|
||||||
public void close() {
|
|
||||||
state = State.DELETE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return URL of progress source.
|
|
||||||
*/
|
|
||||||
public URL getURL() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return method of URL.
|
|
||||||
*/
|
|
||||||
public String getMethod() {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return content type of URL.
|
|
||||||
*/
|
|
||||||
public String getContentType() {
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change content type
|
|
||||||
public void setContentType(String ct) {
|
|
||||||
contentType = ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return current progress.
|
|
||||||
*/
|
|
||||||
public long getProgress() {
|
|
||||||
return progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return expected maximum progress; -1 if expected is unknown.
|
|
||||||
*/
|
|
||||||
public long getExpected() {
|
|
||||||
return expected;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return state.
|
|
||||||
*/
|
|
||||||
public State getState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Begin progress tracking.
|
|
||||||
*/
|
|
||||||
public void beginTracking() {
|
|
||||||
progressMonitor.registerSource(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finish progress tracking.
|
|
||||||
*/
|
|
||||||
public void finishTracking() {
|
|
||||||
progressMonitor.unregisterSource(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update progress.
|
|
||||||
*/
|
|
||||||
public void updateProgress(long latestProgress, long expectedProgress) {
|
|
||||||
lastProgress = progress;
|
|
||||||
progress = latestProgress;
|
|
||||||
expected = expectedProgress;
|
|
||||||
|
|
||||||
if (connected() == false)
|
|
||||||
state = State.CONNECTED;
|
|
||||||
else
|
|
||||||
state = State.UPDATE;
|
|
||||||
|
|
||||||
// The threshold effectively divides the progress into
|
|
||||||
// different set of ranges:
|
|
||||||
//
|
|
||||||
// Range 0: 0..threshold-1,
|
|
||||||
// Range 1: threshold .. 2*threshold-1
|
|
||||||
// ....
|
|
||||||
// Range n: n*threshold .. (n+1)*threshold-1
|
|
||||||
//
|
|
||||||
// To determine which range the progress belongs to, it
|
|
||||||
// would be calculated as follow:
|
|
||||||
//
|
|
||||||
// range number = progress / threshold
|
|
||||||
//
|
|
||||||
// Notification should only be triggered when the current
|
|
||||||
// progress and the last progress are in different ranges,
|
|
||||||
// i.e. they have different range numbers.
|
|
||||||
//
|
|
||||||
// Using this range scheme, notification will be generated
|
|
||||||
// only once when the progress reaches each range.
|
|
||||||
//
|
|
||||||
if (lastProgress / threshold != progress / threshold) {
|
|
||||||
progressMonitor.updateProgress(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect read overrun
|
|
||||||
if (expected != -1) {
|
|
||||||
if (progress >= expected && progress != 0)
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object clone() throws CloneNotSupportedException {
|
|
||||||
return super.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return getClass().getName() + "[url=" + url + ", method=" + method + ", state=" + state
|
|
||||||
+ ", content-type=" + contentType + ", progress=" + progress + ", expected=" + expected + "]";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,7 +27,6 @@ package sun.net.www;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import sun.net.ProgressSource;
|
|
||||||
import sun.net.www.http.ChunkedInputStream;
|
import sun.net.www.http.ChunkedInputStream;
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,19 +41,13 @@ public class MeteredStream extends FilterInputStream {
|
||||||
protected long count = 0;
|
protected long count = 0;
|
||||||
protected long markedCount = 0;
|
protected long markedCount = 0;
|
||||||
protected int markLimit = -1;
|
protected int markLimit = -1;
|
||||||
protected ProgressSource pi;
|
|
||||||
private final ReentrantLock readLock = new ReentrantLock();
|
private final ReentrantLock readLock = new ReentrantLock();
|
||||||
|
|
||||||
public MeteredStream(InputStream is, ProgressSource pi, long expected)
|
public MeteredStream(InputStream is, long expected)
|
||||||
{
|
{
|
||||||
super(is);
|
super(is);
|
||||||
|
|
||||||
this.pi = pi;
|
|
||||||
this.expected = expected;
|
this.expected = expected;
|
||||||
|
|
||||||
if (pi != null) {
|
|
||||||
pi.updateProgress(0, expected);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void justRead(long n) throws IOException {
|
private final void justRead(long n) throws IOException {
|
||||||
|
@ -81,9 +74,6 @@ public class MeteredStream extends FilterInputStream {
|
||||||
markLimit = -1;
|
markLimit = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pi != null)
|
|
||||||
pi.updateProgress(count, expected);
|
|
||||||
|
|
||||||
if (isMarked()) {
|
if (isMarked()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -170,8 +160,6 @@ public class MeteredStream extends FilterInputStream {
|
||||||
lock();
|
lock();
|
||||||
try {
|
try {
|
||||||
if (closed) return;
|
if (closed) return;
|
||||||
if (pi != null)
|
|
||||||
pi.finishTracking();
|
|
||||||
|
|
||||||
closed = true;
|
closed = true;
|
||||||
in.close();
|
in.close();
|
||||||
|
@ -241,17 +229,4 @@ public class MeteredStream extends FilterInputStream {
|
||||||
public final boolean isLockHeldByCurrentThread() {
|
public final boolean isLockHeldByCurrentThread() {
|
||||||
return readLock.isHeldByCurrentThread();
|
return readLock.isHeldByCurrentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
try {
|
|
||||||
close();
|
|
||||||
if (pi != null)
|
|
||||||
pi.close();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
// Call super class
|
|
||||||
super.finalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@ import java.util.Properties;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import sun.net.NetworkClient;
|
import sun.net.NetworkClient;
|
||||||
import sun.net.ProgressSource;
|
|
||||||
import sun.net.www.MessageHeader;
|
import sun.net.www.MessageHeader;
|
||||||
import sun.net.www.HeaderParser;
|
import sun.net.www.HeaderParser;
|
||||||
import sun.net.www.MeteredStream;
|
import sun.net.www.MeteredStream;
|
||||||
|
@ -741,7 +740,7 @@ public class HttpClient extends NetworkClient {
|
||||||
/** Parse the first line of the HTTP request. It usually looks
|
/** Parse the first line of the HTTP request. It usually looks
|
||||||
something like: {@literal "HTTP/1.0 <number> comment\r\n"}. */
|
something like: {@literal "HTTP/1.0 <number> comment\r\n"}. */
|
||||||
|
|
||||||
public boolean parseHTTP(MessageHeader responses, ProgressSource pi, HttpURLConnection httpuc)
|
public boolean parseHTTP(MessageHeader responses, HttpURLConnection httpuc)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
/* If "HTTP/*" is found in the beginning, return true. Let
|
/* If "HTTP/*" is found in the beginning, return true. Let
|
||||||
* HttpURLConnection parse the mime header itself.
|
* HttpURLConnection parse the mime header itself.
|
||||||
|
@ -758,7 +757,7 @@ public class HttpClient extends NetworkClient {
|
||||||
serverInput = new HttpCaptureInputStream(serverInput, capture);
|
serverInput = new HttpCaptureInputStream(serverInput, capture);
|
||||||
}
|
}
|
||||||
serverInput = new BufferedInputStream(serverInput);
|
serverInput = new BufferedInputStream(serverInput);
|
||||||
return (parseHTTPHeader(responses, pi, httpuc));
|
return (parseHTTPHeader(responses, httpuc));
|
||||||
} catch (SocketTimeoutException stex) {
|
} catch (SocketTimeoutException stex) {
|
||||||
// We don't want to retry the request when the app. sets a timeout
|
// We don't want to retry the request when the app. sets a timeout
|
||||||
// but don't close the server if timeout while waiting for 100-continue
|
// but don't close the server if timeout while waiting for 100-continue
|
||||||
|
@ -785,7 +784,7 @@ public class HttpClient extends NetworkClient {
|
||||||
checkTunneling(httpuc);
|
checkTunneling(httpuc);
|
||||||
afterConnect();
|
afterConnect();
|
||||||
writeRequests(requests, poster);
|
writeRequests(requests, poster);
|
||||||
return parseHTTP(responses, pi, httpuc);
|
return parseHTTP(responses, httpuc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -805,7 +804,7 @@ public class HttpClient extends NetworkClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean parseHTTPHeader(MessageHeader responses, ProgressSource pi, HttpURLConnection httpuc)
|
private boolean parseHTTPHeader(MessageHeader responses, HttpURLConnection httpuc)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
/* If "HTTP/*" is found in the beginning, return true. Let
|
/* If "HTTP/*" is found in the beginning, return true. Let
|
||||||
* HttpURLConnection parse the mime header itself.
|
* HttpURLConnection parse the mime header itself.
|
||||||
|
@ -951,7 +950,7 @@ public class HttpClient extends NetworkClient {
|
||||||
checkTunneling(httpuc);
|
checkTunneling(httpuc);
|
||||||
afterConnect();
|
afterConnect();
|
||||||
writeRequests(requests, poster);
|
writeRequests(requests, poster);
|
||||||
return parseHTTP(responses, pi, httpuc);
|
return parseHTTP(responses, httpuc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new SocketException("Unexpected end of file from server");
|
throw new SocketException("Unexpected end of file from server");
|
||||||
|
@ -994,7 +993,7 @@ public class HttpClient extends NetworkClient {
|
||||||
|| (code >= 102 && code <= 199)) {
|
|| (code >= 102 && code <= 199)) {
|
||||||
logFinest("Ignoring interim informational 1xx response: " + code);
|
logFinest("Ignoring interim informational 1xx response: " + code);
|
||||||
responses.reset();
|
responses.reset();
|
||||||
return parseHTTPHeader(responses, pi, httpuc);
|
return parseHTTPHeader(responses, httpuc);
|
||||||
}
|
}
|
||||||
|
|
||||||
long cl = -1;
|
long cl = -1;
|
||||||
|
@ -1067,11 +1066,6 @@ public class HttpClient extends NetworkClient {
|
||||||
// In this case, content length is well known, so it is okay
|
// In this case, content length is well known, so it is okay
|
||||||
// to wrap the input stream with KeepAliveStream/MeteredStream.
|
// to wrap the input stream with KeepAliveStream/MeteredStream.
|
||||||
|
|
||||||
if (pi != null) {
|
|
||||||
// Progress monitor is enabled
|
|
||||||
pi.setContentType(responses.findValue("content-type"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If disableKeepAlive == true, the client will not be returned
|
// If disableKeepAlive == true, the client will not be returned
|
||||||
// to the cache. But we still need to use a keepalive stream to
|
// to the cache. But we still need to use a keepalive stream to
|
||||||
// allow the multi-message authentication exchange on the connection
|
// allow the multi-message authentication exchange on the connection
|
||||||
|
@ -1079,39 +1073,13 @@ public class HttpClient extends NetworkClient {
|
||||||
if (useKeepAliveStream) {
|
if (useKeepAliveStream) {
|
||||||
// Wrap KeepAliveStream if keep alive is enabled.
|
// Wrap KeepAliveStream if keep alive is enabled.
|
||||||
logFinest("KeepAlive stream used: " + url);
|
logFinest("KeepAlive stream used: " + url);
|
||||||
serverInput = new KeepAliveStream(serverInput, pi, cl, this);
|
serverInput = new KeepAliveStream(serverInput, cl, this);
|
||||||
failedOnce = false;
|
failedOnce = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
serverInput = new MeteredStream(serverInput, pi, cl);
|
serverInput = new MeteredStream(serverInput, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cl == -1) {
|
|
||||||
// In this case, content length is unknown - the input
|
|
||||||
// stream would simply be a regular InputStream or
|
|
||||||
// ChunkedInputStream.
|
|
||||||
|
|
||||||
if (pi != null) {
|
|
||||||
// Progress monitoring is enabled.
|
|
||||||
|
|
||||||
pi.setContentType(responses.findValue("content-type"));
|
|
||||||
|
|
||||||
// Wrap MeteredStream for tracking indeterministic
|
|
||||||
// progress, even if the input stream is ChunkedInputStream.
|
|
||||||
serverInput = new MeteredStream(serverInput, pi, cl);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Progress monitoring is disabled, and there is no
|
|
||||||
// need to wrap an unknown length input stream.
|
|
||||||
|
|
||||||
// ** This is an no-op **
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (pi != null)
|
|
||||||
pi.finishTracking();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ package sun.net.www.http;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import sun.net.ProgressSource;
|
|
||||||
import sun.net.www.MeteredStream;
|
import sun.net.www.MeteredStream;
|
||||||
import jdk.internal.misc.InnocuousThread;
|
import jdk.internal.misc.InnocuousThread;
|
||||||
|
|
||||||
|
@ -56,8 +55,8 @@ class KeepAliveStream extends MeteredStream implements Hurryable {
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public KeepAliveStream(InputStream is, ProgressSource pi, long expected, HttpClient hc) {
|
public KeepAliveStream(InputStream is, long expected, HttpClient hc) {
|
||||||
super(is, pi, expected);
|
super(is, expected);
|
||||||
this.hc = hc;
|
this.hc = hc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,9 +100,6 @@ class KeepAliveStream extends MeteredStream implements Hurryable {
|
||||||
hc.finished();
|
hc.finished();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (pi != null)
|
|
||||||
pi.finishTracking();
|
|
||||||
|
|
||||||
if (!queuedForCleanup) {
|
if (!queuedForCleanup) {
|
||||||
// nulling out the underlying inputstream as well as
|
// nulling out the underlying inputstream as well as
|
||||||
// httpClient to let gc collect the memories faster
|
// httpClient to let gc collect the memories faster
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -36,7 +36,6 @@ import java.net.FileNameMap;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
import java.security.Permission;
|
import java.security.Permission;
|
||||||
import sun.net.*;
|
|
||||||
import sun.net.www.*;
|
import sun.net.www.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
@ -82,15 +81,7 @@ public class FileURLConnection extends URLConnection {
|
||||||
throw new FileNotFoundException(filename + " exists, but is not accessible");
|
throw new FileNotFoundException(filename + " exists, but is not accessible");
|
||||||
files = Arrays.<String>asList(fileList);
|
files = Arrays.<String>asList(fileList);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
is = new BufferedInputStream(new FileInputStream(filename));
|
is = new BufferedInputStream(new FileInputStream(filename));
|
||||||
|
|
||||||
// Check if URL should be metered
|
|
||||||
boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET");
|
|
||||||
if (meteredInput) {
|
|
||||||
ProgressSource pi = new ProgressSource(url, "GET", file.length());
|
|
||||||
is = new MeteredStream(is, pi, file.length());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -56,8 +56,6 @@ import sun.net.www.URLConnection;
|
||||||
import sun.net.www.protocol.http.HttpURLConnection;
|
import sun.net.www.protocol.http.HttpURLConnection;
|
||||||
import sun.net.ftp.FtpClient;
|
import sun.net.ftp.FtpClient;
|
||||||
import sun.net.ftp.FtpProtocolException;
|
import sun.net.ftp.FtpProtocolException;
|
||||||
import sun.net.ProgressSource;
|
|
||||||
import sun.net.ProgressMonitor;
|
|
||||||
import sun.net.www.ParseUtil;
|
import sun.net.www.ParseUtil;
|
||||||
import sun.security.action.GetPropertyAction;
|
import sun.security.action.GetPropertyAction;
|
||||||
|
|
||||||
|
@ -466,17 +464,7 @@ public class FtpURLConnection extends URLConnection {
|
||||||
|
|
||||||
// Wrap input stream with MeteredStream to ensure read() will always return -1
|
// Wrap input stream with MeteredStream to ensure read() will always return -1
|
||||||
// at expected length.
|
// at expected length.
|
||||||
|
is = new MeteredStream(is, l);
|
||||||
// Check if URL should be metered
|
|
||||||
boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET");
|
|
||||||
ProgressSource pi = null;
|
|
||||||
|
|
||||||
if (meteredInput) {
|
|
||||||
pi = new ProgressSource(url, "GET", l);
|
|
||||||
pi.beginTracking();
|
|
||||||
}
|
|
||||||
|
|
||||||
is = new MeteredStream(is, pi, l);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
@ -67,7 +67,8 @@ import java.util.Set;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
import jdk.internal.access.JavaNetHttpCookieAccess;
|
import jdk.internal.access.JavaNetHttpCookieAccess;
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
import sun.net.*;
|
import sun.net.NetProperties;
|
||||||
|
import sun.net.NetworkClient;
|
||||||
import sun.net.util.IPAddressUtil;
|
import sun.net.util.IPAddressUtil;
|
||||||
import sun.net.www.*;
|
import sun.net.www.*;
|
||||||
import sun.net.www.http.HttpClient;
|
import sun.net.www.http.HttpClient;
|
||||||
|
@ -384,9 +385,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||||
|
|
||||||
String serverAuthKey, proxyAuthKey;
|
String serverAuthKey, proxyAuthKey;
|
||||||
|
|
||||||
/* Progress source */
|
|
||||||
protected ProgressSource pi;
|
|
||||||
|
|
||||||
/* all the response headers we get back */
|
/* all the response headers we get back */
|
||||||
private MessageHeader responses;
|
private MessageHeader responses;
|
||||||
/* the stream _from_ the server */
|
/* the stream _from_ the server */
|
||||||
|
@ -1331,7 +1329,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
http.parseHTTP(responses, pi, this);
|
http.parseHTTP(responses, this);
|
||||||
} catch (SocketTimeoutException se) {
|
} catch (SocketTimeoutException se) {
|
||||||
if (!enforceTimeOut) {
|
if (!enforceTimeOut) {
|
||||||
throw se;
|
throw se;
|
||||||
|
@ -1662,14 +1660,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||||
return cachedInputStream;
|
return cachedInputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if URL should be metered
|
|
||||||
boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, method);
|
|
||||||
|
|
||||||
if (meteredInput) {
|
|
||||||
pi = new ProgressSource(url, method);
|
|
||||||
pi.beginTracking();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* REMIND: This exists to fix the HttpsURLConnection subclass.
|
/* REMIND: This exists to fix the HttpsURLConnection subclass.
|
||||||
* Hotjava needs to run on JDK1.1FCS. Do proper fix once a
|
* Hotjava needs to run on JDK1.1FCS. Do proper fix once a
|
||||||
* proper solution for SSL can be found.
|
* proper solution for SSL can be found.
|
||||||
|
@ -1679,7 +1669,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||||
if (!streaming()) {
|
if (!streaming()) {
|
||||||
writeRequests();
|
writeRequests();
|
||||||
}
|
}
|
||||||
http.parseHTTP(responses, pi, this);
|
http.parseHTTP(responses, this);
|
||||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||||
logger.fine(responses.toString());
|
logger.fine(responses.toString());
|
||||||
}
|
}
|
||||||
|
@ -1943,10 +1933,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||||
respCode == HTTP_NOT_MODIFIED ||
|
respCode == HTTP_NOT_MODIFIED ||
|
||||||
respCode == HTTP_NO_CONTENT) {
|
respCode == HTTP_NO_CONTENT) {
|
||||||
|
|
||||||
if (pi != null) {
|
|
||||||
pi.finishTracking();
|
|
||||||
pi = null;
|
|
||||||
}
|
|
||||||
http.finished();
|
http.finished();
|
||||||
http = null;
|
http = null;
|
||||||
inputStream = new EmptyInputStream();
|
inputStream = new EmptyInputStream();
|
||||||
|
@ -2166,9 +2152,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||||
sendCONNECTRequest();
|
sendCONNECTRequest();
|
||||||
responses.reset();
|
responses.reset();
|
||||||
|
|
||||||
// There is no need to track progress in HTTP Tunneling,
|
http.parseHTTP(responses, this);
|
||||||
// so ProgressSource is null.
|
|
||||||
http.parseHTTP(responses, null, this);
|
|
||||||
|
|
||||||
/* Log the response to the CONNECT */
|
/* Log the response to the CONNECT */
|
||||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||||
|
@ -3045,10 +3029,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||||
private void disconnectInternal() {
|
private void disconnectInternal() {
|
||||||
responseCode = -1;
|
responseCode = -1;
|
||||||
inputStream = null;
|
inputStream = null;
|
||||||
if (pi != null) {
|
|
||||||
pi.finishTracking();
|
|
||||||
pi = null;
|
|
||||||
}
|
|
||||||
if (http != null) {
|
if (http != null) {
|
||||||
http.closeServer();
|
http.closeServer();
|
||||||
http = null;
|
http = null;
|
||||||
|
@ -3062,10 +3042,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||||
public void disconnect() {
|
public void disconnect() {
|
||||||
|
|
||||||
responseCode = -1;
|
responseCode = -1;
|
||||||
if (pi != null) {
|
|
||||||
pi.finishTracking();
|
|
||||||
pi = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (http != null) {
|
if (http != null) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -40,7 +40,7 @@ public class ProxyModuleMapping {
|
||||||
// unnamed module gets access to sun.invoke package (e.g. via --add-exports)
|
// unnamed module gets access to sun.invoke package (e.g. via --add-exports)
|
||||||
new ProxyModuleMapping(sun.invoke.WrapperInstance.class).test();
|
new ProxyModuleMapping(sun.invoke.WrapperInstance.class).test();
|
||||||
|
|
||||||
Class<?> modulePrivateIntf = Class.forName("sun.net.ProgressListener");
|
Class<?> modulePrivateIntf = Class.forName("sun.net.PlatformSocketImpl");
|
||||||
new ProxyModuleMapping(modulePrivateIntf).test();
|
new ProxyModuleMapping(modulePrivateIntf).test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,103 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code 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 code 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 in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
* @bug 4333920 4994372
|
|
||||||
* @summary ChunkedEncoding unit test; MeteredStream/ProgressData problem
|
|
||||||
* @modules java.base/sun.net
|
|
||||||
* jdk.httpserver
|
|
||||||
* @library /test/lib
|
|
||||||
* @run main ChunkedEncodingWithProgressMonitorTest
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.net.*;
|
|
||||||
import java.util.BitSet;
|
|
||||||
import sun.net.ProgressMeteringPolicy;
|
|
||||||
import sun.net.ProgressMonitor;
|
|
||||||
import sun.net.ProgressListener;
|
|
||||||
import sun.net.ProgressEvent;
|
|
||||||
|
|
||||||
public class ChunkedEncodingWithProgressMonitorTest {
|
|
||||||
public static void main (String[] args) throws Exception {
|
|
||||||
ProgressMonitor.setMeteringPolicy(new MyProgressMeteringPolicy());
|
|
||||||
ProgressListener listener = new MyProgressListener();
|
|
||||||
ProgressMonitor.getDefault().addProgressListener(listener);
|
|
||||||
ChunkedEncodingTest.test();
|
|
||||||
ProgressMonitor.getDefault().removeProgressListener(listener);
|
|
||||||
|
|
||||||
if (flag.cardinality() != 3) {
|
|
||||||
throw new RuntimeException("All three methods in ProgressListener"+
|
|
||||||
" should be called. Yet the number of"+
|
|
||||||
" methods actually called are "+
|
|
||||||
flag.cardinality());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MyProgressMeteringPolicy implements ProgressMeteringPolicy {
|
|
||||||
/**
|
|
||||||
* Return true if metering should be turned on for a particular network input stream.
|
|
||||||
*/
|
|
||||||
public boolean shouldMeterInput(URL url, String method) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return update notification threshold.
|
|
||||||
*/
|
|
||||||
public int getProgressUpdateThreshold() {
|
|
||||||
return 8192;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static BitSet flag = new BitSet(3);
|
|
||||||
|
|
||||||
static class MyProgressListener implements ProgressListener {
|
|
||||||
/**
|
|
||||||
* Start progress.
|
|
||||||
*/
|
|
||||||
public void progressStart(ProgressEvent evt) {
|
|
||||||
System.out.println("start: received progressevent "+evt);
|
|
||||||
if (flag.nextSetBit(0) == -1)
|
|
||||||
flag.set(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update progress.
|
|
||||||
*/
|
|
||||||
public void progressUpdate(ProgressEvent evt) {
|
|
||||||
System.out.println("update: received progressevent "+evt);
|
|
||||||
if (flag.nextSetBit(1) == -1)
|
|
||||||
flag.set(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finish progress.
|
|
||||||
*/
|
|
||||||
public void progressFinish(ProgressEvent evt) {
|
|
||||||
System.out.println("finish: received progressevent "+evt);
|
|
||||||
if (flag.nextSetBit(2) == -1)
|
|
||||||
flag.set(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,293 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code 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 code 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 in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8240275
|
||||||
|
* @library /test/lib
|
||||||
|
* @run main/othervm KeepAliveStreamFinalizer
|
||||||
|
* @summary HttpsURLConnection: connection must not be reused after finalization
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javax.net.ssl.HandshakeCompletedListener;
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
|
import javax.net.ssl.SSLSocket;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
public class KeepAliveStreamFinalizer {
|
||||||
|
|
||||||
|
static Server server;
|
||||||
|
private static volatile String failureReason;
|
||||||
|
|
||||||
|
static class Server extends Thread {
|
||||||
|
final ServerSocket srv;
|
||||||
|
static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n'};
|
||||||
|
|
||||||
|
Server(ServerSocket s) {
|
||||||
|
srv = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean readOneRequest(InputStream is) throws IOException {
|
||||||
|
int requestEndCount = 0, r;
|
||||||
|
while ((r = is.read()) != -1) {
|
||||||
|
if (r == requestEnd[requestEndCount]) {
|
||||||
|
requestEndCount++;
|
||||||
|
if (requestEndCount == 4) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestEndCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
Socket ss = srv.accept();
|
||||||
|
Thread t1 = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
InputStream in = ss.getInputStream();
|
||||||
|
OutputStream out = ss.getOutputStream();
|
||||||
|
while (readOneRequest(in)) {
|
||||||
|
out.write("HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nContent-Length: 1\r\n\r\na".getBytes());
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
out.close();
|
||||||
|
ss.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t1.setDaemon(true);
|
||||||
|
t1.start();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
InetSocketAddress address = startHttpServer();
|
||||||
|
clientHttpCalls(address);
|
||||||
|
if (failureReason != null) {
|
||||||
|
throw new RuntimeException(failureReason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InetSocketAddress startHttpServer() throws Exception {
|
||||||
|
InetAddress localHost = InetAddress.getLoopbackAddress();
|
||||||
|
InetSocketAddress address = new InetSocketAddress(localHost, 0);
|
||||||
|
ServerSocket serverSocket = new ServerSocket();
|
||||||
|
serverSocket.bind(address);
|
||||||
|
server = new Server(serverSocket);
|
||||||
|
server.setDaemon(true);
|
||||||
|
server.start();
|
||||||
|
return (InetSocketAddress) serverSocket.getLocalSocketAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void doRequest(URL url) throws IOException {
|
||||||
|
HttpsURLConnection c = (HttpsURLConnection)url.openConnection();
|
||||||
|
c.setRequestMethod("POST");
|
||||||
|
c.setDoOutput(true);
|
||||||
|
OutputStreamWriter out = new OutputStreamWriter(c.getOutputStream());
|
||||||
|
out.write("test");
|
||||||
|
out.close();
|
||||||
|
int responseCode = c.getResponseCode();
|
||||||
|
// Fully reading the body causes the HttpsClient to be added to the KeepAliveCache immediately,
|
||||||
|
// which avoids this issue since GC will not finalize the HttpsClient.
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clientHttpCalls(InetSocketAddress address) throws Exception {
|
||||||
|
try {
|
||||||
|
System.err.println("http server listen on: " + address.getPort());
|
||||||
|
String hostAddr = address.getAddress().getHostAddress();
|
||||||
|
if (hostAddr.indexOf(':') > -1) hostAddr = "[" + hostAddr + "]";
|
||||||
|
String baseURLStr = "https://" + hostAddr + ":" + address.getPort() + "/";
|
||||||
|
|
||||||
|
URL testUrl = new URL(baseURLStr);
|
||||||
|
|
||||||
|
// CheckFinalizeSocketFactory is not a real SSLSocketFactory;
|
||||||
|
// it produces regular non-SSL sockets. Effectively, the request
|
||||||
|
// is made over http.
|
||||||
|
HttpsURLConnection.setDefaultSSLSocketFactory(new CheckFinalizeSocketFactory());
|
||||||
|
// now perform up to 3 requests; with the broken KeepAliveStream finalizer,
|
||||||
|
// the second request usually attempts to use a finalized socket
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
System.err.println("Request #" + (i + 1));
|
||||||
|
doRequest(testUrl);
|
||||||
|
System.gc();
|
||||||
|
Thread.sleep(100);
|
||||||
|
if (failureReason != null) break;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
server.srv.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CheckFinalizeSocket extends SSLSocket {
|
||||||
|
private volatile boolean finalized;
|
||||||
|
public void finalize() throws Throwable {
|
||||||
|
System.err.println("In finalize");
|
||||||
|
super.finalize();
|
||||||
|
finalized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
if (finalized) {
|
||||||
|
System.err.println(failureReason = "getInputStream called after finalize");
|
||||||
|
Thread.dumpStack();
|
||||||
|
}
|
||||||
|
return super.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputStream getOutputStream() throws IOException {
|
||||||
|
if (finalized) {
|
||||||
|
System.err.println(failureReason = "getOutputStream called after finalize");
|
||||||
|
Thread.dumpStack();
|
||||||
|
}
|
||||||
|
return super.getOutputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void close() throws IOException {
|
||||||
|
if (finalized) {
|
||||||
|
System.err.println(failureReason = "close called after finalize");
|
||||||
|
Thread.dumpStack();
|
||||||
|
}
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// required abstract method overrides
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedCipherSuites() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String[] getEnabledCipherSuites() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setEnabledCipherSuites(String[] suites) { }
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedProtocols() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String[] getEnabledProtocols() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setEnabledProtocols(String[] protocols) { }
|
||||||
|
@Override
|
||||||
|
public SSLSession getSession() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { }
|
||||||
|
@Override
|
||||||
|
public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { }
|
||||||
|
@Override
|
||||||
|
public void startHandshake() throws IOException { }
|
||||||
|
@Override
|
||||||
|
public void setUseClientMode(boolean mode) { }
|
||||||
|
@Override
|
||||||
|
public boolean getUseClientMode() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setNeedClientAuth(boolean need) { }
|
||||||
|
@Override
|
||||||
|
public boolean getNeedClientAuth() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setWantClientAuth(boolean want) { }
|
||||||
|
@Override
|
||||||
|
public boolean getWantClientAuth() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setEnableSessionCreation(boolean flag) { }
|
||||||
|
@Override
|
||||||
|
public boolean getEnableSessionCreation() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CheckFinalizeSocketFactory extends SSLSocketFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Socket createSocket() throws IOException {
|
||||||
|
return new CheckFinalizeSocket();
|
||||||
|
}
|
||||||
|
// required abstract method overrides
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String[] getDefaultCipherSuites() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedCipherSuites() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue