001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2015 ForgeRock AS 026 */ 027 028package org.opends.guitools.controlpanel.datamodel; 029 030import java.io.File; 031import java.text.ParseException; 032import java.util.Objects; 033 034import org.opends.server.util.Base64; 035 036/** 037 * Class used to represent Binary Values. This is required in particular 038 * when the user wants to use the value in a file. To be able to reflect 039 * this this object is used: it contains the binary itself, the base 64 040 * representation and the file that has been used. 041 * 042 */ 043public class BinaryValue 044{ 045 private Type type; 046 private String base64; 047 private byte[] bytes; 048 private File file; 049 private int hashCode; 050 051 /** 052 * The type of the binary value. 053 * 054 */ 055 public enum Type 056 { 057 /** 058 * The binary value is provided as Base 64 string. 059 */ 060 BASE64_STRING, 061 /** 062 * The binary value is provided as a byte array. 063 */ 064 BYTE_ARRAY 065 } 066 067 /** 068 * This is done to force the use of the factory methods (createBase64 and 069 * createFromFile). 070 * 071 */ 072 private BinaryValue() 073 { 074 } 075 076 /** 077 * Creates a binary value using a base64 string. 078 * @param base64 the base64 representation of the binary. 079 * @return the binary value. 080 * @throws ParseException if there is an error decoding the provided base64 081 * string. 082 */ 083 public static BinaryValue createBase64(String base64) throws ParseException 084 { 085 BinaryValue value = new BinaryValue(); 086 value.type = Type.BASE64_STRING; 087 value.base64 = base64; 088 value.bytes = value.getBytes(); 089 value.hashCode = base64.hashCode(); 090 return value; 091 } 092 093 /** 094 * Creates a binary value using an array of bytes. 095 * @param bytes the byte array. 096 * @return the binary value. 097 */ 098 public static BinaryValue createBase64(byte[] bytes) 099 { 100 BinaryValue value = new BinaryValue(); 101 value.type = Type.BASE64_STRING; 102 value.bytes = bytes; 103 value.base64 = value.getBase64(); 104 value.hashCode = value.base64.hashCode(); 105 return value; 106 } 107 108 /** 109 * Creates a binary value using an array of bytes and a file. 110 * @param bytes the bytes in the file. 111 * @param file the file the bytes were read from. 112 * @return the binary value. 113 */ 114 public static BinaryValue createFromFile(byte[] bytes, File file) 115 { 116 BinaryValue value = new BinaryValue(); 117 value.type = Type.BYTE_ARRAY; 118 value.bytes = bytes; 119 value.base64 = value.getBase64(); 120 value.hashCode = value.base64.hashCode(); 121 value.file = file; 122 return value; 123 } 124 125 /** 126 * Returns the base64 representation of the binary value. 127 * @return the base64 representation of the binary value. 128 */ 129 public String getBase64() 130 { 131 if (base64 == null && bytes != null) 132 { 133 base64 = Base64.encode(bytes); 134 } 135 return base64; 136 } 137 138 /** 139 * Returns the byte array of the binary value. 140 * @return the byte array of the binary value. 141 * @throws ParseException if this object was created using a base64 string 142 * and there was an error parsing it. 143 */ 144 public byte[] getBytes() throws ParseException 145 { 146 if (bytes == null && base64 != null) 147 { 148 bytes = Base64.decode(base64); 149 } 150 return bytes; 151 } 152 153 /** 154 * Return the type of the binary value. 155 * @return the type of the binary value. 156 */ 157 public Type getType() 158 { 159 return type; 160 } 161 162 /** 163 * Return the file that was used to read the binary value. 164 * @return the file that was used to read the binary value. 165 */ 166 public File getFile() 167 { 168 return file; 169 } 170 171 /** {@inheritDoc} */ 172 public boolean equals(Object o) 173 { 174 if (this == o) 175 { 176 return true; 177 } 178 if (o instanceof BinaryValue) 179 { 180 BinaryValue candidate = (BinaryValue)o; 181 return candidate.getType() == getType() 182 && Objects.equals(file, candidate.getFile()) 183 && bytesEqual(candidate); 184 } 185 return false; 186 } 187 188 private boolean bytesEqual(BinaryValue candidate) 189 { 190 if (type == Type.BASE64_STRING) 191 { 192 return candidate.getBase64().equals(getBase64()); 193 } 194 195 try 196 { 197 if (candidate.getBytes().length != getBytes().length) { 198 return false; 199 } 200 boolean equals = true; 201 for (int i=0; i<getBytes().length && equals; i++) 202 { 203 equals = bytes[i] == candidate.getBytes()[i]; 204 } 205 return equals; 206 } 207 catch (ParseException pe) 208 { 209 throw new RuntimeException( 210 "Unexpected error getting bytes: "+pe, pe); 211 } 212 } 213 214 /** {@inheritDoc} */ 215 public int hashCode() 216 { 217 return hashCode; 218 } 219}