QpidProperties.java
001 /*
002  *  Licensed to the Apache Software Foundation (ASF) under one
003  *  or more contributor license agreements.  See the NOTICE file
004  *  distributed with this work for additional information
005  *  regarding copyright ownership.  The ASF licenses this file
006  *  to you under the Apache License, Version 2.0 (the
007  *  "License"); you may not use this file except in compliance
008  *  with the License.  You may obtain a copy of the License at
009  *
010  *    http://www.apache.org/licenses/LICENSE-2.0
011  *
012  *  Unless required by applicable law or agreed to in writing,
013  *  software distributed under the License is distributed on an
014  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015  *  KIND, either express or implied.  See the License for the
016  *  specific language governing permissions and limitations
017  *  under the License.
018  *
019  *
020  */
021 package org.apache.qpid.common;
022 
023 import org.slf4j.Logger;
024 import org.slf4j.LoggerFactory;
025 
026 import java.io.IOException;
027 import java.io.InputStream;
028 import java.util.Map;
029 import java.util.Properties;
030 
031 /**
032  * QpidProperties captures the project name, version number, and source code repository revision number from a properties
033  * file which is generated as part of the build process. Normally, the name and version number are pulled from the module
034  * name and version number of the Maven build POM, but could come from other sources if the build system is changed. The
035  * idea behind this, is that every build has these values incorporated directly into its jar file, so that code in the
036  * wild can be identified, should its origination be forgotten.
037  *
038  <p/>To get the build version of any Qpid code call the {@link #main} method. This version string is usually also
039  * printed to the console on broker start up.
040  *
041  <p/><table id="crc"><caption>CRC Card</caption>
042  <tr><td>Load build versioning information into the runtime, for code identification purposes.
043  </table>
044  *
045  * @todo Code to locate/load/log properties can be factored into a reusable properties utils class. Avoid having this
046  *       same snippet of loading code scattered in many places.
047  *
048  * @todo Could also add a build number property for a sequential build number assigned by an automated build system, for
049  *       build reproducability purposes.
050  */
051 public class QpidProperties
052 {
053     /** Used for debugging purposes. */
054     private static final Logger _logger = LoggerFactory.getLogger(QpidProperties.class);
055 
056     /** The name of the version properties file to load from the class path. */
057     public static final String VERSION_RESOURCE = "qpidversion.properties";
058 
059     /** Defines the name of the product property. */
060     public static final String PRODUCT_NAME_PROPERTY = "qpid.name";
061 
062     /** Defines the name of the version property. */
063     public static final String RELEASE_VERSION_PROPERTY = "qpid.version";
064 
065     /** Defines the name of the source code revision property. */
066     public static final String BUILD_VERSION_PROPERTY = "qpid.svnversion";
067 
068     /** Defines the default value for all properties that cannot be loaded. */
069     private static final String DEFAULT = "unknown";
070 
071     /** Holds the product name. */
072     private static String productName = DEFAULT;
073 
074     /** Holds the product version. */
075     private static String releaseVersion = DEFAULT;
076 
077     /** Holds the source code revision. */
078     private static String buildVersion = DEFAULT;
079 
080     // Loads the values from the version properties file.
081     static
082     {
083         Properties props = new Properties();
084 
085         try
086         {
087             InputStream propertyStream = QpidProperties.class.getClassLoader().getResourceAsStream(VERSION_RESOURCE);
088             if (propertyStream == null)
089             {
090                 _logger.warn("Unable to find resource " + VERSION_RESOURCE + " from classloader");
091             }
092             else
093             {
094                 props.load(propertyStream);
095 
096                 if (_logger.isDebugEnabled())
097                 {
098                     _logger.debug("Dumping QpidProperties");
099                     for (Map.Entry<Object, Object> entry : props.entrySet())
100                     {
101                         _logger.debug("Property: " + entry.getKey() " Value: " + entry.getValue());
102                     }
103 
104                     _logger.debug("End of property dump");
105                 }
106 
107                 productName = readPropertyValue(props, PRODUCT_NAME_PROPERTY);
108                 releaseVersion = readPropertyValue(props, RELEASE_VERSION_PROPERTY);
109                 buildVersion = readPropertyValue(props, BUILD_VERSION_PROPERTY);
110             }
111         }
112         catch (IOException e)
113         {
114             // Log a warning about this and leave the values initialized to unknown.
115             _logger.error("Could not load version.properties resource: " + e, e);
116         }
117     }
118 
119     /**
120      * Gets the product name.
121      *
122      @return The product name.
123      */
124     public static String getProductName()
125     {
126         return productName;
127     }
128 
129     /**
130      * Gets the product version.
131      *
132      @return The product version.
133      */
134     public static String getReleaseVersion()
135     {
136         return releaseVersion;
137     }
138 
139     /**
140      * Gets the source code revision.
141      *
142      @return The source code revision.
143      */
144     public static String getBuildVersion()
145     {
146         return buildVersion;
147     }
148 
149     /**
150      * Extracts all of the version information as a printable string.
151      *
152      @return All of the version information as a printable string.
153      */
154     public static String getVersionString()
155     {
156         return getProductName() " - " + getReleaseVersion() " build: " + getBuildVersion();
157     }
158 
159     /**
160      * Helper method to extract a named property from properties.
161      *
162      @param props        The properties.
163      @param propertyName The named property to extract.
164      *
165      @return The extracted property or a default value if the properties do not contain the named property.
166      *
167      * @todo A bit pointless.
168      */
169     private static String readPropertyValue(Properties props, String propertyName)
170     {
171         String retVal = (Stringprops.get(propertyName);
172         if (retVal == null)
173         {
174             retVal = DEFAULT;
175         }
176 
177         return retVal;
178     }
179 
180     /**
181      * Prints the versioning information to the console. This is extremely usefull for identifying Qpid code in the
182      * wild, where the origination of the code has been forgotten.
183      *
184      @param args Does not require any arguments.
185      */
186     public static void main(String[] args)
187     {
188         System.out.println(getVersionString());
189     }
190 }