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 Sun Microsystems, Inc. 025 * Portions Copyright 2013-2014 ForgeRock AS. 026 */ 027package org.forgerock.opendj.config.dsconfig; 028 029import static com.forgerock.opendj.ldap.ConfigMessages.ERR_BUILDVERSION_MISMATCH; 030import static com.forgerock.opendj.ldap.ConfigMessages.ERR_BUILDVERSION_MALFORMED; 031import static com.forgerock.opendj.ldap.ConfigMessages.ERR_BUILDVERSION_NOT_FOUND; 032import static com.forgerock.opendj.ldap.ConfigMessages.ERR_CONFIGVERSION_NOT_FOUND; 033import static org.forgerock.util.Utils.closeSilently; 034 035import java.io.BufferedReader; 036import java.io.File; 037import java.io.FileReader; 038import java.io.IOException; 039import java.util.Arrays; 040 041import org.forgerock.opendj.config.ConfigurationFramework; 042import org.forgerock.opendj.config.server.ConfigException; 043import org.forgerock.opendj.ldap.Connection; 044import org.forgerock.opendj.ldap.LdapException; 045import org.forgerock.opendj.ldap.responses.SearchResultEntry; 046 047/** 048 * Represents a particular version of OpenDJ useful for making comparisons between versions. FIXME TODO Move this file 049 * in ? package. 050 */ 051public class BuildVersion implements Comparable<BuildVersion> { 052 053 private final int major; 054 private final int minor; 055 private final int point; 056 private final long rev; 057 058 /** 059 * Creates a new build version using the provided version information. 060 * 061 * @param major 062 * Major release version number. 063 * @param minor 064 * Minor release version number. 065 * @param point 066 * Point release version number. 067 * @param rev 068 * VCS revision number. 069 */ 070 public BuildVersion(final int major, final int minor, final int point, final long rev) { 071 this.major = major; 072 this.minor = minor; 073 this.point = point; 074 this.rev = rev; 075 } 076 077 /** 078 * Returns the build version as specified in the entry "cn=Version,cn=monitor". 079 * 080 * @param connection 081 * The connection to use to read the entry. 082 * @return The build version as specified in the current installation configuration. 083 * @throws ConfigException 084 * Sends an exception if it is impossible to retrieve the version configuration entry. 085 */ 086 public static BuildVersion binaryVersion(final Connection connection) throws ConfigException { 087 try { 088 final SearchResultEntry entry = connection.readEntry("", "fullVendorVersion"); 089 return valueOf(entry.getAttribute("fullVendorVersion").firstValueAsString()); 090 } catch (LdapException e) { 091 throw new ConfigException(ERR_CONFIGVERSION_NOT_FOUND.get()); 092 } 093 } 094 095 /** 096 * Checks if the binary version is the same than the instance version. If not, a configuration exception is thrown. 097 * 098 * @param connection 099 * The connection to use to read the configuration entry. 100 * @throws ConfigException 101 * Sends an exception if the version mismatch. 102 */ 103 public static void checkVersionMismatch(final Connection connection) throws ConfigException { 104 final BuildVersion binaryVersion = BuildVersion.binaryVersion(connection); 105 final BuildVersion instanceVersion = BuildVersion.instanceVersion(); 106 if (!binaryVersion.toString().equals(instanceVersion.toString())) { 107 throw new ConfigException(ERR_BUILDVERSION_MISMATCH.get(binaryVersion, instanceVersion)); 108 } 109 } 110 111 /** 112 * Reads the instance version from config/buildinfo. 113 * 114 * @return The instance version from config/buildinfo. 115 * @throws ConfigException 116 * If an error occurred while reading or parsing the version. 117 */ 118 public static BuildVersion instanceVersion() throws ConfigException { 119 final String buildInfo = ConfigurationFramework.getInstance().getInstancePath() + File.separator + "config" 120 + File.separator + "buildinfo"; 121 BufferedReader reader = null; 122 try { 123 reader = new BufferedReader(new FileReader(buildInfo)); 124 final String s = reader.readLine(); 125 if (s != null) { 126 return valueOf(s); 127 } else { 128 throw new ConfigException(ERR_BUILDVERSION_MALFORMED.get(buildInfo)); 129 } 130 } catch (IOException e) { 131 throw new ConfigException(ERR_BUILDVERSION_NOT_FOUND.get(buildInfo)); 132 } catch (final IllegalArgumentException e) { 133 throw new ConfigException(ERR_BUILDVERSION_MALFORMED.get(buildInfo)); 134 } finally { 135 closeSilently(reader); 136 } 137 } 138 139 /** 140 * Parses the string argument as a build version. The string must be of the form: 141 * 142 * <pre> 143 * major.minor.point.rev 144 * </pre> 145 * 146 * @param s 147 * The string to be parsed as a build version. 148 * @return The parsed build version. 149 * @throws IllegalArgumentException 150 * If the string does not contain a parsable build version. 151 */ 152 public static BuildVersion valueOf(final String s) { 153 final String[] fields = s.split("\\."); 154 if (fields.length != 4) { 155 throw new IllegalArgumentException("Invalid version string " + s); 156 } 157 final int major = Integer.parseInt(fields[0]); 158 final int minor = Integer.parseInt(fields[1]); 159 final int point = Integer.parseInt(fields[2]); 160 final long rev = Long.parseLong(fields[3]); 161 return new BuildVersion(major, minor, point, rev); 162 } 163 164 /** 165 * Returns the major release version number. 166 * 167 * @return The major release version number. 168 */ 169 public int getMajorVersion() { 170 return major; 171 } 172 173 /** 174 * Returns the minor release version number. 175 * 176 * @return The minor release version number. 177 */ 178 public int getMinorVersion() { 179 return minor; 180 } 181 182 /** 183 * Returns the point release version number. 184 * 185 * @return The point release version number. 186 */ 187 public int getPointVersion() { 188 return point; 189 } 190 191 /** {@inheritDoc} */ 192 public boolean equals(final Object obj) { 193 if (this == obj) { 194 return true; 195 } else if (obj instanceof BuildVersion) { 196 final BuildVersion other = (BuildVersion) obj; 197 return major == other.major && minor == other.minor && point == other.point && rev == other.rev; 198 } else { 199 return false; 200 } 201 } 202 203 /** {@inheritDoc} */ 204 public int compareTo(final BuildVersion version) { 205 if (major == version.major) { 206 if (minor == version.minor) { 207 if (point == version.point) { 208 if (rev == version.rev) { 209 return 0; 210 } else if (rev < version.rev) { 211 return -1; 212 } 213 } else if (point < version.point) { 214 return -1; 215 } 216 } else if (minor < version.minor) { 217 return -1; 218 } 219 } else if (major < version.major) { 220 return -1; 221 } 222 return 1; 223 } 224 225 /** 226 * Returns the VCS revision number. 227 * 228 * @return The VCS revision number. 229 */ 230 public long getRevisionNumber() { 231 return rev; 232 } 233 234 /** {@inheritDoc} */ 235 public int hashCode() { 236 return Arrays.hashCode(new int[] { major, minor, point, (int) (rev >>> 32), (int) (rev & 0xFFFFL) }); 237 } 238 239 /** 240 * Returns the string representation of the version. E.g: 241 * 242 * <pre> 243 * version : 2.8.0.1022 244 * </pre> 245 * 246 * @return The string representation of the version. 247 */ 248 public String toString() { 249 final StringBuilder builder = new StringBuilder(); 250 builder.append(major); 251 builder.append('.'); 252 builder.append(minor); 253 builder.append('.'); 254 builder.append(point); 255 builder.append('.'); 256 builder.append(rev); 257 return builder.toString(); 258 } 259}