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