| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.awt.image;  | 
 | 
 | 
 | 
import java.awt.image.*;  | 
 | 
import java.io.InputStream;  | 
 | 
import java.io.IOException;  | 
 | 
import java.io.BufferedInputStream;  | 
 | 
import java.util.Hashtable;  | 
 | 
 | 
 | 
public abstract class InputStreamImageSource implements ImageProducer,  | 
 | 
                                                        ImageFetchable  | 
 | 
{ | 
 | 
    ImageConsumerQueue consumers;  | 
 | 
 | 
 | 
    ImageDecoder decoder;  | 
 | 
    ImageDecoder decoders;  | 
 | 
 | 
 | 
    boolean awaitingFetch = false;  | 
 | 
 | 
 | 
    abstract boolean checkSecurity(Object context, boolean quiet);  | 
 | 
 | 
 | 
    int countConsumers(ImageConsumerQueue cq) { | 
 | 
        int i = 0;  | 
 | 
        while (cq != null) { | 
 | 
            i++;  | 
 | 
            cq = cq.next;  | 
 | 
        }  | 
 | 
        return i;  | 
 | 
    }  | 
 | 
 | 
 | 
    synchronized int countConsumers() { | 
 | 
        ImageDecoder id = decoders;  | 
 | 
        int i = countConsumers(consumers);  | 
 | 
        while (id != null) { | 
 | 
            i += countConsumers(id.queue);  | 
 | 
            id = id.next;  | 
 | 
        }  | 
 | 
        return i;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void addConsumer(ImageConsumer ic) { | 
 | 
        addConsumer(ic, false);  | 
 | 
    }  | 
 | 
 | 
 | 
    synchronized void printQueue(ImageConsumerQueue cq, String prefix) { | 
 | 
        while (cq != null) { | 
 | 
            System.out.println(prefix+cq);  | 
 | 
            cq = cq.next;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    synchronized void printQueues(String title) { | 
 | 
        System.out.println(title+"[ -----------");  | 
 | 
        printQueue(consumers, "  ");  | 
 | 
        for (ImageDecoder id = decoders; id != null; id = id.next) { | 
 | 
            System.out.println("    "+id); | 
 | 
            printQueue(id.queue, "      ");  | 
 | 
        }  | 
 | 
        System.out.println("----------- ]"+title); | 
 | 
    }  | 
 | 
 | 
 | 
    synchronized void addConsumer(ImageConsumer ic, boolean produce) { | 
 | 
        checkSecurity(null, false);  | 
 | 
        for (ImageDecoder id = decoders; id != null; id = id.next) { | 
 | 
            if (id.isConsumer(ic)) { | 
 | 
                  | 
 | 
                return;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        ImageConsumerQueue cq = consumers;  | 
 | 
        while (cq != null && cq.consumer != ic) { | 
 | 
            cq = cq.next;  | 
 | 
        }  | 
 | 
        if (cq == null) { | 
 | 
            cq = new ImageConsumerQueue(this, ic);  | 
 | 
            cq.next = consumers;  | 
 | 
            consumers = cq;  | 
 | 
        } else { | 
 | 
            if (!cq.secure) { | 
 | 
                Object context = null;  | 
 | 
                SecurityManager security = System.getSecurityManager();  | 
 | 
                if (security != null) { | 
 | 
                    context = security.getSecurityContext();  | 
 | 
                }  | 
 | 
                if (cq.securityContext == null) { | 
 | 
                    cq.securityContext = context;  | 
 | 
                } else if (!cq.securityContext.equals(context)) { | 
 | 
                    // If there are two different security contexts that both  | 
 | 
                    // have a handle on the same ImageConsumer, then there has  | 
 | 
                    // been a security breach and whether or not they trade  | 
 | 
                    // image data is small fish compared to what they could be  | 
 | 
                      | 
 | 
                    errorConsumer(cq, false);  | 
 | 
                    throw new SecurityException("Applets are trading image data!"); | 
 | 
                }  | 
 | 
            }  | 
 | 
            cq.interested = true;  | 
 | 
        }  | 
 | 
        if (produce && decoder == null) { | 
 | 
            startProduction();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public synchronized boolean isConsumer(ImageConsumer ic) { | 
 | 
        for (ImageDecoder id = decoders; id != null; id = id.next) { | 
 | 
            if (id.isConsumer(ic)) { | 
 | 
                return true;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return ImageConsumerQueue.isConsumer(consumers, ic);  | 
 | 
    }  | 
 | 
 | 
 | 
    private void errorAllConsumers(ImageConsumerQueue cq, boolean needReload) { | 
 | 
        while (cq != null) { | 
 | 
            if (cq.interested) { | 
 | 
                errorConsumer(cq, needReload);  | 
 | 
            }  | 
 | 
            cq = cq.next;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void errorConsumer(ImageConsumerQueue cq, boolean needReload) { | 
 | 
        cq.consumer.imageComplete(ImageConsumer.IMAGEERROR);  | 
 | 
        if ( needReload && cq.consumer instanceof ImageRepresentation) { | 
 | 
            ((ImageRepresentation)cq.consumer).image.flush();  | 
 | 
        }  | 
 | 
        removeConsumer(cq.consumer);  | 
 | 
    }  | 
 | 
 | 
 | 
    public synchronized void removeConsumer(ImageConsumer ic) { | 
 | 
        for (ImageDecoder id = decoders; id != null; id = id.next) { | 
 | 
            id.removeConsumer(ic);  | 
 | 
        }  | 
 | 
        consumers = ImageConsumerQueue.removeConsumer(consumers, ic, false);  | 
 | 
    }  | 
 | 
 | 
 | 
    public void startProduction(ImageConsumer ic) { | 
 | 
        addConsumer(ic, true);  | 
 | 
    }  | 
 | 
 | 
 | 
    private synchronized void startProduction() { | 
 | 
        if (!awaitingFetch) { | 
 | 
            if (ImageFetcher.add(this)) { | 
 | 
                awaitingFetch = true;  | 
 | 
            } else { | 
 | 
                ImageConsumerQueue cq = consumers;  | 
 | 
                consumers = null;  | 
 | 
                errorAllConsumers(cq, false);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private synchronized void stopProduction() { | 
 | 
        if (awaitingFetch) { | 
 | 
            ImageFetcher.remove(this);  | 
 | 
            awaitingFetch = false;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public void requestTopDownLeftRightResend(ImageConsumer ic) { | 
 | 
    }  | 
 | 
 | 
 | 
    protected abstract ImageDecoder getDecoder();  | 
 | 
 | 
 | 
    protected ImageDecoder decoderForType(InputStream is,  | 
 | 
                                          String content_type) { | 
 | 
        // Don't believe the content type - file extensions can  | 
 | 
        // lie.  | 
 | 
        /*  | 
 | 
        if (content_type.equals("image/gif")) { | 
 | 
            return new GifImageDecoder(this, is);  | 
 | 
        } else if (content_type.equals("image/jpeg")) { | 
 | 
            return new JPEGImageDecoder(this, is);  | 
 | 
        } else if (content_type.equals("image/x-xbitmap")) { | 
 | 
            return new XbmImageDecoder(this, is);  | 
 | 
        }  | 
 | 
        else if (content_type == URL.content_jpeg) { | 
 | 
            return new JpegImageDecoder(this, is);  | 
 | 
        } else if (content_type == URL.content_xbitmap) { | 
 | 
            return new XbmImageDecoder(this, is);  | 
 | 
        } else if (content_type == URL.content_xpixmap) { | 
 | 
            return new Xpm2ImageDecoder(this, is);  | 
 | 
        }  | 
 | 
        */  | 
 | 
 | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
    protected ImageDecoder getDecoder(InputStream is) { | 
 | 
        if (!is.markSupported())  | 
 | 
            is = new BufferedInputStream(is);  | 
 | 
        try { | 
 | 
            | 
 | 
 | 
 | 
             */  | 
 | 
          is.mark(8);  | 
 | 
            int c1 = is.read();  | 
 | 
            int c2 = is.read();  | 
 | 
            int c3 = is.read();  | 
 | 
            int c4 = is.read();  | 
 | 
            int c5 = is.read();  | 
 | 
            int c6 = is.read();  | 
 | 
              | 
 | 
            int c7 = is.read();  | 
 | 
            int c8 = is.read();  | 
 | 
              | 
 | 
            is.reset();  | 
 | 
            is.mark(-1);  | 
 | 
 | 
 | 
            if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8') { | 
 | 
                return new GifImageDecoder(this, is);  | 
 | 
            } else if (c1 == '\377' && c2 == '\330' && c3 == '\377') { | 
 | 
                return new JPEGImageDecoder(this, is);  | 
 | 
            } else if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f') { | 
 | 
                return new XbmImageDecoder(this, is);  | 
 | 
//          } else if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' &&  | 
 | 
//                     c5 == 'M' && c6 == '2') { | 
 | 
//              return new Xpm2ImageDecoder(this, is);  | 
 | 
                // added to support png  | 
 | 
            } else if (c1 == 137 && c2 == 80 && c3 == 78 &&  | 
 | 
                c4 == 71 && c5 == 13 && c6 == 10 &&  | 
 | 
                c7 == 26 && c8 == 10) { | 
 | 
                return new PNGImageDecoder(this, is);  | 
 | 
            }  | 
 | 
            // end of adding  | 
 | 
        } catch (IOException e) { | 
 | 
        }  | 
 | 
 | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void doFetch() { | 
 | 
        synchronized (this) { | 
 | 
            if (consumers == null) { | 
 | 
                awaitingFetch = false;  | 
 | 
                return;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        ImageDecoder imgd = getDecoder();  | 
 | 
        if (imgd == null) { | 
 | 
            badDecoder();  | 
 | 
        } else { | 
 | 
            setDecoder(imgd);  | 
 | 
            try { | 
 | 
                imgd.produceImage();  | 
 | 
            } catch (IOException e) { | 
 | 
                e.printStackTrace();  | 
 | 
                // the finally clause will send an error.  | 
 | 
            } catch (ImageFormatException e) { | 
 | 
                e.printStackTrace();  | 
 | 
                // the finally clause will send an error.  | 
 | 
            } finally { | 
 | 
                removeDecoder(imgd);  | 
 | 
                if ( Thread.currentThread().isInterrupted() || !Thread.currentThread().isAlive()) { | 
 | 
                    errorAllConsumers(imgd.queue, true);  | 
 | 
                } else { | 
 | 
                    errorAllConsumers(imgd.queue, false);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void badDecoder() { | 
 | 
        ImageConsumerQueue cq;  | 
 | 
        synchronized (this) { | 
 | 
            cq = consumers;  | 
 | 
            consumers = null;  | 
 | 
            awaitingFetch = false;  | 
 | 
        }  | 
 | 
        errorAllConsumers(cq, false);  | 
 | 
    }  | 
 | 
 | 
 | 
    private void setDecoder(ImageDecoder mydecoder) { | 
 | 
        ImageConsumerQueue cq;  | 
 | 
        synchronized (this) { | 
 | 
            mydecoder.next = decoders;  | 
 | 
            decoders = mydecoder;  | 
 | 
            decoder = mydecoder;  | 
 | 
            cq = consumers;  | 
 | 
            mydecoder.queue = cq;  | 
 | 
            consumers = null;  | 
 | 
            awaitingFetch = false;  | 
 | 
        }  | 
 | 
        while (cq != null) { | 
 | 
            if (cq.interested) { | 
 | 
                // Now that there is a decoder, security may have changed  | 
 | 
                  | 
 | 
                if (!checkSecurity(cq.securityContext, true)) { | 
 | 
                    errorConsumer(cq, false);  | 
 | 
                }  | 
 | 
            }  | 
 | 
            cq = cq.next;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private synchronized void removeDecoder(ImageDecoder mydecoder) { | 
 | 
        doneDecoding(mydecoder);  | 
 | 
        ImageDecoder idprev = null;  | 
 | 
        for (ImageDecoder id = decoders; id != null; id = id.next) { | 
 | 
            if (id == mydecoder) { | 
 | 
                if (idprev == null) { | 
 | 
                    decoders = id.next;  | 
 | 
                } else { | 
 | 
                    idprev.next = id.next;  | 
 | 
                }  | 
 | 
                break;  | 
 | 
            }  | 
 | 
            idprev = id;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    synchronized void doneDecoding(ImageDecoder mydecoder) { | 
 | 
        if (decoder == mydecoder) { | 
 | 
            decoder = null;  | 
 | 
            if (consumers != null) { | 
 | 
                startProduction();  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    void latchConsumers(ImageDecoder id) { | 
 | 
        doneDecoding(id);  | 
 | 
    }  | 
 | 
 | 
 | 
    synchronized void flush() { | 
 | 
        decoder = null;  | 
 | 
    }  | 
 | 
}  |