1 /*
   2  * Copyright (c) 2003, 2008, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package sun.print;
  26 
  27 import java.util.Objects;
  28 import java.io.ByteArrayInputStream;
  29 
  30 public class AttributeClass {
  31     private String myName;
  32     private int myType;
  33     private int nameLen;
  34     private Object myValue;
  35 
  36     public static final int TAG_UNSUPPORTED_VALUE = 0x10;
  37     public static final int TAG_INT = 0x21;
  38     public static final int TAG_BOOL = 0x22;
  39     public static final int TAG_ENUM = 0x23;
  40     public static final int TAG_OCTET = 0x30;
  41     public static final int TAG_DATE = 0x31;
  42     public static final int TAG_RESOLUTION = 0x32;
  43     public static final int TAG_RANGE_INTEGER = 0x33;
  44 
  45     public static final int TAG_TEXT_LANGUAGE = 0x35;
  46     public static final int TAG_NAME_LANGUAGE = 0x36;
  47 
  48     public static final int TAG_TEXT_WO_LANGUAGE = 0x41;
  49     public static final int TAG_NAME_WO_LANGUAGE = 0x42;
  50     public static final int TAG_KEYWORD = 0x44;
  51     public static final int TAG_URI = 0x45;
  52     public static final int TAG_CHARSET = 0x47;
  53     public static final int TAG_NATURALLANGUAGE = 0x48;
  54     public static final int TAG_MIME_MEDIATYPE = 0x49;
  55     public static final int TAG_MEMBER_ATTRNAME = 0x4A;
  56 
  57 
  58     public static final AttributeClass ATTRIBUTES_CHARSET =
  59         new AttributeClass("attributes-charset",
  60                            TAG_CHARSET, "utf-8");
  61     public static final AttributeClass ATTRIBUTES_NATURAL_LANGUAGE =
  62         new AttributeClass("attributes-natural-language",
  63                            TAG_NATURALLANGUAGE, "en");
  64 
  65     /*
  66      * value passed in by IPPPrintService.readIPPResponse is a sequence
  67      * of bytes with this format
  68      * | length1 | byte1 | byte 2 | ... byten | length2 | byte1 ... byten |
  69      *      :
  70      * | lengthN | byte1 ... byten | total number of values|
  71      */
  72     protected AttributeClass(String name, int type, Object value) {
  73         myName = name;
  74         myType = type;
  75         nameLen = name.length();
  76         myValue = value;
  77     }
  78 
  79     public byte getType() {
  80         return (byte)myType;
  81     }
  82 
  83     public char[] getLenChars() {
  84         char[] chars = new char[2];
  85         chars[0] = 0;
  86         chars[1] = (char)nameLen;
  87         return chars;
  88     }
  89 
  90     /**
  91      * Returns raw data.
  92      */
  93     public Object getObjectValue() {
  94         return myValue;
  95     }
  96 
  97     /**
  98      * Returns single int value.
  99      */
 100     public int getIntValue() {
 101         byte[] bufArray = (byte[])myValue;
 102 
 103         if (bufArray != null) {
 104             byte[] buf = new byte[4];
 105             for (int i=0; i<4; i++) {
 106                 buf[i] = bufArray[i+1];
 107             }
 108 
 109             return convertToInt(buf);
 110         }
 111         return 0;
 112     }
 113 
 114     /**
 115      * Returns array of int values.
 116      */
 117     public int[] getArrayOfIntValues() {
 118 
 119         byte[] bufArray = (byte[])myValue;
 120         if (bufArray != null) {
 121 
 122             //ArrayList valList = new ArrayList();
 123             ByteArrayInputStream bufStream =
 124                 new ByteArrayInputStream(bufArray);
 125             int available = bufStream.available();
 126 
 127             // total number of values is at the end of the stream
 128             bufStream.mark(available);
 129             bufStream.skip(available-1);
 130             int length = bufStream.read();
 131             bufStream.reset();
 132 
 133             int[] valueArray = new int[length];
 134             for (int i = 0; i < length; i++) {
 135                 // read length
 136                 int valLength = bufStream.read();
 137                 if (valLength != 4) {
 138                     // invalid data
 139                     return null;
 140                 }
 141 
 142                 byte[] bufBytes = new byte[valLength];
 143                 bufStream.read(bufBytes, 0, valLength);
 144                 valueArray[i] = convertToInt(bufBytes);
 145 
 146             }
 147             return valueArray;
 148         }
 149         return null;
 150     }
 151 
 152     /**
 153      * Returns 2 int values.
 154      */
 155     public int[] getIntRangeValue() {
 156         int[] range = {0, 0};
 157         byte[] bufArray = (byte[])myValue;
 158         if (bufArray != null) {
 159             int nBytes = 4; // 32-bit signed integer
 160             for (int j=0; j<2; j++) { // 2 set of integers
 161                 byte[] intBytes = new byte[nBytes];
 162                 // REMIND: # bytes should be 8
 163                 for (int i=0; i< nBytes; i++) {
 164                     //+ 1 because the 1st byte is length
 165                     intBytes[i] = bufArray[i+(4*j)+1];
 166                 }
 167                 range[j] = convertToInt(intBytes);
 168             }
 169         }
 170         return range;
 171 
 172     }
 173 
 174     /**
 175      * Returns String value.
 176      */
 177     public String getStringValue() {
 178         //assumes only 1 attribute value.  Will get the first value
 179         // if > 1.
 180         String strVal = null;
 181         byte[] bufArray = (byte[])myValue;
 182         if (bufArray != null) {
 183             ByteArrayInputStream bufStream =
 184                 new ByteArrayInputStream(bufArray);
 185 
 186             int valLength = bufStream.read();
 187 
 188             byte[] strBytes = new byte[valLength];
 189             bufStream.read(strBytes, 0, valLength);
 190             try {
 191                 strVal = new String(strBytes, "UTF-8");
 192             } catch (java.io.UnsupportedEncodingException uee) {
 193             }
 194         }
 195         return strVal;
 196     }
 197 
 198 
 199     /**
 200      * Returns array of String values.
 201      */
 202     public String[] getArrayOfStringValues() {
 203 
 204         byte[] bufArray = (byte[])myValue;
 205         if (bufArray != null) {
 206             ByteArrayInputStream bufStream =
 207                 new ByteArrayInputStream(bufArray);
 208             int available = bufStream.available();
 209 
 210             // total number of values is at the end of the stream
 211             bufStream.mark(available);
 212             bufStream.skip(available-1);
 213             int length = bufStream.read();
 214             bufStream.reset();
 215 
 216             String[] valueArray = new String[length];
 217             for (int i = 0; i < length; i++) {
 218                 // read length
 219                 int valLength = bufStream.read();
 220                 byte[] bufBytes = new byte[valLength];
 221                 bufStream.read(bufBytes, 0, valLength);
 222                 try {
 223                     valueArray[i] = new String(bufBytes, "UTF-8");
 224                 } catch (java.io.UnsupportedEncodingException uee) {
 225                 }
 226             }
 227             return valueArray;
 228         }
 229         return null;
 230     }
 231 
 232 
 233     /**
 234      * Returns single byte value.
 235      */
 236     public byte getByteValue() {
 237         byte[] bufArray = (byte[])myValue;
 238 
 239         if ((bufArray != null) && (bufArray.length>=2)) {
 240             return bufArray[1];
 241         }
 242         return 0;
 243     }
 244 
 245     /**
 246      * Returns attribute name.
 247      */
 248     public String getName() {
 249         return myName;
 250     }
 251 
 252     @Override
 253     public boolean equals(Object obj) {
 254         if (!(obj instanceof AttributeClass)) {
 255             return false;
 256         }
 257         if (this == obj) {
 258             return true;
 259         }
 260 
 261         AttributeClass acObj = (AttributeClass) obj;
 262         return myType == acObj.getType() &&
 263                Objects.equals(myName, acObj.getName()) &&
 264                Objects.equals(myValue, acObj.getObjectValue());
 265     }
 266 
 267     @Override
 268     public int hashCode() {
 269         return Objects.hash(myType, myName, myValue);
 270     }
 271 
 272     public String toString() {
 273         return myName;
 274     }
 275 
 276     private int unsignedByteToInt(byte b) {
 277         return (int) (b & 0xff);
 278     }
 279 
 280     private int convertToInt(byte[] buf) {
 281         int intVal = 0;
 282         int pos = 0;
 283         intVal+= unsignedByteToInt(buf[pos++]) << 24;
 284         intVal+= unsignedByteToInt(buf[pos++]) << 16;
 285         intVal+= unsignedByteToInt(buf[pos++]) << 8;
 286         intVal+= unsignedByteToInt(buf[pos++]) << 0;
 287         return intVal;
 288     }
 289 }