001 /* 002 * JBoss, Home of Professional Open Source. 003 * Copyright 2008, Red Hat Middleware LLC, and individual contributors 004 * as indicated by the @author tags. See the copyright.txt file in the 005 * distribution for a full listing of individual contributors. 006 * 007 * This is free software; you can redistribute it and/or modify it 008 * under the terms of the GNU Lesser General Public License as 009 * published by the Free Software Foundation; either version 2.1 of 010 * the License, or (at your option) any later version. 011 * 012 * This software is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this software; if not, write to the Free 019 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 020 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 021 */ 022 package org.jboss.dna.graph.properties.basic; 023 024 import java.io.ByteArrayInputStream; 025 import java.io.InputStream; 026 import java.security.MessageDigest; 027 import java.security.NoSuchAlgorithmException; 028 import java.util.Set; 029 import java.util.concurrent.CopyOnWriteArraySet; 030 import net.jcip.annotations.Immutable; 031 import org.jboss.dna.common.util.Base64; 032 import org.jboss.dna.common.util.CheckArg; 033 import org.jboss.dna.common.util.Logger; 034 import org.jboss.dna.graph.GraphI18n; 035 import org.jboss.dna.graph.properties.Binary; 036 import org.jboss.dna.graph.properties.ValueComparators; 037 038 /** 039 * An implementation of {@link Binary} that keeps the binary data in-memory. 040 * 041 * @author Randall Hauch 042 */ 043 @Immutable 044 public class InMemoryBinary implements Binary { 045 046 protected static final Set<String> ALGORITHMS_NOT_FOUND_AND_LOGGED = new CopyOnWriteArraySet<String>(); 047 private static final String SHA1DIGEST_NAME = "SHA-1"; 048 private static final byte[] NO_HASH = new byte[] {}; 049 050 /** 051 */ 052 private static final long serialVersionUID = 8792863149767123559L; 053 054 protected static final byte[] EMPTY_CONTENT = new byte[0]; 055 056 private final byte[] bytes; 057 private byte[] sha1hash; 058 059 public InMemoryBinary( byte[] bytes ) { 060 CheckArg.isNotNull(bytes, "bytes"); 061 this.bytes = bytes; 062 } 063 064 /** 065 * {@inheritDoc} 066 */ 067 public long getSize() { 068 return this.bytes.length; 069 } 070 071 /** 072 * {@inheritDoc} 073 * 074 * @see org.jboss.dna.graph.properties.Binary#getHash() 075 */ 076 public byte[] getHash() { 077 if (sha1hash == null) { 078 // Omnipotent, so doesn't matter if we recompute in concurrent threads ... 079 try { 080 sha1hash = getHash(SHA1DIGEST_NAME); 081 } catch (NoSuchAlgorithmException e) { 082 if (ALGORITHMS_NOT_FOUND_AND_LOGGED.add(SHA1DIGEST_NAME)) { 083 Logger.getLogger(getClass()).error(e, GraphI18n.messageDigestNotFound, SHA1DIGEST_NAME); 084 } 085 sha1hash = NO_HASH; 086 } 087 } 088 return sha1hash; 089 } 090 091 /** 092 * Get the hash of the contents, using the digest identified by the supplied name. 093 * 094 * @param digestName the name of the hashing function (or {@link MessageDigest message digest}) that should be used 095 * @return the hash of the contents as a byte array 096 * @throws NoSuchAlgorithmException if the supplied algorithm could not be found 097 */ 098 protected byte[] getHash( String digestName ) throws NoSuchAlgorithmException { 099 MessageDigest digest = MessageDigest.getInstance(digestName); 100 assert digest != null; 101 return digest.digest(bytes); 102 } 103 104 /** 105 * {@inheritDoc} 106 */ 107 public byte[] getBytes() { 108 return this.bytes; 109 } 110 111 /** 112 * {@inheritDoc} 113 */ 114 public InputStream getStream() { 115 return new ByteArrayInputStream(this.bytes); 116 } 117 118 /** 119 * {@inheritDoc} 120 */ 121 public void acquire() { 122 // do nothing 123 } 124 125 /** 126 * {@inheritDoc} 127 */ 128 public void release() { 129 // do nothing 130 } 131 132 /** 133 * {@inheritDoc} 134 */ 135 public int compareTo( Binary o ) { 136 return ValueComparators.BINARY_COMPARATOR.compare(this, o); 137 } 138 139 /** 140 * {@inheritDoc} 141 */ 142 @Override 143 public boolean equals( Object obj ) { 144 if (obj == this) return true; 145 if (obj instanceof Binary) { 146 Binary that = (Binary)obj; 147 if (this.getSize() != that.getSize()) return false; 148 return ValueComparators.BINARY_COMPARATOR.compare(this, that) == 0; 149 } 150 return false; 151 } 152 153 /** 154 * {@inheritDoc} 155 */ 156 @Override 157 public String toString() { 158 StringBuilder sb = new StringBuilder(super.toString()); 159 sb.append(" len=").append(getSize()).append("; ["); 160 sb.append(Base64.encodeBytes(this.bytes)); 161 return sb.toString(); 162 } 163 164 }