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