1/*
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
3 */
4/*
5 * Licensed to the Apache Software Foundation (ASF) under one or more
6 * contributor license agreements.  See the NOTICE file distributed with
7 * this work for additional information regarding copyright ownership.
8 * The ASF licenses this file to You under the Apache License, Version 2.0
9 * (the "License"); you may not use this file except in compliance with
10 * the License.  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21package com.sun.org.apache.xml.internal.serialize;
22
23import java.io.OutputStream;
24import java.io.OutputStreamWriter;
25import java.io.UnsupportedEncodingException;
26import java.io.Writer;
27import com.sun.org.apache.xerces.internal.util.EncodingMap;
28import java.nio.charset.Charset;
29import java.nio.charset.CharsetEncoder;
30
31/**
32 * This class represents an encoding.
33 *
34 * @deprecated As of JDK 9, Xerces 2.9.0, Xerces DOM L3 Serializer implementation
35 * is replaced by that of Xalan. Main class
36 * {@link com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl} is replaced
37 * by {@link com.sun.org.apache.xml.internal.serializer.dom3.LSSerializerImpl}.
38 */
39@Deprecated
40public class EncodingInfo {
41
42    // name of encoding as registered with IANA;
43    // preferably a MIME name, but aliases are fine too.
44    String ianaName;
45    String javaName;
46    int lastPrintable;
47
48    // The CharsetEncoder with which we test unusual characters.
49    CharsetEncoder fCharsetEncoder = null;
50
51    // Is the charset encoder usable or available.
52    boolean fHaveTriedCharsetEncoder = false;
53
54    /**
55     * Creates new <code>EncodingInfo</code> instance.
56     */
57    public EncodingInfo(String ianaName, String javaName, int lastPrintable) {
58        this.ianaName = ianaName;
59        this.javaName = EncodingMap.getIANA2JavaMapping(ianaName);
60        this.lastPrintable = lastPrintable;
61    }
62
63    /**
64     * Returns a MIME charset name of this encoding.
65     */
66    public String getIANAName() {
67        return this.ianaName;
68    }
69
70    /**
71     * Returns a writer for this encoding based on
72     * an output stream.
73     *
74     * @return A suitable writer
75     * @exception UnsupportedEncodingException There is no convertor
76     *  to support this encoding
77     */
78    public Writer getWriter(OutputStream output)
79        throws UnsupportedEncodingException {
80        // this should always be true!
81        if (javaName != null)
82            return new OutputStreamWriter(output, javaName);
83        javaName = EncodingMap.getIANA2JavaMapping(ianaName);
84        if(javaName == null)
85            // use UTF-8 as preferred encoding
86            return new OutputStreamWriter(output, "UTF8");
87        return new OutputStreamWriter(output, javaName);
88    }
89
90    /**
91     * Checks whether the specified character is printable or not in this encoding.
92     *
93     * @param ch a code point (0-0x10ffff)
94     */
95    public boolean isPrintable(char ch) {
96        if (ch <= this.lastPrintable) {
97            return true;
98        }
99        return isPrintable0(ch);
100    }
101
102    /**
103     * Checks whether the specified character is printable or not in this encoding.
104     * This method accomplishes this using a java.nio.CharsetEncoder. If NIO isn't
105     * available it will attempt use a sun.io.CharToByteConverter.
106     *
107     * @param ch a code point (0-0x10ffff)
108     */
109    private boolean isPrintable0(char ch) {
110
111        // Attempt to get a CharsetEncoder for this encoding.
112        if (fCharsetEncoder == null && !fHaveTriedCharsetEncoder) {
113            // try and create the CharsetEncoder
114            try {
115                Charset charset = java.nio.charset.Charset.forName(javaName);
116                if (charset.canEncode()) {
117                    fCharsetEncoder = charset.newEncoder();
118                }
119                // This charset cannot be used for encoding, don't try it again...
120                else {
121                    fHaveTriedCharsetEncoder = true;
122                }
123            }
124            catch (Exception e) {
125                // don't try it again...
126                fHaveTriedCharsetEncoder = true;
127            }
128        }
129        // Attempt to use the CharsetEncoder to determine whether the character is printable.
130        if (fCharsetEncoder != null) {
131            try {
132                return fCharsetEncoder.canEncode(ch);
133            }
134            catch (Exception e) {
135                // obviously can't use this charset encoder; possibly a JDK bug
136                fCharsetEncoder = null;
137                fHaveTriedCharsetEncoder = false;
138            }
139        }
140
141        return false;
142    }
143
144    // is this an encoding name recognized by this JDK?
145    // if not, will throw UnsupportedEncodingException
146    public static void testJavaEncodingName(String name)  throws UnsupportedEncodingException {
147        final byte [] bTest = {(byte)'v', (byte)'a', (byte)'l', (byte)'i', (byte)'d'};
148        String s = new String(bTest, name);
149    }
150
151}
152