001 /* 002 * Copyright (c) 2007-2015 Concurrent, 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 021 package cascading.util; 022 023 import java.io.IOException; 024 import java.io.InputStream; 025 import java.net.URL; 026 import java.util.Collections; 027 import java.util.HashMap; 028 import java.util.HashSet; 029 import java.util.List; 030 import java.util.Map; 031 import java.util.Properties; 032 import java.util.Set; 033 034 import org.slf4j.Logger; 035 import org.slf4j.LoggerFactory; 036 037 /** 038 * 039 */ 040 public class Version 041 { 042 private static final Logger LOG = LoggerFactory.getLogger( Version.class ); 043 044 private static boolean printedVersion = false; 045 046 public static final String CASCADING_RELEASE_MAJOR = "cascading.release.major"; 047 public static final String CASCADING_RELEASE_MINOR = "cascading.release.minor"; 048 public static final String CASCADING_BUILD_NUMBER = "cascading.build.number"; 049 public static final String CASCADING = "Cascading"; 050 051 public static Properties versionProperties; 052 053 private static synchronized Properties getVersionProperties() 054 { 055 try 056 { 057 if( versionProperties == null ) 058 { 059 versionProperties = loadVersionProperties(); 060 061 if( versionProperties.isEmpty() ) 062 LOG.warn( "unable to load version information" ); 063 } 064 } 065 catch( IOException exception ) 066 { 067 LOG.warn( "unable to load version information", exception ); 068 versionProperties = new Properties(); 069 } 070 071 return versionProperties; 072 } 073 074 public static synchronized void printBanner() 075 { 076 // only print once 077 if( printedVersion ) 078 return; 079 080 printedVersion = true; 081 082 String version = getVersionString(); 083 084 if( version != null ) 085 LOG.info( version ); 086 } 087 088 public static String getVersionString() 089 { 090 if( getVersionProperties().isEmpty() ) 091 return null; 092 093 String releaseVersion; 094 095 if( getReleaseBuild() == null || getReleaseBuild().isEmpty() ) 096 releaseVersion = String.format( "Concurrent, Inc - %s %s", CASCADING, getReleaseFull() ); 097 else 098 releaseVersion = String.format( "Concurrent, Inc - %s %s-%s", CASCADING, getReleaseFull(), getReleaseBuild() ); 099 100 return releaseVersion; 101 } 102 103 public static String getRelease() 104 { 105 if( getVersionProperties().isEmpty() ) 106 return null; 107 108 if( getReleaseBuild() == null || getReleaseBuild().isEmpty() ) 109 return String.format( "%s", getReleaseFull() ); 110 else 111 return String.format( "%s-%s", getReleaseFull(), getReleaseBuild() ); 112 } 113 114 public static String getReleaseFull() 115 { 116 String releaseFull; 117 118 if( getReleaseMinor() == null || getReleaseMinor().isEmpty() ) 119 releaseFull = getReleaseMajor(); 120 else 121 releaseFull = String.format( "%s.%s", getReleaseMajor(), getReleaseMinor() ); 122 123 return releaseFull; 124 } 125 126 public static boolean hasMajorMinorVersionInfo() 127 { 128 return !Util.isEmpty( getReleaseMinor() ) && !Util.isEmpty( getReleaseMajor() ); 129 } 130 131 public static boolean hasAllVersionInfo() 132 { 133 return !Util.isEmpty( getReleaseBuild() ) && hasMajorMinorVersionInfo(); 134 } 135 136 public static String getReleaseBuild() 137 { 138 return getVersionProperties().getProperty( CASCADING_BUILD_NUMBER ); 139 } 140 141 public static String getReleaseMinor() 142 { 143 return getVersionProperties().getProperty( CASCADING_RELEASE_MINOR ); 144 } 145 146 public static String getReleaseMajor() 147 { 148 return getVersionProperties().getProperty( CASCADING_RELEASE_MAJOR ); 149 } 150 151 public static Properties loadVersionProperties() throws IOException 152 { 153 Properties properties = new Properties(); 154 155 List<URL> resources = Collections.list( Version.class.getClassLoader().getResources( "cascading/version.properties" ) ); 156 157 if( resources.isEmpty() ) 158 return properties; 159 160 warnOnDuplicate( resources ); 161 162 InputStream stream = resources.get( 0 ).openStream(); 163 164 if( stream == null ) 165 return properties; 166 167 try 168 { 169 properties.load( stream ); 170 } 171 finally 172 { 173 stream.close(); 174 } 175 176 stream = Version.class.getClassLoader().getResourceAsStream( "cascading/build.number.properties" ); 177 178 if( stream != null ) 179 { 180 try 181 { 182 properties.load( stream ); 183 } 184 finally 185 { 186 stream.close(); 187 } 188 } 189 190 return properties; 191 } 192 193 /** 194 * A shaded jar will have multiple version.properties, e.g. 195 * <pre> 196 * file:/mnt/var/lib/hadoop/tmp/hadoop-unjar7817209360894770970/cascading/version.properties 197 * jar:file:/mnt/single-load/./load-hadoop2-tez-20150729.jar!/cascading/version.properties 198 * </pre> 199 * <p/> 200 * only warn if there are duplicates within a protocol, not across since we should only be seeing file: and jar: 201 */ 202 private static void warnOnDuplicate( List<URL> resources ) 203 { 204 if( resources.size() == 1 ) 205 return; 206 207 Map<String, Set<String>> map = new HashMap<String, Set<String>>(); 208 209 for( URL resource : resources ) 210 { 211 String protocol = resource.getProtocol(); 212 213 if( !map.containsKey( protocol ) ) 214 map.put( protocol, new HashSet<String>() ); 215 216 map.get( protocol ).add( resource.toString() ); 217 } 218 219 for( String key : map.keySet() ) 220 { 221 Set<String> values = map.get( key ); 222 223 if( values.size() > 1 ) 224 LOG.warn( "found multiple 'cascading/version.properties' files on the CLASSPATH. Please check your dependencies: {}, using first returned", Util.join( values, "," ) ); 225 } 226 } 227 }