8188083: NullPointerExcpn-java.awt.image.FilteredImageSource.startProduction JDK-8079607
Reviewed-by: serb, prr, jdv
This commit is contained in:
parent
72e094dcd4
commit
c0e7592e4e
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1995, 2017, 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
|
||||||
@ -35,7 +35,8 @@ import java.awt.image.ColorModel;
|
|||||||
/**
|
/**
|
||||||
* This class is an implementation of the ImageProducer interface which
|
* This class is an implementation of the ImageProducer interface which
|
||||||
* takes an existing image and a filter object and uses them to produce
|
* takes an existing image and a filter object and uses them to produce
|
||||||
* image data for a new filtered version of the original image.
|
* image data for a new filtered version of the original image. Furthermore,
|
||||||
|
* {@code FilteredImageSource} is safe for use by multiple threads.
|
||||||
* Here is an example which filters an image by swapping the red and
|
* Here is an example which filters an image by swapping the red and
|
||||||
* blue components:
|
* blue components:
|
||||||
* <pre>
|
* <pre>
|
||||||
@ -171,7 +172,7 @@ public class FilteredImageSource implements ImageProducer {
|
|||||||
* @param ic the consumer for the filtered image
|
* @param ic the consumer for the filtered image
|
||||||
* @see ImageConsumer
|
* @see ImageConsumer
|
||||||
*/
|
*/
|
||||||
public void startProduction(ImageConsumer ic) {
|
public synchronized void startProduction(ImageConsumer ic) {
|
||||||
if (proxies == null) {
|
if (proxies == null) {
|
||||||
proxies = new Hashtable<>();
|
proxies = new Hashtable<>();
|
||||||
}
|
}
|
||||||
@ -198,7 +199,7 @@ public class FilteredImageSource implements ImageProducer {
|
|||||||
*
|
*
|
||||||
* @see ImageConsumer
|
* @see ImageConsumer
|
||||||
*/
|
*/
|
||||||
public void requestTopDownLeftRightResend(ImageConsumer ic) {
|
public synchronized void requestTopDownLeftRightResend(ImageConsumer ic) {
|
||||||
if (proxies != null) {
|
if (proxies != null) {
|
||||||
ImageFilter imgf = proxies.get(ic);
|
ImageFilter imgf = proxies.get(ic);
|
||||||
if (imgf != null) {
|
if (imgf != null) {
|
||||||
|
212
test/jdk/java/awt/image/FilteredImageSourceTest.java
Normal file
212
test/jdk/java/awt/image/FilteredImageSourceTest.java
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 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 8188083
|
||||||
|
* @summary The test checks whether applying image filters using
|
||||||
|
* FilteredImageSource results in a NullPointerException.
|
||||||
|
* @run main FilteredImageSourceTest
|
||||||
|
*/
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.image.ColorModel;
|
||||||
|
import java.awt.image.FilteredImageSource;
|
||||||
|
import java.awt.image.ImageConsumer;
|
||||||
|
import java.awt.image.ImageFilter;
|
||||||
|
import java.awt.image.ImageObserver;
|
||||||
|
import java.awt.image.ImageProducer;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An empty image consumer that will be added to the list of consumers
|
||||||
|
* interested in image data for the filtered image.
|
||||||
|
*/
|
||||||
|
class EmptyImageConsumer implements ImageConsumer {
|
||||||
|
@Override
|
||||||
|
public void setDimensions(int width, int height) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProperties(Hashtable<?, ?> props) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setColorModel(ColorModel colorModel) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHints(int hintFlags) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPixels(int x, int y, int width, int height,
|
||||||
|
ColorModel colorModel, byte[] pixels,
|
||||||
|
int offset, int scanSize) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPixels(int x, int y, int width, int height,
|
||||||
|
ColorModel colorModel, int[] pixels,
|
||||||
|
int offset, int scanSize) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void imageComplete(int i) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An empty image producer whose sole purpose is to provide stub methods
|
||||||
|
* that will be invoked while preparing filtered image.
|
||||||
|
*/
|
||||||
|
class EmptyImageProducer implements ImageProducer {
|
||||||
|
@Override
|
||||||
|
public void addConsumer(ImageConsumer imageConsumer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConsumer(ImageConsumer imageConsumer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeConsumer(ImageConsumer imageConsumer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startProduction(ImageConsumer imageConsumer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestTopDownLeftRightResend(ImageConsumer imageConsumer) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Typically, an Image object will contain an ImageProducer that prepares
|
||||||
|
* image data. FilteredImageSource will be set as image producer for images
|
||||||
|
* that require image filter applied to image data.
|
||||||
|
*/
|
||||||
|
class EmptyFilteredImage extends Image {
|
||||||
|
ImageFilter filter = null;
|
||||||
|
ImageProducer producer = null;
|
||||||
|
|
||||||
|
public EmptyFilteredImage(ImageProducer imgSource) {
|
||||||
|
filter = new ImageFilter();
|
||||||
|
producer = new FilteredImageSource(imgSource, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth(ImageObserver observer) {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight(ImageObserver observer) {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImageProducer getSource() {
|
||||||
|
return producer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Graphics getGraphics() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getProperty(String name, ImageObserver observer) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class FilteredImageSourceTest {
|
||||||
|
// Minimum test duration in ms
|
||||||
|
private static final int TEST_MIN_DURATION = 5000;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A throwable object that will hold any exception generated while
|
||||||
|
* executing methods on FilteredImageSource. The test passes if the
|
||||||
|
* methods execute without any exception
|
||||||
|
*/
|
||||||
|
private static volatile Throwable fail = null;
|
||||||
|
|
||||||
|
public static void main(final String[] args)
|
||||||
|
throws InterruptedException {
|
||||||
|
final ImageConsumer ic = new EmptyImageConsumer();
|
||||||
|
final ImageProducer ip = new EmptyImageProducer();
|
||||||
|
final Image image = new EmptyFilteredImage(ip);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simulate the framework's operations on FilteredImageSource by
|
||||||
|
* invoking the concerned methods in multiple threads and observe
|
||||||
|
* whether exceptions are generated.
|
||||||
|
*/
|
||||||
|
Thread t1 = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
image.getSource().addConsumer(ic);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
fail = t;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t1.setDaemon(true);
|
||||||
|
|
||||||
|
Thread t2 = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
image.getSource().removeConsumer(ic);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
fail = t;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t2.setDaemon(true);
|
||||||
|
|
||||||
|
Thread t3 = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
image.getSource().startProduction(ic);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
fail = t;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t3.setDaemon(true);
|
||||||
|
|
||||||
|
// Start the threads
|
||||||
|
t1.start();
|
||||||
|
t2.start();
|
||||||
|
t3.start();
|
||||||
|
|
||||||
|
// Wait on one of the threads for a specific duration.
|
||||||
|
t1.join(TEST_MIN_DURATION);
|
||||||
|
if (fail != null) {
|
||||||
|
throw new RuntimeException("Test failed with exception: ", fail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user