001 /* 002 * Copyright (c) 2007-2014 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.property; 022 023 import java.util.Map; 024 import java.util.Properties; 025 import java.util.Set; 026 import java.util.TreeSet; 027 028 import cascading.util.Util; 029 import org.slf4j.Logger; 030 import org.slf4j.LoggerFactory; 031 032 import static cascading.util.Util.join; 033 034 /** 035 * Class AppProps is a fluent helper for setting various application level properties that every 036 * {@link cascading.flow.Flow} may or may not be required to have set. These properties are typically passed to a Flow 037 * via a {@link cascading.flow.FlowConnector}. 038 * <p/> 039 * In prior releases, the FlowConnector was responsible for setting the "application jar" class or path. Those 040 * methods have been deprecated and moved to AppProps. 041 * <p/> 042 * New property settings that may be set in Cascading 2 are application name, version, and any tags. 043 */ 044 public class AppProps extends Props 045 { 046 private static final Logger LOG = LoggerFactory.getLogger( AppProps.class ); 047 048 public static final String APP_ID = "cascading.app.id"; 049 public static final String APP_NAME = "cascading.app.name"; 050 public static final String APP_VERSION = "cascading.app.version"; 051 public static final String APP_TAGS = "cascading.app.tags"; 052 public static final String APP_FRAMEWORKS = "cascading.app.frameworks"; 053 public static final String APP_JAR_CLASS = "cascading.app.appjar.class"; 054 public static final String APP_JAR_PATH = "cascading.app.appjar.path"; 055 056 static final String DEP_APP_JAR_CLASS = "cascading.flowconnector.appjar.class"; 057 static final String DEP_APP_JAR_PATH = "cascading.flowconnector.appjar.path"; 058 059 // need a global unique value here 060 private static String appID; 061 062 protected String name; 063 protected String version; 064 protected Set<String> tags = new TreeSet<String>(); 065 protected Class jarClass; 066 protected String jarPath; 067 protected Set<String> frameworks = new TreeSet<String>(); 068 069 public static AppProps appProps() 070 { 071 return new AppProps(); 072 } 073 074 /** 075 * Method setApplicationJarClass is used to set the application jar file. 076 * </p> 077 * All cluster executed Cascading applications 078 * need to call setApplicationJarClass(java.util.Map, Class) or 079 * {@link #setApplicationJarPath(java.util.Map, String)}, otherwise ClassNotFound exceptions are likely. 080 * 081 * @param properties of type Map 082 * @param type of type Class 083 */ 084 public static void setApplicationJarClass( Map<Object, Object> properties, Class type ) 085 { 086 if( type != null ) 087 properties.put( APP_JAR_CLASS, type ); 088 } 089 090 /** 091 * Method getApplicationJarClass returns the Class set by the setApplicationJarClass method. 092 * 093 * @param properties of type Map<Object, Object> 094 * @return Class 095 */ 096 public static Class getApplicationJarClass( Map<Object, Object> properties ) 097 { 098 Class property = PropertyUtil.getProperty( properties, DEP_APP_JAR_CLASS, (Class) null ); 099 100 if( property != null ) 101 { 102 LOG.warn( "using deprecated property: {}, use instead: {}", DEP_APP_JAR_CLASS, APP_JAR_CLASS ); 103 return property; 104 } 105 106 return PropertyUtil.getProperty( properties, APP_JAR_CLASS, (Class) null ); 107 } 108 109 /** 110 * Method setApplicationJarPath is used to set the application jar file. 111 * </p> 112 * All cluster executed Cascading applications 113 * need to call {@link #setApplicationJarClass(java.util.Map, Class)} or 114 * setApplicationJarPath(java.util.Map, String), otherwise ClassNotFound exceptions are likely. 115 * 116 * @param properties of type Map 117 * @param path of type String 118 */ 119 public static void setApplicationJarPath( Map<Object, Object> properties, String path ) 120 { 121 if( path != null ) 122 properties.put( APP_JAR_PATH, path ); 123 } 124 125 /** 126 * Method getApplicationJarPath return the path set by the setApplicationJarPath method. 127 * 128 * @param properties of type Map<Object, Object> 129 * @return String 130 */ 131 public static String getApplicationJarPath( Map<Object, Object> properties ) 132 { 133 String property = PropertyUtil.getProperty( properties, DEP_APP_JAR_PATH, (String) null ); 134 135 if( property != null ) 136 { 137 LOG.warn( "using deprecated property: {}, use instead: {}", DEP_APP_JAR_PATH, APP_JAR_PATH ); 138 return property; 139 } 140 141 return PropertyUtil.getProperty( properties, APP_JAR_PATH, (String) null ); 142 } 143 144 public static void setApplicationID( Map<Object, Object> properties ) 145 { 146 properties.put( APP_ID, getAppID() ); 147 } 148 149 public static String getApplicationID( Map<Object, Object> properties ) 150 { 151 if( properties == null ) 152 return getAppID(); 153 154 return PropertyUtil.getProperty( properties, APP_ID, getAppID() ); 155 } 156 157 private static String getAppID() 158 { 159 if( appID == null ) 160 { 161 appID = Util.createUniqueID(); 162 LOG.info( "using app.id: {}", appID ); 163 } 164 165 return appID; 166 } 167 168 /** Sets the static appID value to null. For debugging purposes. */ 169 public static void resetAppID() 170 { 171 appID = null; 172 } 173 174 public static void setApplicationName( Map<Object, Object> properties, String name ) 175 { 176 if( name != null ) 177 properties.put( APP_NAME, name ); 178 } 179 180 public static String getApplicationName( Map<Object, Object> properties ) 181 { 182 return PropertyUtil.getProperty( properties, APP_NAME, (String) null ); 183 } 184 185 public static void setApplicationVersion( Map<Object, Object> properties, String version ) 186 { 187 if( version != null ) 188 properties.put( APP_VERSION, version ); 189 } 190 191 public static String getApplicationVersion( Map<Object, Object> properties ) 192 { 193 return PropertyUtil.getProperty( properties, APP_VERSION, (String) null ); 194 } 195 196 public static void addApplicationTag( Map<Object, Object> properties, String tag ) 197 { 198 if( tag == null ) 199 return; 200 201 String tags = PropertyUtil.getProperty( properties, APP_TAGS, (String) null ); 202 203 if( tags != null ) 204 tags = join( ",", tag.trim(), tags ); 205 else 206 tags = tag; 207 208 properties.put( APP_TAGS, tags ); 209 } 210 211 public static String getApplicationTags( Map<Object, Object> properties ) 212 { 213 return PropertyUtil.getProperty( properties, APP_TAGS, (String) null ); 214 } 215 216 /** 217 * Adds a framework "name:version" string to the property set and to the System properties. 218 * <p/> 219 * Properties may be null. Duplicates are removed. 220 * 221 * @param properties may be null, additionally adds to System properties 222 * @param framework "name:version" String 223 */ 224 public static void addApplicationFramework( Map<Object, Object> properties, String framework ) 225 { 226 if( framework == null ) 227 return; 228 229 String frameworks = PropertyUtil.getProperty( properties, APP_FRAMEWORKS, System.getProperty( APP_FRAMEWORKS ) ); 230 231 if( frameworks != null ) 232 frameworks = join( ",", framework.trim(), frameworks ); 233 else 234 frameworks = framework; 235 236 frameworks = Util.unique( frameworks, "," ); 237 238 if( properties != null ) 239 properties.put( APP_FRAMEWORKS, frameworks ); 240 241 System.setProperty( APP_FRAMEWORKS, frameworks ); 242 } 243 244 public static String getApplicationFrameworks( Map<Object, Object> properties ) 245 { 246 return PropertyUtil.getProperty( properties, APP_FRAMEWORKS, System.getProperty( APP_FRAMEWORKS ) ); 247 } 248 249 public AppProps() 250 { 251 } 252 253 /** 254 * Sets the name and version of this application. 255 * 256 * @param name of type String 257 * @param version of type String 258 */ 259 public AppProps( String name, String version ) 260 { 261 this.name = name; 262 this.version = version; 263 } 264 265 public AppProps setName( String name ) 266 { 267 this.name = name; 268 269 return this; 270 } 271 272 public AppProps setVersion( String version ) 273 { 274 this.version = version; 275 276 return this; 277 } 278 279 public String getTags() 280 { 281 return join( tags, "," ); 282 } 283 284 public AppProps addTag( String tag ) 285 { 286 if( !Util.isEmpty( tag ) ) 287 tags.add( tag ); 288 289 return this; 290 } 291 292 public AppProps addTags( String... tags ) 293 { 294 for( String tag : tags ) 295 addTag( tag ); 296 297 return this; 298 } 299 300 /** 301 * Returns a list of frameworks used to build this App. 302 * 303 * @return Registered frameworks 304 */ 305 public String getFrameworks() 306 { 307 return join( frameworks, "," ); 308 } 309 310 /** 311 * Adds a new framework name to the list of frameworks used. 312 * <p/> 313 * Higher level tools should register themselves, and preferably with their version, 314 * for example {@code foo-flow-builder:1.2.3}. 315 * <p/> 316 * See {@link #addFramework(String, String)}. 317 * 318 * @param framework A String 319 * @return this AppProps instance 320 */ 321 public AppProps addFramework( String framework ) 322 { 323 if( !Util.isEmpty( framework ) ) 324 frameworks.add( framework ); 325 326 return this; 327 } 328 329 /** 330 * Adds a new framework name and its version to the list of frameworks used. 331 * <p/> 332 * Higher level tools should register themselves, and preferably with their version, 333 * for example {@code foo-flow-builder:1.2.3}. 334 * 335 * @param framework A String 336 * @return this AppProps instance 337 */ 338 public AppProps addFramework( String framework, String version ) 339 { 340 if( !Util.isEmpty( framework ) && !Util.isEmpty( version ) ) 341 frameworks.add( framework + ":" + version ); 342 343 if( !Util.isEmpty( framework ) ) 344 frameworks.add( framework ); 345 346 return this; 347 } 348 349 /** 350 * Adds new framework names to the list of frameworks used. 351 * <p/> 352 * Higher level tools should register themselves, and preferably with their version, 353 * for example {@code foo-flow-builder:1.2.3}. 354 * 355 * @param frameworks Strings 356 * @return this AppProps instance 357 */ 358 public AppProps addFrameworks( String... frameworks ) 359 { 360 for( String framework : frameworks ) 361 addFramework( framework ); 362 363 return this; 364 } 365 366 /** 367 * Method setJarClass is used to set the application jar file. 368 * </p> 369 * All cluster executed Cascading applications 370 * need to call setApplicationJarClass(java.util.Map, Class) or 371 * {@link #setApplicationJarPath(java.util.Map, String)}, otherwise ClassNotFound exceptions are likely. 372 * 373 * @param jarClass of type Class 374 */ 375 public AppProps setJarClass( Class jarClass ) 376 { 377 this.jarClass = jarClass; 378 379 return this; 380 } 381 382 /** 383 * Method setJarPath is used to set the application jar file. 384 * </p> 385 * All cluster executed Cascading applications 386 * need to call {@link #setJarClass(Class)} or 387 * setJarPath(java.util.Map, String), otherwise ClassNotFound exceptions are likely. 388 * 389 * @param jarPath of type String 390 */ 391 public AppProps setJarPath( String jarPath ) 392 { 393 this.jarPath = jarPath; 394 395 return this; 396 } 397 398 @Override 399 protected void addPropertiesTo( Properties properties ) 400 { 401 setApplicationID( properties ); 402 setApplicationName( properties, name ); 403 setApplicationVersion( properties, version ); 404 addApplicationTag( properties, getTags() ); 405 addApplicationFramework( properties, getFrameworks() ); 406 setApplicationJarClass( properties, jarClass ); 407 setApplicationJarPath( properties, jarPath ); 408 } 409 }