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 * 47 * @author shura, mrkam, erikgreijus 48 */ 49 public class Environment { 50 51 /** 52 * 53 */ 54 public static final String JEMMY_PROPERTIES_FILE_PROPERTY = "jemmy.properties"; 55 public static final String TIMEOUTS_FILE_PROPERTY = "timeouts"; 56 /** 57 * Information output for Environment class 58 */ 59 public static final String OUTPUT = Environment.class.getName() + ".OUTPUT"; 60 private final static Environment env = new Environment(null); 61 62 /** 63 * 64 * @return 65 */ 66 public static Environment getEnvironment() { 67 return env; 68 } 69 70 static { 71 env.setOutput(new TestOut(System.in, System.out, System.err)); 72 env.setExecutor(new DefaultExecutor()); 73 } 74 private HashMap<PropertyKey, Object> environment = new HashMap<PropertyKey, Object>(); 75 private Environment parent; 76 77 /** 78 * 79 * @param parent 80 */ 81 public Environment(Environment parent) { 82 this.parent = parent; 83 environment = new HashMap<PropertyKey, Object>(); 84 if (parent == null) { 85 loadProperties(System.getProperty(JEMMY_PROPERTIES_FILE_PROPERTY)); 86 } 87 } 88 89 /** 90 * 91 */ 92 public Environment() { 93 this(getEnvironment()); 94 } 95 96 /** 97 * 98 * @return 99 */ 100 public Environment getParentEnvironment() { 101 return parent; 102 } 103 104 /** 105 * 106 * @param parent 107 */ 108 public void setParentEnvironment(Environment parent) { 109 this.parent = parent; 110 } 111 112 public void loadProperties(String propFileName) { 113 if (propFileName == null || propFileName.length() == 0) { 114 propFileName = System.getProperty("user.home") + File.separator + ".jemmy.properties"; 115 } 116 File propFile = new File(propFileName); 117 System.out.println("Loading jemmy properties from " + propFile); 118 if (propFile.exists()) { 119 Properties props = new Properties(); 120 try { 121 props.load(new FileInputStream(propFile)); 122 } catch (IOException ex) { 123 throw new JemmyException("Unable to load properties", ex, propFileName); 124 } 125 for (String k : props.stringPropertyNames()) { 126 if (k.equals(TIMEOUTS_FILE_PROPERTY)) { 127 loadTimeouts(propFile.getParentFile(), props.getProperty(k)); 128 } else { 129 setProperty(k, props.getProperty(k)); 130 } 131 } 132 } else { 133 System.out.println("Property file " + propFile + " does not exists. Ignoring."); 134 } 135 } 136 137 private void loadTimeouts(File propDir, String file) { 138 File timeoutsFile = new File(file); 139 if (!timeoutsFile.isAbsolute()) { 140 timeoutsFile = new File(propDir.getAbsolutePath() + File.separator + file); 141 } 142 System.out.println("Loading timeouts from " + timeoutsFile.getAbsolutePath()); 143 try { 144 Properties timeouts = new Properties(); 145 timeouts.load(new FileInputStream(timeoutsFile)); 146 for (String k : timeouts.stringPropertyNames()) { 147 setTimeout(k, Long.parseLong(timeouts.getProperty(k))); 148 } 149 } catch (IOException ex) { 150 throw new JemmyException("Unable to load timeouts", ex, timeoutsFile.getAbsolutePath()); 151 } 152 } 153 154 /** 155 * 156 * @param cls 157 * @return 158 */ 159 public List<?> get(Class cls) { 160 Set<PropertyKey> all = environment.keySet(); 161 ArrayList<Object> result = new ArrayList<Object>(); 162 for (PropertyKey key : all) { 163 if (key.getCls().equals(cls)) { 164 result.add(environment.get(key)); 165 } 166 } 167 return result; 168 } 169 170 /** 171 * 172 * @param defaultExecutor 173 * @return 174 */ 175 public ActionExecutor setExecutor(ActionExecutor defaultExecutor) { 176 return (ActionExecutor) setProperty(ActionExecutor.class, defaultExecutor); 177 } 178 179 /** 180 * 181 * @return 182 */ 183 public ActionExecutor getExecutor() { 184 ActionExecutor res = (ActionExecutor) getProperty(ActionExecutor.class); 185 if (res == null) { 186 String executorClassName = (String) getProperty(ActionExecutor.ACTION_EXECUTOR_PROPERTY); 187 try { 188 res = ActionExecutor.class.cast(Class.forName(executorClassName).newInstance()); 189 setExecutor(res); 190 } catch (InstantiationException ex) { 191 throw new JemmyException("Unable to instantiate executor ", ex, executorClassName); 192 } catch (IllegalAccessException ex) { 193 throw new JemmyException("Unable to instantiate executor ", ex, executorClassName); 194 } catch (ClassNotFoundException ex) { 195 throw new JemmyException("No executorclass ", ex, executorClassName); 196 } 197 } 198 return res; 199 } 200 201 public <T> T setProperty(Class<T> cls, Object ref, T obj) { 202 return setProperty(new PropertyKey<T>(cls, ref), obj); 203 } 204 205 private <T> T setPropertyIfNotSet(Class<T> cls, Object ref, T obj) { 206 return setPropertyIfNotSet(new PropertyKey<T>(cls, ref), obj); 207 } 208 209 private <T> T getProperty(Class<T> cls, Object ref) { 210 return getProperty(cls, ref, null); 211 } 212 213 @SuppressWarnings("unchecked") 214 public <T> T getProperty(Class cls, Object ref, T defaultValue) { 215 for (PropertyKey pk : environment.keySet()) { 216 if (pk.equals(new PropertyKey(cls, ref))) { 217 return (T) environment.get(pk); 218 } 219 } 220 if (getParentEnvironment() != null) { 221 return getParentEnvironment().getProperty(cls, ref, defaultValue); 222 } else { 223 return defaultValue; 224 } 225 } 226 227 /** 228 * 229 * @param <T> 230 * @param cls 231 * @param obj if null then property is removed 232 * @return 233 */ 234 public <T> T setProperty(Class<T> cls, T obj) { 235 return setProperty(cls, null, obj); 236 } 237 238 /** 239 * 240 * @param <T> 241 * @param cls 242 * @param obj if null then property is removed 243 * @return 244 */ 245 public <T> T setPropertyIfNotSet(Class<T> cls, T obj) { 246 return setPropertyIfNotSet(cls, null, obj); 247 } 248 249 /** 250 * 251 * @param <T> 252 * @param cls 253 * @return 254 */ 255 public <T> T getProperty(Class<T> cls) { 256 return getProperty(cls, null); 257 } 258 259 /** 260 * 261 * @param name 262 * @param obj if null then property is removed 263 * @return 264 */ 265 public Object setProperty(String name, Object obj) { 266 return setProperty(Object.class, name, obj); 267 } 268 269 /** 270 * 271 * @param name 272 * @param obj 273 * @return 274 */ 275 public Object setPropertyIfNotSet(String name, Object obj) { 276 return setPropertyIfNotSet(Object.class, name, obj); 277 } 278 279 /** 280 * 281 * @param name 282 * @return 283 */ 284 public Object getProperty(String name) { 285 return getProperty(Object.class, name); 286 } 287 288 /** 289 * 290 * @param name 291 * @param defaultValue 292 * @return 293 */ 294 public Object getProperty(String name, Object defaultValue) { 295 return getProperty(Environment.class, name, defaultValue); 296 } 297 298 private <T> T setProperty(PropertyKey<T> key, Object value) { 299 if (value == null) { 300 return key.cls.cast(environment.remove(key)); 301 } else { 302 return key.cls.cast(environment.put(key, value)); 303 } 304 } 305 306 private <T> T setPropertyIfNotSet(PropertyKey<T> key, T value) { 307 if (getParentEnvironment() != null) { 308 T res = key.cls.cast(getParentEnvironment().getProperty(key)); 309 if (res != null) { 310 return res; 311 } 312 } 313 T res = key.cls.cast(environment.get(key)); 314 if (res == null) { 315 return key.cls.cast(environment.put(key, value)); 316 } else { 317 return res; 318 } 319 } 320 321 private Object getProperty(PropertyKey key) { 322 return environment.get(key); 323 } 324 325 /** 326 * 327 * @param out 328 * @return 329 */ 330 public TestOut setOutput(TestOut out) { 331 return (TestOut) setProperty(TestOut.class, out); 332 } 333 334 /** 335 * 336 * @return 337 */ 338 public TestOut getOutput() { 339 return (TestOut) getProperty(TestOut.class); 340 } 341 342 /** 343 * Set some specific output. All classes which provide output should use 344 * some specific outputs. Please consult javadoc for a class in question. 345 * Use <code>null</code> to unset the property. 346 * 347 * @param outputName 348 * @param out 349 * @return 350 */ 351 public TestOut setOutput(String outputName, TestOut out) { 352 return (TestOut) setProperty(TestOut.class, outputName, out); 353 } 354 355 /** 356 * Initializes some specific output only if it is not yet set. 357 * 358 * @param outputName 359 * @param out 360 * @return 361 */ 362 public TestOut initOutput(String outputName, TestOut out) { 363 TestOut res = (TestOut) getProperty(TestOut.class, outputName); 364 if (res == null) { 365 return setOutput(outputName, out); 366 } else { 367 return res; 368 } 369 } 370 371 /** 372 * Get's a specific output. If nothing assigned, returns 373 * <code>getOutput()</code> 374 * 375 * @param outputName 376 * @return 377 */ 378 public TestOut getOutput(String outputName) { 379 TestOut res = (TestOut) getProperty(TestOut.class, outputName); 380 return (res != null) ? res : getOutput(); 381 } 382 383 /** 384 * 385 * @param timeout 386 * @return 387 */ 388 public Waiter getWaiter(Timeout timeout) { 389 return getWaiter(timeout.getName()); 390 } 391 392 /** 393 * 394 * @param timeoutName 395 * @return 396 */ 397 public Waiter getWaiter(String timeoutName) { 398 return new Waiter(getTimeout(timeoutName)); 399 } 400 401 /** 402 * 403 * @param timeout 404 * @return 405 */ 406 public Timeout getTimeout(Timeout timeout) { 407 return getTimeout(timeout.getName()); 408 } 409 410 /** 411 * 412 * @param name 413 * @return 414 */ 415 public Timeout getTimeout(String name) { 416 return (Timeout) getProperty(Timeout.class, name); 417 } 418 419 /** 420 * Sets timeout. 421 * 422 * @param timeout Timeout to set. 423 * @return replaced timeout if it was already set. 424 */ 425 public Timeout setTimeout(Timeout timeout) { 426 return (Timeout) setProperty(Timeout.class, timeout.getName(), timeout); 427 } 428 429 /** 430 * Initializes timeout only if it is not set. 431 * 432 * @param timeout Timeout to set. 433 * @return replaced timeout if it was already set. 434 */ 435 public Timeout initTimeout(Timeout timeout) { 436 if (getProperty(Timeout.class, timeout.getName()) == null) { 437 return setTimeout(timeout); 438 } 439 return getTimeout(timeout); 440 } 441 442 /** 443 * Sets new value for the timeout specified by Timeout object instance. 444 * 445 * @param timeout Timeout object instance which identifies the name of the 446 * timeout to set. 447 * @param value new value for the timout. 448 * @return replaced timeout if it was already set. 449 */ 450 public Timeout setTimeout(Timeout timeout, long value) { 451 return setTimeout(timeout.getName(), value); 452 } 453 454 /** 455 * Sets new value for the timeout. 456 * 457 * @param name Name of the timeout. 458 * @param value Value of the timeout. 459 * @return replaced timeout if it was already set. 460 */ 461 public Timeout setTimeout(String name, long value) { 462 return setTimeout(new Timeout(name, value)); 463 } 464 465 /** 466 * 467 * @return 468 */ 469 public CharBindingMap getBindingMap() { 470 return (CharBindingMap) getProperty(CharBindingMap.class); 471 } 472 473 /** 474 * 475 * @param map 476 * @return 477 */ 478 public CharBindingMap setBindingMap(CharBindingMap map) { 479 return (CharBindingMap) setProperty(CharBindingMap.class, map); 480 } 481 482 /** 483 * 484 * @return 485 */ 486 public ImageLoader getImageLoader() { 487 ImageLoader res = (ImageLoader) getProperty(ImageLoader.class); 488 if (res == null) { 489 String loaderClass = (String) getProperty(Wrap.IMAGE_LOADER_PROPERTY); 490 if (loaderClass == null) { 491 throw new IllegalStateException("No image loader provided!"); 492 } 493 try { 494 res = ImageLoader.class.cast(Class.forName(String.class.cast(loaderClass)).newInstance()); 495 setImageLoader(res); 496 } catch (InstantiationException ex) { 497 throw new JemmyException("Unable to instantiate image loader ", ex, loaderClass); 498 } catch (IllegalAccessException ex) { 499 throw new JemmyException("Unable to instantiate image loader ", ex, loaderClass); 500 } catch (ClassNotFoundException ex) { 501 throw new JemmyException("No image loader class ", ex, loaderClass); 502 } 503 } 504 return res; 505 } 506 507 /** 508 * 509 * @return 510 */ 511 public ImageCapturer getImageCapturer() { 512 ImageCapturer res = (ImageCapturer) getProperty(ImageCapturer.class); 513 if (res == null) { 514 String capturerClass = (String) getProperty(Wrap.IMAGE_CAPTURER_PROPERTY); 515 if (capturerClass == null) { 516 throw new IllegalStateException("No image capturer provided!"); 517 } 518 try { 519 res = ImageCapturer.class.cast(Class.forName(String.class.cast(capturerClass)).newInstance()); 520 setImageCapturer(res); 521 } catch (InstantiationException ex) { 522 throw new JemmyException("Unable to instantiate image capturer ", ex, capturerClass); 523 } catch (IllegalAccessException ex) { 524 throw new JemmyException("Unable to instantiate image capturer ", ex, capturerClass); 525 } catch (ClassNotFoundException ex) { 526 throw new JemmyException("No image capturer class ", ex, capturerClass); 527 } 528 } 529 return res; 530 } 531 532 /** 533 * 534 * @param imageLoader 535 * @return 536 */ 537 public ImageLoader setImageLoader(ImageLoader imageLoader) { 538 return (ImageLoader) setProperty(ImageLoader.class, imageLoader); 539 } 540 541 /** 542 * 543 * @param imageCapturer 544 * @return 545 */ 546 public ImageCapturer setImageCapturer(ImageCapturer imageCapturer) { 547 getOutput(OUTPUT).println("ImageCapturer set to " + imageCapturer); 548 return (ImageCapturer) setProperty(ImageCapturer.class, imageCapturer); 549 } 550 551 /** 552 * 553 * @return 554 */ 555 public ControlInterfaceFactory getInputFactory() { 556 ControlInterfaceFactory res = (ControlInterfaceFactory) getProperty(ControlInterfaceFactory.class); 557 if (res == null) { 558 String factoryClass = (String) getProperty(Wrap.INPUT_FACTORY_PROPERTY); 559 if (factoryClass != null) { 560 try { 561 res = ControlInterfaceFactory.class.cast(Class.forName(String.class.cast(factoryClass)).newInstance()); 562 setInputFactory(res); 563 } catch (InstantiationException ex) { 564 throw new JemmyException("Unable to instantiate input factory", ex, factoryClass); 565 } catch (IllegalAccessException ex) { 566 throw new JemmyException("Unable to instantiate input factory", ex, factoryClass); 567 } catch (ClassNotFoundException ex) { 568 throw new JemmyException("Unable to load input factory", ex, factoryClass); 569 } 570 } 571 } 572 return res; 573 } 574 575 /** 576 * 577 * @param factory 578 * @return 579 */ 580 public ControlInterfaceFactory setInputFactory(ControlInterfaceFactory factory) { 581 getOutput(OUTPUT).println("Input factory set to " + factory); 582 return (ControlInterfaceFactory) setProperty(ControlInterfaceFactory.class, factory); 583 } 584 585 private static class PropertyKey<TYPE> { 586 587 private Class<TYPE> cls; 588 private Object ref; 589 590 public PropertyKey(Class<TYPE> cls, Object ref) { 591 this.cls = cls; 592 this.ref = ref; 593 } 594 595 private PropertyKey(Class<TYPE> cls) { 596 this(cls, null); 597 } 598 599 public Class<TYPE> getCls() { 600 return cls; 601 } 602 603 public Object getRef() { 604 return ref; 605 } 606 607 @Override 608 public boolean equals(Object obj) { 609 if (obj == null) { 610 return false; 611 } 612 if (getClass() != obj.getClass()) { 613 return false; 614 } 615 final PropertyKey other = (PropertyKey) obj; 616 if (this.cls != other.cls && (this.cls == null || !this.cls.equals(other.cls))) { 617 return false; 618 } 619 if (this.ref != other.ref && (this.ref == null || !this.ref.equals(other.ref))) { 620 return false; 621 } 622 return true; 623 } 624 625 @Override 626 public int hashCode() { 627 int hash = 7; 628 hash = 41 * hash + (this.cls != null ? this.cls.hashCode() : 0); 629 hash = 41 * hash + (this.ref != null ? this.ref.hashCode() : 0); 630 return hash; 631 } 632 } 633 }