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