1 /* ServerAccess.java 2 Copyright (C) 2011, 2012 Red Hat, Inc. 3 4 This file is part of IcedTea. 5 6 IcedTea is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, version 2. 9 10 IcedTea is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with IcedTea; see the file COPYING. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 02110-1301 USA. 19 20 Linking this library statically or dynamically with other modules is 21 making a combined work based on this library. Thus, the terms and 22 conditions of the GNU General Public License cover the whole 23 combination. 24 25 As a special exception, the copyright holders of this library give you 26 permission to link this library with independent modules to produce an 27 executable, regardless of the license terms of these independent 28 modules, and to copy and distribute the resulting executable under 29 terms of your choice, provided that you also meet, for each linked 30 independent module, the terms and conditions of the license of that 31 module. An independent module is a module which is not derived from 32 or based on this library. If you modify this library, you may extend 33 this exception to your version of the library, but you are not 34 obligated to do so. If you do not wish to do so, delete this 35 exception statement from your version. 36 */ 37 package net.sourceforge.jnlp; 38 39 import java.io.ByteArrayOutputStream; 40 import java.io.File; 41 import java.io.IOException; 42 import java.io.InputStream; 43 import java.net.HttpURLConnection; 44 import java.net.MalformedURLException; 45 import java.net.ServerSocket; 46 import java.net.URL; 47 import java.net.URLConnection; 48 import java.util.ArrayList; 49 import java.util.Arrays; 50 import java.util.List; 51 import net.sourceforge.jnlp.browsertesting.Browser; 52 import net.sourceforge.jnlp.browsertesting.BrowserFactory; 53 import net.sourceforge.jnlp.browsertesting.Browsers; 54 import net.sourceforge.jnlp.closinglisteners.AutoErrorClosingListener; 55 import net.sourceforge.jnlp.closinglisteners.AutoOkClosingListener; 56 import net.sourceforge.jnlp.util.FileUtils; 57 import net.sourceforge.jnlp.util.logging.OutputController; 58 59 /** 60 * 61 * This class provides access to virtual server and stuff around. 62 * It can find unoccupied port, start server, provides its singleton instantiation, launch parallel instantiations, 63 * read location of installed (tested javaws) see javaws.build.bin java property, 64 * location of server www root on file system (see test.server.dir java property), 65 * stubs for launching javaws and for locating resources and read resources. 66 * 67 * It can also execute processes with timeout (@see PROCESS_TIMEOUT) (used during launching javaws) 68 * Some protected apis are exported because public classes in this package are put to be tested by makefile. 69 * 70 * There are included test cases which show some basic usages. 71 * 72 * 73 */ 74 public class ServerAccess { 75 76 public static enum AutoClose { 77 78 CLOSE_ON_EXCEPTION, CLOSE_ON_CORRECT_END, CLOSE_ON_BOTH 79 } 80 81 public static final long NANO_TIME_DELIMITER=1000000l; 82 /** 83 * java property which value containing path to default (makefile by) directory with deployed resources 84 */ 85 public static final String TEST_SERVER_DIR = "test.server.dir"; 86 /** 87 * java property which value containing path to installed (makefile by) javaws binary 88 */ 89 public static final String JAVAWS_BUILD_BIN = "javaws.build.bin"; 90 /** property to set the different then default browser 91 */ 92 public static final String USED_BROWSERS = "used.browsers"; 93 public static final String DEFAULT_LOCALHOST_NAME = "localhost"; 94 /** 95 * server instance singleton 96 */ 97 private static ServerLauncher server; 98 /** 99 * inner version of engine 100 */ 101 private static final String version = "5"; 102 /** 103 * timeout to read 'remote' resources 104 * This can be changed in runtime, but will affect all following tasks 105 */ 106 public static int READ_TIMEOUT = 1000; 107 /** 108 * timeout in ms to let process to finish, before assassin will kill it. 109 * This can be changed in runtime, but will affect all following tasks 110 */ 111 public static long PROCESS_TIMEOUT = 10 * 1000;//ms 112 /** 113 * this flag is indicating whether output of executeProcess should be logged. By default true. 114 */ 115 public static boolean PROCESS_LOG = true; 116 public static boolean LOGS_REPRINT = false; 117 118 private Browser currentBrowser; 119 public static final String UNSET_BROWSER="unset_browser"; 120 121 /** 122 * main method of this class prints out random free port 123 * or runs server 124 * param "port" prints out the port 125 * nothing or number will run server on random(or on number specified) 126 * port in -Dtest.server.dir 127 * @param args params from commandline. recognized params are port and randomport 128 * @throws java.lang.Exception if anything happens 129 */ main(String[] args)130 public static void main(String[] args) throws Exception { 131 if (args.length > 0 && args[0].equalsIgnoreCase("port")) { 132 int i = findFreePort(); 133 System.out.println(i); 134 System.exit(0); 135 } else { 136 int port = 44321; 137 if (args.length > 0 && args[0].equalsIgnoreCase("randomport")) { 138 port = findFreePort(); 139 } else if (args.length > 0) { 140 port = new Integer(args[0]); 141 } 142 getIndependentInstance(port); 143 while (true) { 144 Thread.sleep(1000); 145 } 146 147 } 148 } 149 150 /** 151 * utility method to find random free port 152 * 153 * @return - found random free port 154 * @throws IOException - if socket can't be opened or no free port exists 155 */ findFreePort()156 public static int findFreePort() 157 throws IOException { 158 ServerSocket findPortTestingSocket = new ServerSocket(0); 159 int port = findPortTestingSocket.getLocalPort(); 160 findPortTestingSocket.close(); 161 return port; 162 } 163 public static final String HEADLES_OPTION=OptionsDefinitions.OPTIONS.HEADLESS.option; 164 public static final String VERBOSE_OPTION=OptionsDefinitions.OPTIONS.VERBOSE.option; 165 166 /** 167 * we would like to have an singleton instance ASAP 168 */ ServerAccess()169 public ServerAccess() { 170 171 getInstance(); 172 173 174 } 175 176 /** 177 * 178 * @return cached instance. If none, then creates new 179 */ getInstance()180 public static ServerLauncher getInstance() { 181 if (server == null) { 182 server = getIndependentInstance(); 183 } 184 return server; 185 } 186 187 /** 188 * 189 * @return new not cached iserver instance on random port, 190 * useful for testing application loading from different url then base 191 */ getIndependentInstance()192 public static ServerLauncher getIndependentInstance() { 193 return getIndependentInstance(true); 194 } getIndependentInstance(boolean daemon)195 public static ServerLauncher getIndependentInstance(boolean daemon) { 196 String dir = (System.getProperty(TEST_SERVER_DIR)); 197 try{ 198 return getIndependentInstance(dir, findFreePort(),daemon); 199 }catch (Exception ex){ 200 throw new RuntimeException(ex); 201 } 202 } 203 204 205 /** 206 * 207 * @param port specific port on which this server is accepting requests 208 * @return new not cached iserver instance on random port, 209 * useful for testing application loading from different url then base 210 */ 211 getIndependentInstance(int port)212 public static ServerLauncher getIndependentInstance(int port) { 213 return getIndependentInstance(port, true); 214 } getIndependentInstance(int port,boolean daemon)215 public static ServerLauncher getIndependentInstance(int port,boolean daemon) { 216 String dir = (System.getProperty(TEST_SERVER_DIR)); 217 return getIndependentInstance(dir,port,daemon); 218 } 219 220 /** 221 * 222 * @param dir directory from which server returns resources 223 * @param port specific port on which this server is accepting requests 224 * @return new not cached iserver instance on random port upon custom www root directory, 225 * useful for testing application loading from different url then base 226 */ 227 getIndependentInstance(String dir, int port)228 public static ServerLauncher getIndependentInstance(String dir, int port) { 229 return getIndependentInstance(dir, port, true); 230 } 231 getIndependentInstance(String dir)232 public static ServerLauncher getIndependentInstance(String dir) throws IOException { 233 return getIndependentInstance(dir, findFreePort(), true); 234 } 235 getIndependentInstanceOnTmpDir()236 public static ServerLauncher getIndependentInstanceOnTmpDir() throws IOException { 237 File f = File.createTempFile("itwReproducers_", "_anotherDeployDir"); 238 f.delete(); 239 f.mkdir(); 240 f.deleteOnExit(); 241 return getIndependentInstance(f.getAbsolutePath(), findFreePort(), true); 242 } 243 getIndependentInstance(String dir, int port, boolean daemon)244 public static ServerLauncher getIndependentInstance(String dir, int port, boolean daemon) { 245 246 247 if (dir == null || dir.trim().length() == 0 || !new File(dir).exists() || !new File(dir).isDirectory()) { 248 throw new RuntimeException("test.server.dir property must be set to valid directory!"); 249 } 250 try { 251 ServerLauncher lServerLuncher = new ServerLauncher(port, new File(dir)); 252 Thread r=new Thread(lServerLuncher); 253 r.setDaemon(daemon); 254 r.start(); 255 return lServerLuncher; 256 } catch (Exception ex) { 257 throw new RuntimeException(ex); 258 } 259 260 } 261 262 /** 263 * 264 * @return - value passed inside as javaws binary location. See JAVAWS_BUILD_BIN 265 */ getJavawsLocation()266 public String getJavawsLocation() { 267 return System.getProperty(JAVAWS_BUILD_BIN); 268 } 269 270 /** 271 * 272 * @return - bianry from where to lunch current browser 273 */ getBrowserLocation()274 public String getBrowserLocation() { 275 if (this.currentBrowser==null) return UNSET_BROWSER; 276 return this.currentBrowser.getBin(); 277 } 278 getBrowserParams()279 public List<String> getBrowserParams() { 280 if (this.currentBrowser==null) return null; 281 List<String> l1=this.currentBrowser.getComaptibilitySwitches(); 282 List<String> l2=this.currentBrowser.getDefaultSwitches(); 283 List<String> l= new ArrayList<>(); 284 if (l1!=null)l.addAll(l1); 285 if (l2!=null)l.addAll(l2); 286 return l; 287 288 } 289 getCurrentBrowsers()290 public Browsers getCurrentBrowsers() { 291 if (currentBrowser==null) return null; 292 return currentBrowser.getID(); 293 } getCurrentBrowser()294 public Browser getCurrentBrowser() { 295 return currentBrowser; 296 } 297 setCurrentBrowser(Browsers currentBrowser)298 public void setCurrentBrowser(Browsers currentBrowser) { 299 this.currentBrowser = BrowserFactory.getFactory().getBrowser(currentBrowser); 300 if (this.currentBrowser == null) { 301 LoggingBottleneck.getDefaultLoggingBottleneck().setLoggedBrowser(UNSET_BROWSER); 302 } else { 303 LoggingBottleneck.getDefaultLoggingBottleneck().setLoggedBrowser(this.currentBrowser.getID().toString()); 304 } 305 } 306 setCurrentBrowser(Browser currentBrowser)307 public void setCurrentBrowser(Browser currentBrowser) { 308 this.currentBrowser = currentBrowser; 309 if (this.currentBrowser == null) { 310 LoggingBottleneck.getDefaultLoggingBottleneck().setLoggedBrowser(UNSET_BROWSER); 311 } else { 312 LoggingBottleneck.getDefaultLoggingBottleneck().setLoggedBrowser(this.currentBrowser.getID().toString()); 313 } 314 } 315 316 317 318 /** 319 * 320 * @return - value passed inside as javaws binary location as file. See JAVAWS_BUILD_BIN 321 */ getJavawsFile()322 public File getJavawsFile() { 323 return new File(System.getProperty(JAVAWS_BUILD_BIN)); 324 } 325 326 /** 327 * 328 * @return port on which is running cached server. If non singleton instance is running, new is created. 329 */ getPort()330 public int getPort() { 331 if (server == null) { 332 getInstance(); 333 } 334 //if (!server.isRunning()) throw new RuntimeException("Server mysteriously died"); 335 return server.getPort(); 336 337 } 338 339 /** 340 * 341 * @return directory upon which is running cached server. If non singleton instance is running, new is created. 342 */ getDir()343 public File getDir() { 344 if (server == null) { 345 getInstance(); 346 } 347 // if (!server.isRunning()) throw new RuntimeException("Server mysteriously died"); 348 return server.getDir(); 349 } 350 351 /** 352 * 353 * @throws java.net.MalformedURLException if url for this resource can not be constructed 354 * @return complete url for this resource on this server 355 * @param resource relative path pointing to server resource. If non singleton instance is running, new is created. 356 */ getUrl(String resource)357 public URL getUrl(String resource) throws MalformedURLException { 358 if (server == null) { 359 getInstance(); 360 } 361 //if (!server.isRunning()) throw new RuntimeException("Server mysteriously died"); 362 return server.getUrl(resource); 363 } 364 365 /** 366 * 367 * @return url pointing to cached server . If non singleton instance is running, new is created. 368 * @throws java.net.MalformedURLException 369 */ getUrl()370 public URL getUrl() throws MalformedURLException { 371 return getUrl(""); 372 373 } 374 375 /** 376 * 377 * @return whether cached server is alive. If non singleton instance is running, new is created. 378 */ isRunning()379 public boolean isRunning() { 380 if (server == null) { 381 getInstance(); 382 } 383 //if (!server.isRunning()) throw new RuntimeException("Server mysteriously died"); 384 return server.isRunning(); 385 386 } 387 388 /** 389 * Return resource from cached server 390 * 391 * @param resource to be located on cached server 392 * @return individual bytes of resource 393 * @throws IOException if connection can't be established or resource does not exist 394 */ getResourceAsBytes(String resource)395 public ByteArrayOutputStream getResourceAsBytes(String resource) throws IOException { 396 return getResourceAsBytes(getUrl(resource)); 397 } 398 399 /** 400 * Return resource from cached server 401 * 402 * @param resource to be located on cached server 403 * @return string constructed from resource 404 * @throws IOException if connection can't be established or resource does not exist 405 */ getResourceAsString(String resource)406 public String getResourceAsString(String resource) throws IOException { 407 return getResourceAsString(getUrl(resource)); 408 } 409 410 /** 411 * utility method which can read bytes of any stream 412 * 413 * @param is stream to be read 414 * @return individual bytes of resource 415 * @throws IOException if connection can't be established or resource does not exist 416 */ getBytesFromStream(InputStream is)417 public static ByteArrayOutputStream getBytesFromStream(InputStream is) throws IOException { 418 ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 419 int nRead; 420 byte[] data = new byte[16384]; 421 while ((nRead = is.read(data, 0, data.length)) != -1) { 422 buffer.write(data, 0, nRead); 423 } 424 buffer.flush(); 425 return buffer; 426 } 427 428 /** 429 * utility method which can read from any stream as one long String 430 * 431 * @param is stream to be read 432 * @param encoding encoding of this stream 433 * @return stream as string 434 * @throws IOException if connection can't be established or resource does not exist 435 */ getContentOfStream(InputStream is, String encoding)436 public static String getContentOfStream(InputStream is, String encoding) throws IOException { 437 return FileUtils.getContentOfStream(is, encoding); 438 } 439 440 /** 441 * utility method which can read from any stream as one long String 442 * 443 * @param is input stream to read from 444 * @return stream as string 445 * @throws IOException if connection can't be established or resource does not exist 446 */ getContentOfStream(InputStream is)447 public static String getContentOfStream(InputStream is) throws IOException { 448 return FileUtils.getContentOfStream(is); 449 } 450 451 /** 452 * utility method which can read bytes of resource from any url 453 * 454 * @param u full url to read from 455 * @return individual bytes of resource 456 * @throws IOException if connection can't be established or resource does not exist 457 */ getResourceAsBytes(URL u)458 public static ByteArrayOutputStream getResourceAsBytes(URL u) throws IOException { 459 URLConnection connection = null; 460 try { 461 connection = u.openConnection(); 462 if (connection instanceof HttpURLConnection) { 463 ((HttpURLConnection) connection).setRequestMethod("GET"); 464 } 465 connection.setDoOutput(true); 466 connection.setReadTimeout(READ_TIMEOUT); 467 connection.connect(); 468 return getBytesFromStream(connection.getInputStream()); 469 } finally { 470 if (connection != null && connection instanceof HttpURLConnection) { 471 ((HttpURLConnection) connection).disconnect(); 472 } 473 } 474 475 } 476 477 /** 478 * utility method which can read string of resource from any url 479 * 480 * @param u full url to read from 481 * @return resource as string 482 * @throws IOException if connection can't be established or resource does 483 * not exist 484 */ getResourceAsString(URL u)485 public static String getResourceAsString(URL u) throws IOException { 486 URLConnection connection = null; 487 try { 488 connection = (HttpURLConnection) u.openConnection(); 489 if (connection instanceof HttpURLConnection) { 490 ((HttpURLConnection) connection).setRequestMethod("GET"); 491 } 492 connection.setDoOutput(true); 493 connection.setReadTimeout(READ_TIMEOUT); 494 connection.connect(); 495 return getContentOfStream(connection.getInputStream()); 496 } finally { 497 if (connection != null && connection instanceof HttpURLConnection) { 498 ((HttpURLConnection) connection).disconnect(); 499 } 500 } 501 } 502 503 /** 504 * helping dummy method to save String as file in UTF-8 encoding. 505 * 506 * @param content which will be saved as it is saved in this String 507 * @param f file to be saved. No warnings provided 508 * @throws IOException 509 */ saveFile(String content, File f)510 public static void saveFile(String content, File f) throws IOException { 511 FileUtils.saveFile(content, f); 512 } 513 514 /** 515 * helping dummy method to save String as file in specified encoding/. 516 * 517 * @param content which will be saved as it is saved in this String 518 * @param f file to be saved. No warnings provided 519 * @param encoding of output byte representation 520 * @throws IOException 521 */ saveFile(String content, File f,String encoding)522 public static void saveFile(String content, File f,String encoding) throws IOException { 523 FileUtils.saveFile(content, f, encoding); 524 } 525 526 /** 527 * wrapping method to executeProcess (eg: javaws -headless http://localhost:port/resource) 528 * will execute default javaws (@see JAVAWS_BUILD_BIN) upon default url upon cached server (@see SERVER_NAME @see getPort(), @see getInstance()) 529 * with parameter -headless (no gui, no asking) 530 * @param resource name of resource 531 * @return result what left after running this process 532 * @throws Exception 533 */ executeJavawsHeadless(String resource)534 public ProcessResult executeJavawsHeadless(String resource) throws Exception { 535 return executeJavawsHeadless(null, resource); 536 } executeJavawsHeadless(String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl)537 public ProcessResult executeJavawsHeadless(String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl) throws Exception { 538 return executeJavawsHeadless(null, resource,stdoutl,stderrl,null); 539 } executeJavawsClearCache()540 public ProcessResult executeJavawsClearCache() throws Exception { 541 return executeProcess(Arrays.asList(new String[]{getJavawsLocation(), OptionsDefinitions.OPTIONS.CLEARCACHE.option, ServerAccess.HEADLES_OPTION})); 542 } 543 544 /** 545 * wrapping method to executeProcess (eg: javaws arg arg -headless http://localhost:port/resource) 546 * will execute default javaws (@see JAVAWS_BUILD_BIN) upon default url upon cached server (@see SERVER_NAME @see getPort(), @see getInstance()) 547 * with parameter -headless (no gui, no asking) 548 * @param resource name of resource 549 * @param otherargs other arguments to be added to headless one 550 * @return result what left after running this process 551 * @throws Exception 552 */ executeJavawsHeadless(List<String> otherargs, String resource)553 public ProcessResult executeJavawsHeadless(List<String> otherargs, String resource) throws Exception { 554 return executeJavawsHeadless(otherargs, resource,null,null,null); 555 } executeJavawsHeadless(List<String> otherargs, String resource, String[] vars)556 public ProcessResult executeJavawsHeadless(List<String> otherargs, String resource, String[] vars) throws Exception { 557 return executeJavawsHeadless(otherargs, resource,null,null,vars); 558 } 559 executeJavawsHeadless(List<String> otherargs, String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl,String[] vars)560 public ProcessResult executeJavawsHeadless(List<String> otherargs, String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl,String[] vars) throws Exception { 561 if (otherargs == null) { 562 otherargs = new ArrayList<>(1); 563 } 564 List<String> headlesList = new ArrayList<>(otherargs); 565 headlesList.add(HEADLES_OPTION); 566 return executeJavaws(headlesList, resource,stdoutl,stderrl,vars); 567 } 568 569 570 /** 571 * wrapping method to executeProcess (eg: javaws http://localhost:port/resource) 572 * will execute default javaws (@see JAVAWS_BUILD_BIN) upon default url upon cached server (@see SERVER_NAME @see getPort(), @see getInstance()) 573 * @param resource name of resource 574 * @return result what left after running this process 575 * @throws Exception 576 */ executeJavaws(String resource)577 public ProcessResult executeJavaws(String resource) throws Exception { 578 return executeJavaws(null, resource); 579 } executeJavaws(String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl)580 public ProcessResult executeJavaws(String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl) throws Exception { 581 return executeJavaws(null, resource,stdoutl,stderrl); 582 } 583 executeBrowser(String string, AutoClose autoClose)584 public net.sourceforge.jnlp.ProcessResult executeBrowser(String string, AutoClose autoClose) throws Exception { 585 ClosingListener errClosing = null; 586 ClosingListener outClosing = null; 587 if (autoClose == AutoClose.CLOSE_ON_BOTH || autoClose == AutoClose.CLOSE_ON_EXCEPTION){ 588 errClosing=new AutoErrorClosingListener(); 589 } 590 if (autoClose == AutoClose.CLOSE_ON_BOTH || autoClose == AutoClose.CLOSE_ON_CORRECT_END){ 591 outClosing=new AutoOkClosingListener(); 592 } 593 return executeBrowser(string, outClosing, errClosing); 594 } 595 596 /** 597 * 598 * @param resource relative resource to be opened in browser for current server instance. 599 * @return result of browser run 600 * 601 */ executeBrowser(String resource)602 public ProcessResult executeBrowser(String resource) throws Exception { 603 return executeBrowser(getBrowserParams(), resource); 604 } 605 606 /** 607 * 608 * @param resource relative resource to be opened in browser for current server instance. 609 * @param stdoutl listener for stdout 610 * @param stderrl listener for stderr 611 * @return result of browser run 612 * 613 */ executeBrowser(String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl)614 public ProcessResult executeBrowser(String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl) throws Exception { 615 return executeBrowser(getBrowserParams(), resource, stdoutl, stderrl); 616 } 617 618 /** 619 * 620 * @param resource elative resource to be opened in browser for current server instance. 621 * @param stdoutl listeners for stdout 622 * @param stderrl listeners for stderr 623 * @return result of browser run 624 * 625 */ executeBrowser(String resource, List<ContentReaderListener> stdoutl, List<ContentReaderListener> stderrl)626 public ProcessResult executeBrowser(String resource, List<ContentReaderListener> stdoutl, List<ContentReaderListener> stderrl) throws Exception { 627 return executeBrowser(getBrowserParams(), resource, stdoutl, stderrl); 628 } 629 630 /** 631 * wrapping method to executeProcess (eg: javaws arg arg http://localhost:port/resource) 632 * will execute default javaws (@see JAVAWS_BUILD_BIN) upon default url upon cached server (@see SERVER_NAME @see getPort(), @see getInstance())) 633 * @param resource name of resource 634 * @param otherargs other arguments to be added 635 * @return result what left after running this process 636 * @throws Exception 637 */ executeJavaws(List<String> otherargs, String resource)638 public ProcessResult executeJavaws(List<String> otherargs, String resource) throws Exception { 639 return executeProcessUponURL(getJavawsLocation(), otherargs, getUrlUponThisInstance(resource)); 640 } executeJavaws(List<String> otherargs, String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl)641 public ProcessResult executeJavaws(List<String> otherargs, String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl) throws Exception { 642 return executeProcessUponURL(getJavawsLocation(), otherargs, getUrlUponThisInstance(resource),stdoutl,stderrl); 643 } executeJavaws(List<String> otherargs, String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl,String[] vars)644 public ProcessResult executeJavaws(List<String> otherargs, String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl,String[] vars) throws Exception { 645 return executeProcessUponURL(getJavawsLocation(), otherargs, getUrlUponThisInstance(resource),stdoutl,stderrl,vars); 646 } 647 executeBrowser(List<String> otherargs, String resource)648 public ProcessResult executeBrowser(List<String> otherargs, String resource) throws Exception { 649 return executeBrowser(otherargs, getUrlUponThisInstance(resource)); 650 } 651 executeBrowser(List<String> otherargs, URL url)652 public ProcessResult executeBrowser(List<String> otherargs, URL url) throws Exception { 653 ProcessWrapper rpw = new ProcessWrapper(getBrowserLocation(), otherargs, url); 654 rpw.setReactingProcess(getCurrentBrowser());//current browser may be null, but it does not metter 655 return rpw.execute(); 656 } 657 executeBrowser(List<String> otherargs, String resource, ContentReaderListener stdoutl, ContentReaderListener stderrl)658 public ProcessResult executeBrowser(List<String> otherargs, String resource, ContentReaderListener stdoutl, ContentReaderListener stderrl) throws Exception { 659 ProcessWrapper rpw = new ProcessWrapper(getBrowserLocation(), otherargs, getUrlUponThisInstance(resource), stdoutl, stderrl, null); 660 rpw.setReactingProcess(getCurrentBrowser());//current browser may be null, but it does not metter 661 return rpw.execute(); 662 } 663 executeBrowser(List<String> otherargs, URL url, ContentReaderListener stdoutl, ContentReaderListener stderrl)664 public ProcessResult executeBrowser(List<String> otherargs, URL url, ContentReaderListener stdoutl, ContentReaderListener stderrl) throws Exception { 665 ProcessWrapper rpw = new ProcessWrapper(getBrowserLocation(), otherargs, url, stdoutl, stderrl, null); 666 rpw.setReactingProcess(getCurrentBrowser());//current browser may be null, but it does not metter 667 return rpw.execute(); 668 } 669 executeBrowser(List<String> otherargs, String resource, List<ContentReaderListener> stdoutl, List<ContentReaderListener> stderrl)670 public ProcessResult executeBrowser(List<String> otherargs, String resource, List<ContentReaderListener> stdoutl, List<ContentReaderListener> stderrl) throws Exception { 671 ProcessWrapper rpw = new ProcessWrapper(getBrowserLocation(), otherargs, getUrlUponThisInstance(resource), stdoutl, stderrl, null); 672 rpw.setReactingProcess(getCurrentBrowser());// current browser may be null, but it does not matter 673 return rpw.execute(); 674 } 675 executeBrowser(Browser b, List<String> otherargs, String resource)676 public ProcessResult executeBrowser(Browser b, List<String> otherargs, String resource) throws Exception { 677 ProcessWrapper rpw = new ProcessWrapper(b.getBin(), otherargs, getUrlUponThisInstance(resource)); 678 rpw.setReactingProcess(b); 679 return rpw.execute(); 680 } 681 executeBrowser(Browser b, List<String> otherargs, String resource, ContentReaderListener stdoutl, ContentReaderListener stderrl)682 public ProcessResult executeBrowser(Browser b, List<String> otherargs, String resource, ContentReaderListener stdoutl, ContentReaderListener stderrl) throws Exception { 683 ProcessWrapper rpw = new ProcessWrapper(b.getBin(), otherargs, getUrlUponThisInstance(resource), stdoutl, stderrl, null); 684 rpw.setReactingProcess(b); 685 return rpw.execute(); 686 } 687 executeBrowser(Browser b, List<String> otherargs, String resource, List<ContentReaderListener> stdoutl, List<ContentReaderListener> stderrl)688 public ProcessResult executeBrowser(Browser b, List<String> otherargs, String resource, List<ContentReaderListener> stdoutl, List<ContentReaderListener> stderrl) throws Exception { 689 ProcessWrapper rpw = new ProcessWrapper(b.getBin(), otherargs, getUrlUponThisInstance(resource), stdoutl, stderrl, null); 690 rpw.setReactingProcess(b); 691 return rpw.execute(); 692 } 693 694 /** 695 * Create resource on http, on 'localhost' on port on which this cached instance is running 696 * @param resource 697 * @return 698 * @throws MalformedURLException 699 */ getUrlUponThisInstance(String resource)700 public URL getUrlUponThisInstance(String resource) throws MalformedURLException { 701 getInstance(); 702 return getUrlUponInstance(server, resource); 703 } 704 705 /** 706 * Create resource on http, on 'localhost' on port on which this instance is running 707 * @param instance of server to return the resource 708 * @param resource relative path to resource to be loaded from specified instance 709 * @return the absolute url 710 * @throws MalformedURLException 711 */ getUrlUponInstance(ServerLauncher instance,String resource)712 public static URL getUrlUponInstance(ServerLauncher instance,String resource) throws MalformedURLException { 713 return instance.getUrl(resource); 714 } 715 716 /** 717 * wrapping method to executeProcess (eg: javaws arg arg arg url) 718 * will execute default javaws (@see JAVAWS_BUILD_BIN) upon any server 719 * @param otherargs - commandline arguments for javaws process 720 * @param u url of resource upon any server 721 * @return result what left after running this process 722 * @throws Exception 723 */ executeJavawsUponUrl(List<String> otherargs, URL u)724 public ProcessResult executeJavawsUponUrl(List<String> otherargs, URL u) throws Exception { 725 return executeProcessUponURL(getJavawsLocation(), otherargs, u); 726 } executeJavawsUponUrl(List<String> otherargs, URL u,ContentReaderListener stdoutl,ContentReaderListener stderrl)727 public ProcessResult executeJavawsUponUrl(List<String> otherargs, URL u,ContentReaderListener stdoutl,ContentReaderListener stderrl) throws Exception { 728 return executeProcessUponURL(getJavawsLocation(), otherargs, u,stdoutl,stderrl); 729 } 730 731 /** 732 * wrapping utility method to executeProcess (eg: any_binary arg arg arg url) 733 * 734 * will execute any process upon url upon any server 735 * @param toBeExecuted - command to lunch javaws program 736 * @param u url of resource upon any server 737 * @param otherargs commandline arguments for new process 738 * @return result what left after running this process 739 * @throws Exception 740 */ executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u)741 public static ProcessResult executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u) throws Exception { 742 return new ProcessWrapper(toBeExecuted, otherargs, u).execute(); 743 } 744 executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u, ContentReaderListener stdoutl, ContentReaderListener stderrl)745 public static ProcessResult executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u, ContentReaderListener stdoutl, ContentReaderListener stderrl) throws Exception { 746 return new ProcessWrapper(toBeExecuted, otherargs, u, stdoutl, stderrl, null).execute(); 747 } 748 executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u, ContentReaderListener stdoutl, ContentReaderListener stderrl, String[] vars)749 public static ProcessResult executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u, ContentReaderListener stdoutl, ContentReaderListener stderrl, String[] vars) throws Exception { 750 return new ProcessWrapper(toBeExecuted, otherargs, u, stdoutl, stderrl, vars).execute(); 751 } 752 executeProcess(final List<String> args)753 public static ProcessResult executeProcess(final List<String> args) throws Exception { 754 return executeProcess(args, null); 755 } executeProcess(final List<String> args,ContentReaderListener stdoutl,ContentReaderListener stderrl)756 public static ProcessResult executeProcess(final List<String> args,ContentReaderListener stdoutl,ContentReaderListener stderrl) throws Exception { 757 return executeProcess(args, null,stdoutl,stderrl); 758 } executeProcess(final List<String> args,ContentReaderListener stdoutl,ContentReaderListener stderrl,String[] vars)759 public static ProcessResult executeProcess(final List<String> args,ContentReaderListener stdoutl,ContentReaderListener stderrl,String[] vars) throws Exception { 760 return executeProcess(args, null,stdoutl,stderrl,vars); 761 } 762 /** 763 * utility method to lunch process, get its stdout/stderr, its return value and to kill it if running to long (@see PROCESS_TIMEOUT) 764 * 765 * 766 * Small background: 767 * This method creates thread inside which exec will be executed. Then creates assassin thread with given timeout to kill the previously created thread if necessary. 768 * Starts assassin thread, starts process thread. Wait until process is running, then starts content readers. 769 * Closes input of process. 770 * Wait until process is running (no matter if it terminate itself (correctly or badly), or is terminated by its assassin. 771 * Construct result from read stdout, stderr, process return value, assassin successfully 772 * 773 * @param args binary with args to be executed 774 * @param dir optional, directory where this process will run 775 * @return what left from process - process itself, its stdout, stderr and return value and whether it was terminated by assassin. 776 * @throws Exception 777 */ executeProcess(final List<String> args,File dir)778 public static ProcessResult executeProcess(final List<String> args,File dir) throws Exception { 779 return executeProcess(args, dir, null, null); 780 } 781 782 /** 783 * Proceed message s to logging with request to reprint to System.err 784 * @param s 785 */ logErrorReprint(String s)786 public static void logErrorReprint(String s) { 787 log(s, false, true); 788 } 789 790 /** 791 * Proceed message s to logging with request to reprint to System.out 792 * @param s 793 */ logOutputReprint(String s)794 public static void logOutputReprint(String s) { 795 log(s, true, false); 796 } 797 798 /** 799 * Proceed message s to logging withhout request to reprint 800 * @param s 801 */ logNoReprint(String s)802 public static void logNoReprint(String s) { 803 log(s, false, false); 804 } 805 log(String message, boolean printToOut, boolean printToErr)806 static void log(String message, boolean printToOut, boolean printToErr) { 807 String idded; 808 StackTraceElement ste = getTestMethod(); 809 String fullId = LoggingBottleneck.getDefaultLoggingBottleneck().modifyMethodWithForBrowser(ste.getMethodName(), ste.getClassName()); 810 if (message.contains("\n")) { 811 idded = fullId + ": \n" + message + "\n" + fullId + " ---"; 812 } else { 813 idded = fullId + ": " + message; 814 815 } 816 if (LOGS_REPRINT) { 817 if (printToOut) { 818 System.out.println(idded); 819 } 820 if (printToErr) { 821 System.err.println(idded); 822 } 823 } 824 LoggingBottleneck.getDefaultLoggingBottleneck().logIntoPlaintextLog(idded, printToOut,printToErr); 825 LoggingBottleneck.getDefaultLoggingBottleneck().addToXmlLog(message,printToOut,printToErr,ste); 826 } 827 logException(Throwable t)828 public static void logException(Throwable t){ 829 logException(t, true); 830 } logException(Throwable t, boolean print)831 public static void logException(Throwable t, boolean print){ 832 log(OutputController.exceptionToString(t), false, print); 833 } 834 getTestMethod()835 private static StackTraceElement getTestMethod() { 836 return getTestMethod(Thread.currentThread().getStackTrace()); 837 } 838 getTestMethod(StackTraceElement[] stack)839 private static StackTraceElement getTestMethod(StackTraceElement[] stack) { 840 //0 is always thread 841 //1 is net.sourceforge.jnlp.* 842 //we need to get out of all of classes from this package or pick last of it 843 StackTraceElement result = stack[1]; 844 String baseClass = stack[1].getClassName(); 845 int i = 2; 846 for (; i < stack.length; i++) { 847 result = stack[i];//at least moving up 848 if (stack[i].getClassName().contains("$")) { 849 continue; 850 } 851 //probablky it is necessary to get out of net.sourceforge.jnlp. 852 //package where are right now all test-extensions 853 //for now keeping exactly the three classes helping you access the log 854 try { 855 Class<?> clazz = Class.forName(stack[i].getClassName()); 856 String path = null; 857 try { 858 path = clazz.getProtectionDomain().getCodeSource().getLocation().getPath(); 859 } catch (NullPointerException ex) { 860 //silently ignoring and continuing with null path 861 } 862 if (path != null && path.contains("/tests.build/")) { 863 if (!path.contains("/test-extensions/")) { 864 break; 865 } 866 } else { 867 //running from ide 868 if (!stack[i].getClassName().startsWith("net.sourceforge.jnlp.")) { 869 break; 870 } 871 } 872 } catch (ClassNotFoundException ex) { 873 ///should not happen, searching only for already loaded class 874 ex.printStackTrace(); 875 } 876 } 877 //if nothing left in stack then we have been in ServerAccess already 878 //so the target method is the highest form it and better to return it 879 //rather then die to ArrayOutOfBounds 880 if (i >= stack.length) { 881 return result; 882 } 883 //now we are out of test-extensions 884 //method we need (the test) is highest from following class 885 baseClass = stack[i].getClassName(); 886 for (; i < stack.length; i++) { 887 if(stack[i].getClassName().contains("$")){ 888 continue; 889 } 890 if (!baseClass.equals(stack[i].getClassName())) { 891 break; 892 } 893 result = stack[i]; 894 } 895 896 return result; 897 } 898 executeProcess(final List<String> args, File dir, ContentReaderListener stdoutl, ContentReaderListener stderrl)899 public static ProcessResult executeProcess(final List<String> args, File dir, ContentReaderListener stdoutl, ContentReaderListener stderrl) throws Exception { 900 return executeProcess(args, dir, stdoutl, stderrl,null); 901 902 } executeProcess(final List<String> args, File dir, ContentReaderListener stdoutl, ContentReaderListener stderrl, String[] vars)903 public static ProcessResult executeProcess(final List<String> args, File dir, ContentReaderListener stdoutl, ContentReaderListener stderrl, String[] vars) throws Exception { 904 return new ProcessWrapper(args, dir, stdoutl, stderrl, vars).execute(); 905 } 906 907 } 908