/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.guitools.statuspanel; import java.io.UnsupportedEncodingException; import java.util.logging.Level; import java.util.logging.Logger; import org.opends.quicksetup.util.Utils; import org.opends.server.util.StaticUtils; /** * This class is used to represent a Base DN / Replica and is aimed to be * used by the classes in the DatabasesTableModel class. * */ public class BaseDNDescriptor implements Comparable { /** * An enumeration describing the type of base DN for a given Database. */ public enum Type { /** * The base DN is not replicated. */ NOT_REPLICATED, /** * The base DN is replicated. */ REPLICATED }; private int missingChanges; private DatabaseDescriptor db; private int ageOfOldestMissingChange; private Type type; private String baseDn; private String unescapedDn; private static final Logger LOG = Logger.getLogger(BaseDNDescriptor.class.getName()); /** * Constructor for this class. * @param type the type of replication. * @param baseDn the base DN associated with the Replication. * @param db the database containing this base DN. * @param ageOfOldestMissingChange the number of missing changes. * @param missingChanges the number of missing changes. */ public BaseDNDescriptor(Type type, String baseDn, DatabaseDescriptor db, int ageOfOldestMissingChange, int missingChanges) { this.baseDn = baseDn; this.db = db; this.type = type; this.ageOfOldestMissingChange = ageOfOldestMissingChange; this.missingChanges = missingChanges; try { this.unescapedDn = unescapeUtf8(baseDn); } catch (Throwable t) { this.unescapedDn = baseDn; LOG.log(Level.WARNING, "Error unescaping dn: "+baseDn, t); } } /** * Return the String DN associated with the base DN.. * @return the String DN associated with the base DN. */ public String getDn() { return baseDn; } /** * Return the String DN associated with the base DN with unescaped UTF-8 * characters. * @return the String DN associated with the base DN with unescaped UTF-8 * characters. */ public String getUnescapedDn() { return unescapedDn; } /** * {@inheritDoc} */ public boolean equals(Object v) { boolean equals = false; if (this != v) { if (v instanceof BaseDNDescriptor) { BaseDNDescriptor desc = (BaseDNDescriptor)v; equals = (getType() == desc.getType()) && Utils.areDnsEqual(getDn(), desc.getDn()) && (getAgeOfOldestMissingChange() == desc.getAgeOfOldestMissingChange()) && (getMissingChanges() == desc.getMissingChanges()) && getDatabase().getBackendID().equals( desc.getDatabase().getBackendID()) && (getDatabase().getEntries() == desc.getDatabase().getEntries()); } } else { equals = true; } return equals; } /** * {@inheritDoc} */ public int hashCode() { return (getType().toString() + getAgeOfOldestMissingChange() + getDn() + getDatabase().getBackendID() + getMissingChanges()).hashCode(); } /** * {@inheritDoc} */ public int compareTo(Object o) { int returnValue = -1; if (o instanceof BaseDNDescriptor) { BaseDNDescriptor desc = (BaseDNDescriptor)o; returnValue = desc.getDn().compareTo(getDn()); } return returnValue; } /** * Returns the number of missing changes in the replication topology for * this base DN. * @return the number of missing changes in the replication topology for * this base DN. */ public int getMissingChanges() { return missingChanges; } /** * Returns the age of the oldest missing change in seconds in the * replication topology for this base DN. * @return the age of the oldest missing change in seconds in the * replication topology for this base DN. */ public int getAgeOfOldestMissingChange() { return ageOfOldestMissingChange; } /** * Returns the type for this base DN. * @return the type for this base DN. */ public Type getType() { return type; } /** * Returns the database where this base DN is defined. * @return the database where this base DN is defined. */ public DatabaseDescriptor getDatabase() { return db; } /** * Sets the type of this base DN. * @param type the new type for this base DN. */ void setType(Type type) { this.type = type; } /** * Sets the database containing this base DN. * @param db the database containing this base DN. */ void setDatabase(DatabaseDescriptor db) { this.db = db; } private String unescapeUtf8(String v) throws UnsupportedEncodingException { byte[] stringBytes = v.getBytes("UTF-8"); byte[] decodedBytes = new byte[stringBytes.length]; int pos = 0; for (int i = 0; i < stringBytes.length; i++) { if ((stringBytes[i] == '\\') && (i + 2 < stringBytes.length) && StaticUtils.isHexDigit(stringBytes[i+1]) && StaticUtils.isHexDigit(stringBytes[i+2])) { // Convert hex-encoded UTF-8 to 16-bit chars. byte b; byte escapedByte1 = stringBytes[++i]; switch (escapedByte1) { case '0': b = (byte) 0x00; break; case '1': b = (byte) 0x10; break; case '2': b = (byte) 0x20; break; case '3': b = (byte) 0x30; break; case '4': b = (byte) 0x40; break; case '5': b = (byte) 0x50; break; case '6': b = (byte) 0x60; break; case '7': b = (byte) 0x70; break; case '8': b = (byte) 0x80; break; case '9': b = (byte) 0x90; break; case 'a': case 'A': b = (byte) 0xA0; break; case 'b': case 'B': b = (byte) 0xB0; break; case 'c': case 'C': b = (byte) 0xC0; break; case 'd': case 'D': b = (byte) 0xD0; break; case 'e': case 'E': b = (byte) 0xE0; break; case 'f': case 'F': b = (byte) 0xF0; break; default: throw new IllegalStateException("Unexpected byte: "+escapedByte1); } byte escapedByte2 = stringBytes[++i]; switch (escapedByte2) { case '0': break; case '1': b |= 0x01; break; case '2': b |= 0x02; break; case '3': b |= 0x03; break; case '4': b |= 0x04; break; case '5': b |= 0x05; break; case '6': b |= 0x06; break; case '7': b |= 0x07; break; case '8': b |= 0x08; break; case '9': b |= 0x09; break; case 'a': case 'A': b |= 0x0A; break; case 'b': case 'B': b |= 0x0B; break; case 'c': case 'C': b |= 0x0C; break; case 'd': case 'D': b |= 0x0D; break; case 'e': case 'E': b |= 0x0E; break; case 'f': case 'F': b |= 0x0F; break; default: throw new IllegalStateException("Unexpected byte: "+escapedByte2); } decodedBytes[pos++] = b; } else { decodedBytes[pos++] = stringBytes[i]; } } return new String(decodedBytes, 0, pos, "UTF-8"); } }