1 /* 2 * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package org.jemmy.env; 26 27 import java.io.File; 28 import java.io.FileInputStream; 29 import java.io.IOException; 30 import java.util.ArrayList; 31 import java.util.HashMap; 32 import java.util.List; 33 import java.util.Properties; 34 import java.util.Set; 35 import org.jemmy.JemmyException; 36 import org.jemmy.action.ActionExecutor; 37 import org.jemmy.action.DefaultExecutor; 38 import org.jemmy.control.Wrap; 39 import org.jemmy.image.ImageCapturer; 40 import org.jemmy.image.ImageLoader; 41 import org.jemmy.input.CharBindingMap; 42 import org.jemmy.interfaces.ControlInterfaceFactory; 43 import org.jemmy.timing.Waiter; 44 45 /** 46 * @author shura, mrkam, erikgreijus 47 */ 48 public class Environment { 49 public static final String JEMMY_PROPERTIES_FILE_PROPERTY = "jemmy.properties"; 50 public static final String TIMEOUTS_FILE_PROPERTY = "timeouts"; 51 /** 52 * Information output for Environment class 53 */ 54 public static final String OUTPUT = Environment.class.getName() + ".OUTPUT"; 55 private final static Environment env = new Environment(null); 56 57 public static Environment getEnvironment() { 58 return env; 59 } 60 61 static { 62 env.setOutput(new TestOut(System.in, System.out, System.err)); 63 env.setExecutor(new DefaultExecutor()); 64 } 65 private HashMap<PropertyKey, Object> environment = new HashMap<PropertyKey, Object>(); 66 private Environment parent; 67 68 public Environment(Environment parent) { 69 this.parent = parent; 70 environment = new HashMap<PropertyKey, Object>(); 71 if (parent == null) { 72 loadProperties(System.getProperty(JEMMY_PROPERTIES_FILE_PROPERTY)); 73 } 74 } 75 76 public Environment() { 77 this(getEnvironment()); 78 } 79 80 public Environment getParentEnvironment() { 81 return parent; 82 } 83 84 public void setParentEnvironment(Environment parent) { 85 this.parent = parent; 86 } 87 88 public void loadProperties(String propFileName) { 89 if (propFileName == null || propFileName.length() == 0) { 90 propFileName = System.getProperty("user.home") + File.separator + ".jemmy.properties"; 91 } 92 File propFile = new File(propFileName); 93 System.out.println("Loading jemmy properties from " + propFile); 94 if (propFile.exists()) { 95 Properties props = new Properties(); 96 try { 97 props.load(new FileInputStream(propFile)); 98 } catch (IOException ex) { 99 throw new JemmyException("Unable to load properties", ex, propFileName); 100 } 101 for (String k : props.stringPropertyNames()) { 102 if (k.equals(TIMEOUTS_FILE_PROPERTY)) { 103 loadTimeouts(propFile.getParentFile(), props.getProperty(k)); 104 } else { 105 setProperty(k, props.getProperty(k)); 106 } 107 } 108 } else { 109 System.out.println("Property file " + propFile + " does not exists. Ignoring."); 110 } 111 } 112 113 private void loadTimeouts(File propDir, String file) { 114 File timeoutsFile = new File(file); 115 if (!timeoutsFile.isAbsolute()) { 116 timeoutsFile = new File(propDir.getAbsolutePath() + File.separator + file); 117 } 118 System.out.println("Loading timeouts from " + timeoutsFile.getAbsolutePath()); 119 try { 120 Properties timeouts = new Properties(); 121 timeouts.load(new FileInputStream(timeoutsFile)); 122 for (String k : timeouts.stringPropertyNames()) { 123 setTimeout(k, Long.parseLong(timeouts.getProperty(k))); 124 } 125 } catch (IOException ex) { 126 throw new JemmyException("Unable to load timeouts", ex, timeoutsFile.getAbsolutePath()); 127 } 128 } 129 130 public List<?> get(Class cls) { 131 Set<PropertyKey> all = environment.keySet(); 132 ArrayList<Object> result = new ArrayList<Object>(); 133 for (PropertyKey key : all) { 134 if (key.getCls().equals(cls)) { 135 result.add(environment.get(key)); 136 } 137 } 138 return result; 139 } 140 141 public ActionExecutor setExecutor(ActionExecutor defaultExecutor) { 142 return (ActionExecutor) setProperty(ActionExecutor.class, defaultExecutor); 143 } 144 145 public ActionExecutor getExecutor() { 146 ActionExecutor res = (ActionExecutor) getProperty(ActionExecutor.class); 147 if (res == null) { 148 String executorClassName = (String) getProperty(ActionExecutor.ACTION_EXECUTOR_PROPERTY); 149 try { 150 res = ActionExecutor.class.cast(Class.forName(executorClassName).newInstance()); 151 setExecutor(res); 152 } catch (InstantiationException ex) { 153 throw new JemmyException("Unable to instantiate executor ", ex, executorClassName); 154 } catch (IllegalAccessException ex) { 155 throw new JemmyException("Unable to instantiate executor ", ex, executorClassName); 156 } catch (ClassNotFoundException ex) { 157 throw new JemmyException("No executorclass ", ex, executorClassName); 158 } 159 } 160 return res; 161 } 162 163 public <T> T setProperty(Class<T> cls, Object ref, T obj) { 164 return setProperty(new PropertyKey<T>(cls, ref), obj); 165 } 166 167 private <T> T setPropertyIfNotSet(Class<T> cls, Object ref, T obj) { 168 return setPropertyIfNotSet(new PropertyKey<T>(cls, ref), obj); 169 } 170 171 private <T> T getProperty(Class<T> cls, Object ref) { 172 return getProperty(cls, ref, null); 173 } 174 175 @SuppressWarnings("unchecked") 176 public <T> T getProperty(Class cls, Object ref, T defaultValue) { 177 for (PropertyKey pk : environment.keySet()) { 178 if (pk.equals(new PropertyKey(cls, ref))) { 179 return (T) environment.get(pk); 180 } 181 } 182 if (getParentEnvironment() != null) { 183 return getParentEnvironment().getProperty(cls, ref, defaultValue); 184 } else { 185 return defaultValue; 186 } 187 } 188 189 /** 190 * @param <T> todo document 191 * @param cls todo document 192 * @param obj if null then property is removed 193 * @return todo document 194 */ 195 public <T> T setProperty(Class<T> cls, T obj) { 196 return setProperty(cls, null, obj); 197 } 198 199 /** 200 * @param <T> todo document 201 * @param cls todo document 202 * @param obj if null then property is removed 203 * @return todo document 204 */ 205 public <T> T setPropertyIfNotSet(Class<T> cls, T obj) { 206 return setPropertyIfNotSet(cls, null, obj); 207 } 208 209 public <T> T getProperty(Class<T> cls) { 210 return getProperty(cls, null); 211 } 212 213 /** 214 * @param name todo document 215 * @param obj if null then property is removed 216 * @return todo document 217 */ 218 public Object setProperty(String name, Object obj) { 219 return setProperty(Object.class, name, obj); 220 } 221 222 public Object setPropertyIfNotSet(String name, Object obj) { 223 return setPropertyIfNotSet(Object.class, name, obj); 224 } 225 226 public Object getProperty(String name) { 227 return getProperty(Object.class, name); 228 } 229 230 public Object getProperty(String name, Object defaultValue) { 231 return getProperty(Environment.class, name, defaultValue); 232 } 233 234 private <T> T setProperty(PropertyKey<T> key, Object value) { 235 if (value == null) { 236 return key.cls.cast(environment.remove(key)); 237 } else { 238 return key.cls.cast(environment.put(key, value)); 239 } 240 } 241 242 private <T> T setPropertyIfNotSet(PropertyKey<T> key, T value) { 243 if (getParentEnvironment() != null) { 244 T res = key.cls.cast(getParentEnvironment().getProperty(key)); 245 if (res != null) { 246 return res; 247 } 248 } 249 T res = key.cls.cast(environment.get(key)); 250 if (res == null) { 251 return key.cls.cast(environment.put(key, value)); 252 } else { 253 return res; 254 } 255 } 256 257 private Object getProperty(PropertyKey key) { 258 return environment.get(key); 259 } 260 261 public TestOut setOutput(TestOut out) { 262 return (TestOut) setProperty(TestOut.class, out); 263 } 264 265 public TestOut getOutput() { 266 return (TestOut) getProperty(TestOut.class); 267 } 268 269 /** 270 * Set some specific output. All classes which provide output should use 271 * some specific outputs. Please consult javadoc for a class in question. 272 * Use <code>null</code> to unset the property. 273 * 274 * @param outputName todo document 275 * @param out todo document 276 * @return todo document 277 */ 278 public TestOut setOutput(String outputName, TestOut out) { 279 return (TestOut) setProperty(TestOut.class, outputName, out); 280 } 281 282 /** 283 * Initializes some specific output only if it is not yet set. 284 * 285 * @param outputName todo document 286 * @param out todo document 287 * @return todo document 288 */ 289 public TestOut initOutput(String outputName, TestOut out) { 290 TestOut res = (TestOut) getProperty(TestOut.class, outputName); 291 if (res == null) { 292 return setOutput(outputName, out); 293 } else { 294 return res; 295 } 296 } 297 298 /** 299 * Get's a specific output. If nothing assigned, returns 300 * <code>getOutput()</code> 301 * 302 * @param outputName todo document 303 * @return todo document 304 */ 305 public TestOut getOutput(String outputName) { 306 TestOut res = (TestOut) getProperty(TestOut.class, outputName); 307 return (res != null) ? res : getOutput(); 308 } 309 310 public Waiter getWaiter(Timeout timeout) { 311 return getWaiter(timeout.getName()); 312 } 313 314 public Waiter getWaiter(String timeoutName) { 315 return new Waiter(getTimeout(timeoutName)); 316 } 317 318 public Timeout getTimeout(Timeout timeout) { 319 return getTimeout(timeout.getName()); 320 } 321 322 public Timeout getTimeout(String name) { 323 return (Timeout) getProperty(Timeout.class, name); 324 } 325 326 /** 327 * Sets timeout. 328 * 329 * @param timeout Timeout to set. 330 * @return replaced timeout if it was already set. 331 */ 332 public Timeout setTimeout(Timeout timeout) { 333 return (Timeout) setProperty(Timeout.class, timeout.getName(), timeout); 334 } 335 336 /** 337 * Initializes timeout only if it is not set. 338 * 339 * @param timeout Timeout to set. 340 * @return replaced timeout if it was already set. 341 */ 342 public Timeout initTimeout(Timeout timeout) { 343 if (getProperty(Timeout.class, timeout.getName()) == null) { 344 return setTimeout(timeout); 345 } 346 return getTimeout(timeout); 347 } 348 349 /** 350 * Sets new value for the timeout specified by Timeout object instance. 351 * 352 * @param timeout Timeout object instance which identifies the name of the 353 * timeout to set. 354 * @param value new value for the timout. 355 * @return replaced timeout if it was already set. 356 */ 357 public Timeout setTimeout(Timeout timeout, long value) { 358 return setTimeout(timeout.getName(), value); 359 } 360 361 /** 362 * Sets new value for the timeout. 363 * 364 * @param name Name of the timeout. 365 * @param value Value of the timeout. 366 * @return replaced timeout if it was already set. 367 */ 368 public Timeout setTimeout(String name, long value) { 369 return setTimeout(new Timeout(name, value)); 370 } 371 372 public CharBindingMap getBindingMap() { 373 return (CharBindingMap) getProperty(CharBindingMap.class); 374 } 375 376 public CharBindingMap setBindingMap(CharBindingMap map) { 377 return (CharBindingMap) setProperty(CharBindingMap.class, map); 378 } 379 380 public ImageLoader getImageLoader() { 381 ImageLoader res = (ImageLoader) getProperty(ImageLoader.class); 382 if (res == null) { 383 String loaderClass = (String) getProperty(Wrap.IMAGE_LOADER_PROPERTY); 384 if (loaderClass == null) { 385 throw new IllegalStateException("No image loader provided!"); 386 } 387 try { 388 res = ImageLoader.class.cast(Class.forName(String.class.cast(loaderClass)).newInstance()); 389 setImageLoader(res); 390 } catch (InstantiationException ex) { 391 throw new JemmyException("Unable to instantiate image loader ", ex, loaderClass); 392 } catch (IllegalAccessException ex) { 393 throw new JemmyException("Unable to instantiate image loader ", ex, loaderClass); 394 } catch (ClassNotFoundException ex) { 395 throw new JemmyException("No image loader class ", ex, loaderClass); 396 } 397 } 398 return res; 399 } 400 401 public ImageCapturer getImageCapturer() { 402 ImageCapturer res = (ImageCapturer) getProperty(ImageCapturer.class); 403 if (res == null) { 404 String capturerClass = (String) getProperty(Wrap.IMAGE_CAPTURER_PROPERTY); 405 if (capturerClass == null) { 406 throw new IllegalStateException("No image capturer provided!"); 407 } 408 try { 409 res = ImageCapturer.class.cast(Class.forName(String.class.cast(capturerClass)).newInstance()); 410 setImageCapturer(res); 411 } catch (InstantiationException ex) { 412 throw new JemmyException("Unable to instantiate image capturer ", ex, capturerClass); 413 } catch (IllegalAccessException ex) { 414 throw new JemmyException("Unable to instantiate image capturer ", ex, capturerClass); 415 } catch (ClassNotFoundException ex) { 416 throw new JemmyException("No image capturer class ", ex, capturerClass); 417 } 418 } 419 return res; 420 } 421 422 public ImageLoader setImageLoader(ImageLoader imageLoader) { 423 return (ImageLoader) setProperty(ImageLoader.class, imageLoader); 424 } 425 426 public ImageCapturer setImageCapturer(ImageCapturer imageCapturer) { 427 getOutput(OUTPUT).println("ImageCapturer set to " + imageCapturer); 428 return (ImageCapturer) setProperty(ImageCapturer.class, imageCapturer); 429 } 430 431 public ControlInterfaceFactory getInputFactory() { 432 ControlInterfaceFactory res = (ControlInterfaceFactory) getProperty(ControlInterfaceFactory.class); 433 if (res == null) { 434 String factoryClass = (String) getProperty(Wrap.INPUT_FACTORY_PROPERTY); 435 if (factoryClass != null) { 436 try { 437 res = ControlInterfaceFactory.class.cast(Class.forName(String.class.cast(factoryClass)).newInstance()); 438 setInputFactory(res); 439 } catch (InstantiationException ex) { 440 throw new JemmyException("Unable to instantiate input factory", ex, factoryClass); 441 } catch (IllegalAccessException ex) { 442 throw new JemmyException("Unable to instantiate input factory", ex, factoryClass); 443 } catch (ClassNotFoundException ex) { 444 throw new JemmyException("Unable to load input factory", ex, factoryClass); 445 } 446 } 447 } 448 return res; 449 } 450 451 public ControlInterfaceFactory setInputFactory(ControlInterfaceFactory factory) { 452 getOutput(OUTPUT).println("Input factory set to " + factory); 453 return (ControlInterfaceFactory) setProperty(ControlInterfaceFactory.class, factory); 454 } 455 456 private static class PropertyKey<TYPE> { 457 458 private Class<TYPE> cls; 459 private Object ref; 460 461 public PropertyKey(Class<TYPE> cls, Object ref) { 462 this.cls = cls; 463 this.ref = ref; 464 } 465 466 private PropertyKey(Class<TYPE> cls) { 467 this(cls, null); 468 } 469 470 public Class<TYPE> getCls() { 471 return cls; 472 } 473 474 public Object getRef() { 475 return ref; 476 } 477 478 @Override 479 public boolean equals(Object obj) { 480 if (obj == null) { 481 return false; 482 } 483 if (getClass() != obj.getClass()) { 484 return false; 485 } 486 final PropertyKey other = (PropertyKey) obj; 487 if (this.cls != other.cls && (this.cls == null || !this.cls.equals(other.cls))) { 488 return false; 489 } 490 if (this.ref != other.ref && (this.ref == null || !this.ref.equals(other.ref))) { 491 return false; 492 } 493 return true; 494 } 495 496 @Override 497 public int hashCode() { 498 int hash = 7; 499 hash = 41 * hash + (this.cls != null ? this.cls.hashCode() : 0); 500 hash = 41 * hash + (this.ref != null ? this.ref.hashCode() : 0); 501 return hash; 502 } 503 } 504 }