001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.io; 018 019 import java.io.Serializable; 020 021 /** 022 * Byte Order Mark (BOM) representation - 023 * see {@link org.apache.commons.io.input.BOMInputStream}. 024 * 025 * @see org.apache.commons.io.input.BOMInputStream 026 * @see <a href="http://en.wikipedia.org/wiki/Byte_order_mark">Wikipedia - Byte Order Mark</a> 027 * @version $Id: ByteOrderMark.java 1005099 2010-10-06 16:13:01Z niallp $ 028 * @since Commons IO 2.0 029 */ 030 public class ByteOrderMark implements Serializable { 031 032 private static final long serialVersionUID = 1L; 033 034 /** UTF-8 BOM */ 035 public static final ByteOrderMark UTF_8 = new ByteOrderMark("UTF-8", 0xEF, 0xBB, 0xBF); 036 /** UTF-16BE BOM (Big Endian) */ 037 public static final ByteOrderMark UTF_16BE = new ByteOrderMark("UTF-16BE", 0xFE, 0xFF); 038 /** UTF-16LE BOM (Little Endian) */ 039 public static final ByteOrderMark UTF_16LE = new ByteOrderMark("UTF-16LE", 0xFF, 0xFE); 040 041 private final String charsetName; 042 private final int[] bytes; 043 044 /** 045 * Construct a new BOM. 046 * 047 * @param charsetName The name of the charset the BOM represents 048 * @param bytes The BOM's bytes 049 * @throws IllegalArgumentException if the charsetName is null or 050 * zero length 051 * @throws IllegalArgumentException if the bytes are null or zero 052 * length 053 */ 054 public ByteOrderMark(String charsetName, int... bytes) { 055 if (charsetName == null || charsetName.length() == 0) { 056 throw new IllegalArgumentException("No charsetName specified"); 057 } 058 if (bytes == null || bytes.length == 0) { 059 throw new IllegalArgumentException("No bytes specified"); 060 } 061 this.charsetName = charsetName; 062 this.bytes = new int[bytes.length]; 063 System.arraycopy(bytes, 0, this.bytes, 0, bytes.length); 064 } 065 066 /** 067 * Return the name of the {@link java.nio.charset.Charset} the BOM represents. 068 * 069 * @return the character set name 070 */ 071 public String getCharsetName() { 072 return charsetName; 073 } 074 075 /** 076 * Return the length of the BOM's bytes. 077 * 078 * @return the length of the BOM's bytes 079 */ 080 public int length() { 081 return bytes.length; 082 } 083 084 /** 085 * The byte at the specified position. 086 * 087 * @param pos The position 088 * @return The specified byte 089 */ 090 public int get(int pos) { 091 return bytes[pos]; 092 } 093 094 /** 095 * Return a copy of the BOM's bytes. 096 * 097 * @return a copy of the BOM's bytes 098 */ 099 public byte[] getBytes() { 100 byte[] copy = new byte[bytes.length]; 101 for (int i = 0; i < bytes.length; i++) { 102 copy[i] = (byte)bytes[i]; 103 } 104 return copy; 105 } 106 107 /** 108 * Indicates if this BOM's bytes equals another. 109 * 110 * @param obj The object to compare to 111 * @return true if the bom's bytes are equal, otherwise 112 * false 113 */ 114 @Override 115 public boolean equals(Object obj) { 116 if (!(obj instanceof ByteOrderMark)) { 117 return false; 118 } 119 ByteOrderMark bom = (ByteOrderMark)obj; 120 if (bytes.length != bom.length()) { 121 return false; 122 } 123 for (int i = 0; i < bytes.length; i++) { 124 if (bytes[i] != bom.get(i)) { 125 return false; 126 } 127 } 128 return true; 129 } 130 131 /** 132 * Return the hashcode for this BOM. 133 * 134 * @return the hashcode for this BOM. 135 * @see java.lang.Object#hashCode() 136 */ 137 @Override 138 public int hashCode() { 139 int hashCode = getClass().hashCode(); 140 for (int b : bytes) { 141 hashCode += b; 142 } 143 return hashCode; 144 } 145 146 /** 147 * Provide a String representation of the BOM. 148 * 149 * @return the length of the BOM's bytes 150 */ 151 @Override 152 public String toString() { 153 StringBuilder builder = new StringBuilder(); 154 builder.append(getClass().getSimpleName()); 155 builder.append('['); 156 builder.append(charsetName); 157 builder.append(": "); 158 for (int i = 0; i < bytes.length; i++) { 159 if (i > 0) { 160 builder.append(","); 161 } 162 builder.append("0x"); 163 builder.append(Integer.toHexString(0xFF & bytes[i]).toUpperCase()); 164 } 165 builder.append(']'); 166 return builder.toString(); 167 } 168 169 }