001/*
002 * Syncany, www.syncany.org
003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com> 
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU General Public License as published by
007 * the Free Software Foundation, either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018package org.syncany.database;
019
020import java.security.SecureRandom;
021import java.util.Arrays;
022
023import org.syncany.util.StringUtil;
024
025/**
026 * The object ID is a generic identifier used by the database entities.
027 * As of now, it uses a byte array internally, but could also use different
028 * more memory-preserving methods (such as two longs).  
029 * 
030 * @author Fabrice Rossi (fabrice.rossi@apiacoa.org)
031 */
032public abstract class ObjectId {
033        private static SecureRandom secureRng = new SecureRandom();
034        protected byte[] identifier;
035        
036        public ObjectId(byte[] identifier) {
037                if (identifier == null) {
038                        throw new IllegalArgumentException("Argument 'identifier' cannot be null.");
039                }
040                
041                this.identifier = identifier;
042        }
043        
044        /**
045         * Returns the raw representation of the object identifier in the
046         * form of a byte array.  
047         */
048        public byte[] getBytes() {
049                return Arrays.copyOf(identifier, identifier.length);
050        }
051
052        /**
053         * Converts the byte-array based identifier to a lower 
054         * case hex string and returns this string.
055         */
056        @Override
057        public String toString() {
058                return StringUtil.toHex(identifier);
059        }
060
061        public static byte[] parseObjectId(String s) {
062                if (s == null) {
063                        throw new IllegalArgumentException("Argument 's' cannot be null.");
064                }
065                
066                return StringUtil.fromHex(s);
067        }
068
069        public static byte[] secureRandomBytes(int size) {
070                byte[] newRandomBytes = new byte[size]; 
071                
072                synchronized (secureRng) {
073                        secureRng.nextBytes(newRandomBytes);                    
074                }
075                
076                return newRandomBytes;
077        }               
078        
079        @Override
080        public int hashCode() {
081                final int prime = 31;
082                int result = 1;
083                result = prime * result + Arrays.hashCode(identifier);
084                return result;
085        }
086
087        @Override
088        public boolean equals(Object obj) {
089                if (this == obj) {
090                        return true;
091                }
092                if (obj == null) {
093                        return false;
094                }
095                if (!(obj instanceof ObjectId)) {
096                        return false;
097                }
098                ObjectId other = (ObjectId) obj;
099                if (!Arrays.equals(identifier, other.identifier)) {
100                        return false;
101                }
102                return true;
103        }
104}