001/* 002 * Copyright (c) 2016-2017 Chris K Wensel <chris@wensel.net>. All Rights Reserved. 003 * Copyright (c) 2007-2017 Xplenty, Inc. All Rights Reserved. 004 * 005 * Project and contact information: http://www.cascading.org/ 006 * 007 * This file is part of the Cascading project. 008 * 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 */ 021 022package cascading.util; 023 024import java.io.IOException; 025import java.io.InputStream; 026import java.net.URL; 027import java.util.Collections; 028import java.util.List; 029import java.util.Properties; 030import java.util.Set; 031 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034 035/** 036 * 037 */ 038public class Version 039 { 040 private static final Logger LOG = LoggerFactory.getLogger( Version.class ); 041 042 private static boolean printedVersion = false; 043 044 public static final String CASCADING_RELEASE_MAJOR = "cascading.release.major"; 045 public static final String CASCADING_RELEASE_MINOR = "cascading.release.minor"; 046 public static final String CASCADING_BUILD_NUMBER = "cascading.build.number"; 047 public static final String CASCADING = "Cascading"; 048 049 public static Properties versionProperties; 050 051 private static synchronized Properties getVersionProperties() 052 { 053 try 054 { 055 if( versionProperties == null ) 056 { 057 versionProperties = loadVersionProperties(); 058 059 if( versionProperties.isEmpty() ) 060 LOG.warn( "unable to load version information" ); 061 } 062 } 063 catch( IOException exception ) 064 { 065 LOG.warn( "unable to load version information", exception ); 066 versionProperties = new Properties(); 067 } 068 069 return versionProperties; 070 } 071 072 public static synchronized void printBanner() 073 { 074 // only print once 075 if( printedVersion ) 076 return; 077 078 printedVersion = true; 079 080 String version = getVersionString(); 081 082 if( version != null ) 083 LOG.info( version ); 084 } 085 086 public static String getVersionString() 087 { 088 if( getVersionProperties().isEmpty() ) 089 return null; 090 091 String releaseVersion; 092 093 if( getReleaseBuild() == null || getReleaseBuild().isEmpty() ) 094 releaseVersion = String.format( "%s %s", CASCADING, getReleaseFull() ); 095 else 096 releaseVersion = String.format( "%s %s-%s", CASCADING, getReleaseFull(), getReleaseBuild() ); 097 098 return releaseVersion; 099 } 100 101 public static String getRelease() 102 { 103 if( getVersionProperties().isEmpty() ) 104 return null; 105 106 if( getReleaseBuild() == null || getReleaseBuild().isEmpty() ) 107 return String.format( "%s", getReleaseFull() ); 108 else 109 return String.format( "%s-%s", getReleaseFull(), getReleaseBuild() ); 110 } 111 112 public static String getReleaseFull() 113 { 114 String releaseFull; 115 116 if( getReleaseMinor() == null || getReleaseMinor().isEmpty() ) 117 releaseFull = getReleaseMajor(); 118 else 119 releaseFull = String.format( "%s.%s", getReleaseMajor(), getReleaseMinor() ); 120 121 return releaseFull; 122 } 123 124 public static boolean hasMajorMinorVersionInfo() 125 { 126 return !Util.isEmpty( getReleaseMinor() ) && !Util.isEmpty( getReleaseMajor() ); 127 } 128 129 public static boolean hasAllVersionInfo() 130 { 131 return !Util.isEmpty( getReleaseBuild() ) && hasMajorMinorVersionInfo(); 132 } 133 134 public static String getReleaseBuild() 135 { 136 return getVersionProperties().getProperty( CASCADING_BUILD_NUMBER ); 137 } 138 139 public static String getReleaseMinor() 140 { 141 return getVersionProperties().getProperty( CASCADING_RELEASE_MINOR ); 142 } 143 144 public static String getReleaseMajor() 145 { 146 return getVersionProperties().getProperty( CASCADING_RELEASE_MAJOR ); 147 } 148 149 public static Properties loadVersionProperties() throws IOException 150 { 151 Properties properties = new Properties(); 152 153 List<URL> resources = Collections.list( Version.class.getClassLoader().getResources( "cascading/version.properties" ) ); 154 155 if( resources.isEmpty() ) 156 return properties; 157 158 warnOnDuplicate( resources ); 159 160 InputStream stream = resources.get( 0 ).openStream(); 161 162 if( stream == null ) 163 return properties; 164 165 try 166 { 167 properties.load( stream ); 168 } 169 finally 170 { 171 stream.close(); 172 } 173 174 stream = Version.class.getClassLoader().getResourceAsStream( "cascading/build.number.properties" ); 175 176 if( stream != null ) 177 { 178 try 179 { 180 properties.load( stream ); 181 } 182 finally 183 { 184 stream.close(); 185 } 186 } 187 188 return properties; 189 } 190 191 /** 192 * A shaded jar will have multiple version.properties, e.g. 193 * <pre> 194 * file:/mnt/var/lib/hadoop/tmp/hadoop-unjar7817209360894770970/cascading/version.properties 195 * jar:file:/mnt/single-load/./load-hadoop2-tez-20150729.jar!/cascading/version.properties 196 * </pre> 197 * <p> 198 * only warn if there are duplicates within a protocol, not across since we should only be seeing file: and jar: 199 */ 200 private static void warnOnDuplicate( List<URL> resources ) 201 { 202 if( resources.size() == 1 ) 203 return; 204 205 SetMultiMap<String, String> map = new SetMultiMap<>(); 206 207 for( URL resource : resources ) 208 map.put( resource.getProtocol(), resource.toString() ); 209 210 for( String key : map.getKeys() ) 211 { 212 Set<String> values = map.getValues( key ); 213 214 if( values.size() > 1 ) 215 LOG.warn( "found multiple 'cascading/version.properties' files on the CLASSPATH. Please check your dependencies: {}, using first returned", Util.join( values, "," ) ); 216 } 217 } 218 }