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 }