1/*
2 * Copyright (c) 2012, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug 5082756
27 * @summary ensure that boolean attributes follow ( "TRUE" | "FALSE" )
28 *          including correct (i.e. upper) case
29 *
30 * @run main BooleanAttributes
31 */
32
33import java.awt.image.BufferedImage;
34import java.io.ByteArrayInputStream;
35import java.io.ByteArrayOutputStream;
36import java.io.StringReader;
37import java.util.Arrays;
38import java.util.List;
39import javax.imageio.IIOImage;
40import javax.imageio.ImageIO;
41import javax.imageio.ImageReader;
42import javax.imageio.ImageTypeSpecifier;
43import javax.imageio.ImageWriteParam;
44import javax.imageio.ImageWriter;
45import javax.imageio.metadata.IIOMetadata;
46import javax.imageio.stream.ImageInputStream;
47import javax.imageio.stream.ImageOutputStream;
48import javax.imageio.stream.MemoryCacheImageInputStream;
49import javax.imageio.stream.MemoryCacheImageOutputStream;
50import javax.xml.transform.Result;
51import javax.xml.transform.Source;
52import javax.xml.transform.TransformerFactory;
53import javax.xml.transform.dom.DOMResult;
54import javax.xml.transform.stream.StreamSource;
55import javax.xml.xpath.XPath;
56import javax.xml.xpath.XPathConstants;
57import javax.xml.xpath.XPathFactory;
58import org.w3c.dom.Document;
59import org.w3c.dom.Element;
60import org.w3c.dom.Node;
61import org.w3c.dom.NodeList;
62
63public class BooleanAttributes {
64
65    private static TransformerFactory transformerFactory =
66        TransformerFactory.newInstance();
67
68    private static XPath xpathEngine = XPathFactory.newInstance().newXPath();
69
70    public static void main(String[] args) throws Exception {
71        test("image/png", false, "<javax_imageio_1.0 />",
72             "Chroma/BlackIsZero/@value",
73             "Compression/Lossless/@value");
74
75        test("image/png", false,
76             "<javax_imageio_png_1.0>" +
77             "<iTXt><iTXtEntry keyword='Comment' compressionFlag='TRUE' " +
78             "compressionMethod='0' languageTag='en' " +
79             "translatedKeyword='comment' text='foo'/></iTXt>" +
80             "</javax_imageio_png_1.0>",
81             "iTXt/iTXtEntry/@compressionFlag");
82
83        test("image/png", false,
84             "<javax_imageio_png_1.0>" +
85             "<iTXt><iTXtEntry keyword='Comment' compressionFlag='FALSE' " +
86             "compressionMethod='0' languageTag='en' " +
87             "translatedKeyword='comment' text='foo'/></iTXt>" +
88             "</javax_imageio_png_1.0>",
89             "iTXt/iTXtEntry/@compressionFlag");
90
91        test("image/gif", false, "<javax_imageio_1.0 />",
92             "Chroma/BlackIsZero/@value",
93             "Compression/Lossless/@value");
94
95        test("image/gif", false,
96             "<javax_imageio_gif_image_1.0>" +
97             "<ImageDescriptor imageLeftPosition='0' imageTopPosition='0' " +
98             "imageWidth='16' imageHeight='16' interlaceFlag='TRUE' />" +
99             "<LocalColorTable sizeOfLocalColorTable='2' " +
100             "backgroundColorIndex='1' sortFlag='TRUE'>" +
101             "<ColorTableEntry index='0' red='0' green='0' blue='0' />" +
102             "<ColorTableEntry index='1' red='255' green='255' blue='255' />" +
103             "</LocalColorTable>" +
104             "<GraphicControlExtension disposalMethod='doNotDispose' " +
105             "userInputFlag='FALSE' transparentColorFlag='TRUE' " +
106             "delayTime='100' transparentColorIndex='1' />" +
107             "</javax_imageio_gif_image_1.0>",
108             "ImageDescriptor/@interlaceFlag",
109             "LocalColorTable/@sortFlag",
110             "GraphicControlExtension/@userInputFlag",
111             "GraphicControlExtension/@transparentColorFlag");
112
113        test("image/gif", true,
114             "<javax_imageio_gif_stream_1.0>" +
115             "<GlobalColorTable sizeOfGlobalColorTable='2' " +
116             "backgroundColorIndex='1' sortFlag='TRUE'>" +
117             "<ColorTableEntry index='0' red='0' green='0' blue='0' />" +
118             "<ColorTableEntry index='1' red='255' green='255' blue='255' />" +
119             "</GlobalColorTable>" +
120             "</javax_imageio_gif_stream_1.0>",
121             "GlobalColorTable/@sortFlag");
122
123        test("image/jpeg", false, "<javax_imageio_1.0 />",
124             "Compression/Lossless/@value");
125    }
126
127    private static void transform(Source src, Result dst)
128        throws Exception
129    {
130        transformerFactory.newTransformer().transform(src, dst);
131    }
132
133    private static void verify(Node meta, String[] xpaths, boolean required)
134        throws Exception
135    {
136        for (String xpath: xpaths) {
137            NodeList list = (NodeList)
138                xpathEngine.evaluate(xpath, meta, XPathConstants.NODESET);
139            if (list.getLength() == 0 && required)
140                throw new AssertionError("Missing value: " + xpath);
141            for (int i = 0; i < list.getLength(); ++i) {
142                String value = list.item(i).getNodeValue();
143                if (!(value.equals("TRUE") || value.equals("FALSE")))
144                    throw new AssertionError(xpath + " has value " + value);
145            }
146        }
147    }
148
149    public static void test(String mimeType, boolean useStreamMeta,
150                            String metaXml, String... boolXpaths)
151        throws Exception
152    {
153        BufferedImage img =
154            new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
155        ImageWriter iw = ImageIO.getImageWritersByMIMEType(mimeType).next();
156        ByteArrayOutputStream os = new ByteArrayOutputStream();
157        ImageOutputStream ios = new MemoryCacheImageOutputStream(os);
158        iw.setOutput(ios);
159        ImageWriteParam param = null;
160        IIOMetadata streamMeta = iw.getDefaultStreamMetadata(param);
161        IIOMetadata imageMeta =
162            iw.getDefaultImageMetadata(new ImageTypeSpecifier(img), param);
163        IIOMetadata meta = useStreamMeta ? streamMeta : imageMeta;
164        Source src = new StreamSource(new StringReader(metaXml));
165        DOMResult dst = new DOMResult();
166        transform(src, dst);
167        Document doc = (Document)dst.getNode();
168        Element node = doc.getDocumentElement();
169        String metaFormat = node.getNodeName();
170
171        // Verify that the default metadata gets formatted correctly.
172        verify(meta.getAsTree(metaFormat), boolXpaths, false);
173
174        meta.mergeTree(metaFormat, node);
175
176        // Verify that the merged metadata gets formatte correctly.
177        verify(meta.getAsTree(metaFormat), boolXpaths, true);
178
179        iw.write(streamMeta, new IIOImage(img, null, imageMeta), param);
180        iw.dispose();
181        ios.close();
182        ImageReader ir = ImageIO.getImageReader(iw);
183        byte[] bytes = os.toByteArray();
184        if (bytes.length == 0)
185            throw new AssertionError("Zero length image file");
186        ByteArrayInputStream is = new ByteArrayInputStream(bytes);
187        ImageInputStream iis = new MemoryCacheImageInputStream(is);
188        ir.setInput(iis);
189        if (useStreamMeta) meta = ir.getStreamMetadata();
190        else meta = ir.getImageMetadata(0);
191
192        // Verify again after writing and re-reading the image
193        verify(meta.getAsTree(metaFormat), boolXpaths, true);
194    }
195
196    public static void xtest(Object... eatAnyArguments) {
197        System.err.println("Disabled test! Change xtest back into test!");
198    }
199
200}
201