EventDispatcher.java :  » IDE-Netbeans » jemmy » org » netbeans » jemmy » Java Open Source

Java Open Source » IDE Netbeans » jemmy 
jemmy » org » netbeans » jemmy » EventDispatcher.java
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s): Alexandre Iline.
 *
 * The Original Software is the Jemmy library.
 * The Initial Developer of the Original Software is Alexandre Iline.
 * All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 *
 *
 *
 * $Id$ $Revision$ $Date$
 *
 */

package org.netbeans.jemmy;

import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.Window;

import java.awt.event.AWTEventListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;

import javax.swing.SwingUtilities;

/** 
 * Provides low level functions for reproducing user actions.
 * One dispatch model uses the managed component's event queue to dispatch
 * events.  The other dispatch model uses <code>java.awt.Robot</code> to
 * generate native events.  It is an option in the Robot dispatch model
 * to wait for the managed component's event queue to empty before dispatching
 * events.
 *
 * Timeouts used: <BR>
 * EventDispatcher.WaitQueueEmptyTimeout - to wait event queue empty. <BR>
 * EventDispatcher.RobotAutoDelay - param for java.awt.Robot.setAutoDelay method. <BR>
 * EventDispatcher.WaitComponentUnderMouseTimeout - time to wait component under mouse. <BR>
 *
 * @see org.netbeans.jemmy.Timeouts
 *
 * @author Alexandre Iline (alexandre.iline@sun.com)
 *
 */
public class EventDispatcher implements Outputable, Timeoutable {

    private final static long WAIT_QUEUE_EMPTY_TIMEOUT = 180000;
    private final static long ROBOT_AUTO_DELAY = 10;
    private final static long WAIT_COMPONENT_UNDER_MOUSE_TIMEOUT = 60000;

    private static Field[] keyFields;
    private static MotionListener motionListener = null;

    /**
     * Component to dispatch events to.
     */
    protected Component component;
    private TestOut output;
    private Timeouts timeouts;
    private ClassReference reference;
    private int model;
    private ClassReference robotReference = null;
    private boolean outsider = false;
    private QueueTool queueTool;

    /**
     * Constructor.
     * @param comp Component to operate with.
     */
    public EventDispatcher(Component comp) {
  super();
  component = comp;
  reference = new ClassReference(comp);
  queueTool = new QueueTool();
  setOutput(JemmyProperties.getProperties().getOutput());
  setTimeouts(JemmyProperties.getProperties().getTimeouts());
  setDispatchingModel(JemmyProperties.getProperties().getDispatchingModel());
    }

    /**
     * Waits for the managed component's <code>java.awt.EventQueue</code> to empty.
     * The timeout for this wait is EventDispatcher.WaitQueueEmptyTimeout.
     * @param output Output to print exception into.
     * @param timeouts A collection of timeout assignments.
     * @throws TimeoutExpiredException
     * @see org.netbeans.jemmy.QueueTool
     */
    public static void waitQueueEmpty(TestOut output, Timeouts timeouts) {
  QueueTool qt = new QueueTool();
  qt.setTimeouts(timeouts.cloneThis());
  qt.getTimeouts().
      setTimeout("QueueTool.WaitQueueEmptyTimeout",
           JemmyProperties.
           getCurrentTimeout("EventDispatcher.WaitQueueEmptyTimeout"));
  qt.setOutput(output);
  qt.waitEmpty();
    }

    /**
     * Waits for the managed component's <code>java.awt.EventQueue</code> to empty.
     * Uses default output and timeouts.  The timeout for this wait is
     * EventDispatcher.WaitQueueEmptyTimeout.
     * @see QueueTool
     * @throws TimeoutExpiredException
     */
    public static void waitQueueEmpty() {
  waitQueueEmpty(JemmyProperties.getCurrentOutput(),
           JemmyProperties.getCurrentTimeouts());
    }

    /**
     * Waits for the managed component's <code>java.awt.EventQueue</code> to stay empty.
     * The timeout for this wait is EventDispatcher.WaitQueueEmptyTimeout.
     * @param emptyTime The time that the event queue has to stay empty to avoid
     * a TimeoutExpiredException.
     * @param output Output to print exception into
     * @param timeouts A collection of timeout assignments.
     * @throws TimeoutExpiredException
     * @see org.netbeans.jemmy.QueueTool
     */
    public static void waitQueueEmpty(long emptyTime, TestOut output, Timeouts timeouts) {
  QueueTool qt = new QueueTool();
  qt.setTimeouts(timeouts.cloneThis());
  qt.getTimeouts().
      setTimeout("QueueTool.WaitQueueEmptyTimeout",
           JemmyProperties.
           getCurrentTimeout("EventDispatcher.WaitQueueEmptyTimeout"));
  qt.setOutput(output);
  qt.waitEmpty(emptyTime);
    }

    /**
     * Waits for the managed component's <code>java.awt.EventQueue</code> to stay empty.
     * Uses default output and timeouts.  The timeout for this wait is
     * EventDispatcher.WaitQueueEmptyTimeout.
     * @param emptyTime The time that the event queue has to stay empty to avoid
     * a TimeoutExpiredException.
     * @throws TimeoutExpiredException
     * @see org.netbeans.jemmy.QueueTool
     */
    public static void waitQueueEmpty(long emptyTime) {
  waitQueueEmpty(emptyTime,
           JemmyProperties.getCurrentOutput(),
           JemmyProperties.getCurrentTimeouts());
    }

    /**
     * Get a string representation for key modifiers.
     * Used to print trace.
     * @param modifiers Bit mask of keyboard event modifiers.
     * @return a string representation for the keyboard event modifiers.
     */
    public static String getModifiersString(int modifiers) {
  String result = "";
  if((modifiers & InputEvent.CTRL_MASK) != 0) {
      result = result + "CTRL_MASK | ";
  }
  if((modifiers & InputEvent.META_MASK) != 0) {
      result = result + "META_MASK | ";
  }
  if((modifiers & InputEvent.ALT_MASK) != 0) {
      result = result + "ALT_MASK | ";
  }
  if((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
      result = result + "ALT_GRAPH_MASK | ";
  }
  if((modifiers & InputEvent.SHIFT_MASK) != 0) {
      result = result + "SHIFT_MASK | ";
  }
  if(result.length() > 0) {
      return(result.substring(0, result.length() - 3));
  }
  return(result);
    }

    /**
     * Returns a string representation for a keyboard event.
     * Used to print trace.
     * @param keyCode Key code (<code>KeyEvent.VK_*</code> value)
     * @return the KeyEvent field name.
     */
    public static String getKeyDescription(int keyCode) {
  for(int i = 0; i < keyFields.length; i++) {
      try {
    if(keyFields[i].getName().startsWith("VK_") && 
       keyFields[i].getInt(null) == keyCode) {
        return(keyFields[i].getName());
    }
      } catch(IllegalAccessException e) {
    JemmyProperties.getCurrentOutput().printStackTrace(e);
      }
  }
  return("VK_UNKNOWN");
    }

    /**
     * Returns a mouse button string representation.
     * Used to print trace.
     * @param button Mouse button (<code>InputEvent.BUTTON1/2/3_MASK</code> value).
     * @return InputEvent field name.
     */
    public static String getMouseButtonDescription(int button) {
  String result;
  if       ((button & InputEvent.BUTTON1_MASK) != 0) {
      result = "BUTTON1";
  } else if((button & InputEvent.BUTTON2_MASK) != 0) {
      result = "BUTTON2";
  } else if((button & InputEvent.BUTTON3_MASK) != 0) {
      result = "BUTTON3";
  } else {
      result = "UNKNOWN_BUTTON";
  }
  return(result);
    }

    static {
  Timeouts.initDefault("EventDispatcher.WaitQueueEmptyTimeout", WAIT_QUEUE_EMPTY_TIMEOUT);
  Timeouts.initDefault("EventDispatcher.RobotAutoDelay", ROBOT_AUTO_DELAY);
  Timeouts.initDefault("EventDispatcher.WaitComponentUnderMouseTimeout", WAIT_COMPONENT_UNDER_MOUSE_TIMEOUT);
  try {
      keyFields = Class.forName("java.awt.event.KeyEvent").getFields();
  } catch(ClassNotFoundException e) {
      JemmyProperties.getCurrentOutput().printStackTrace(e);
  }
    }

    /**
     * Wait (or not) for the mouse to move over a Java component before pressing.
     * This option is relevant when using <code>java.awt.Robot</code> to generate
     * mouse events.  If a mouse press occurs at a position not occupied by a
     * known Java component then a <code>NoComponentUnderMouseException</code>
     * will be thrown.
     * @param yesOrNo if <code>true</code> then the test system will wait for
     * the mouse to move over a Java component before pressing.
     * therwise, mouse presses can take place anywhere on the screen.
     */
    public void checkComponentUnderMouse(boolean yesOrNo) {
  outsider = !yesOrNo;
    }

    /**
     * Defines print output streams or writers.
     * @param out Identify the streams or writers used for print output.
     * @see org.netbeans.jemmy.Outputable
     * @see org.netbeans.jemmy.TestOut
     * @see #getOutput
     */
    public void setOutput(TestOut out) {
  output = out;
  queueTool.setOutput(out);
    }

    /**
     * Returns print output streams or writers.
     * @return an object that contains references to objects for
     * printing to output and err streams.
     * @see org.netbeans.jemmy.Outputable
     * @see org.netbeans.jemmy.TestOut
     * @see #setOutput
     */
    public TestOut getOutput() {
  return(output);
    }

    /**
     * Defines current timeouts.
     * @param timeouts A collection of timeout assignments.
     * @see org.netbeans.jemmy.Timeoutable
     * @see org.netbeans.jemmy.Timeouts
     * @see #getTimeouts
     */
    public void setTimeouts(Timeouts timeouts) {
  this.timeouts = timeouts;
  queueTool.setTimeouts(timeouts);
  queueTool.getTimeouts().
      setTimeout("QueueTool.WaitQueueEmptyTimeout",
           timeouts.
           getTimeout("EventDispatcher.WaitQueueEmptyTimeout"));
  if(robotReference != null) {
      try {
    Object[] params = {new Integer((int)timeouts.getTimeout("EventDispatcher.RobotAutoDelay"))};
    Class[] paramClasses = {Integer.TYPE};
    robotReference.invokeMethod("setAutoDelay", params, paramClasses);
      } catch(InvocationTargetException e) {
    output.printStackTrace(e);
      } catch(IllegalStateException e) {
    output.printStackTrace(e);
      } catch(NoSuchMethodException e) {
    output.printStackTrace(e);
      } catch(IllegalAccessException e) {
    output.printStackTrace(e);
      }
  }
    }

    /**
     * Return current timeouts.
     * @return the collection of current timeout assignments.
     * @see org.netbeans.jemmy.Timeoutable
     * @see org.netbeans.jemmy.Timeouts
     * @see #setTimeouts
     */
    public Timeouts getTimeouts() {
  return(timeouts);
    }

    /**
     * Defines dispatching model.
     * @param m New model value.
     * @see #getDispatchingModel()
     * @see org.netbeans.jemmy.JemmyProperties#QUEUE_MODEL_MASK
     * @see org.netbeans.jemmy.JemmyProperties#ROBOT_MODEL_MASK
     * @see org.netbeans.jemmy.JemmyProperties#getCurrentDispatchingModel()
     * @see org.netbeans.jemmy.JemmyProperties#setCurrentDispatchingModel(int)
     * @see org.netbeans.jemmy.JemmyProperties#initDispatchingModel(boolean, boolean)
     * @see org.netbeans.jemmy.JemmyProperties#initDispatchingModel()
     */
    public void setDispatchingModel(int m) {
  model = m;
  if((model & JemmyProperties.ROBOT_MODEL_MASK) != 0) {
      createRobot();
      try {
    Object[] params = { (model & JemmyProperties.QUEUE_MODEL_MASK) != 0 ? Boolean.TRUE : Boolean.FALSE };
    Class[] paramClasses = {Boolean.TYPE};
    robotReference.invokeMethod("setAutoWaitForIdle", params, paramClasses);
      } catch(InvocationTargetException e) {
    output.printStackTrace(e);
      } catch(IllegalStateException e) {
    output.printStackTrace(e);
      } catch(NoSuchMethodException e) {
    output.printStackTrace(e);
      } catch(IllegalAccessException e) {
    output.printStackTrace(e);
      }
  }
    }

    /**
     * Gets the dispatching model value.
     * @return the model value.
     * @see #setDispatchingModel(int)
     * @see org.netbeans.jemmy.JemmyProperties#QUEUE_MODEL_MASK
     * @see org.netbeans.jemmy.JemmyProperties#ROBOT_MODEL_MASK
     * @see org.netbeans.jemmy.JemmyProperties#getCurrentDispatchingModel()
     * @see org.netbeans.jemmy.JemmyProperties#setCurrentDispatchingModel(int)
     * @see org.netbeans.jemmy.JemmyProperties#initDispatchingModel(boolean, boolean)
     * @see org.netbeans.jemmy.JemmyProperties#initDispatchingModel()
     */
    public int getDispatchingModel() {
  return(model);
    }

    /**
     * Dispatches <code>AWTEvent</code> to component passed in constructor.
     * If <code>(getDispatchingModel & JemmyProperties.QUEUE_MODEL_MASK) == 0</code>
     * dispatched event directly, otherwise uses
     * <code>javax.swing.SwingUtilities.invokeAndWait(Runnable)</code><BR>
     * @param event AWTEvent instance to be dispatched.
     * @throws ComponentIsNotVisibleException
     * @throws ComponentIsNotFocusedException
     */
    public void dispatchEvent(final AWTEvent event) {
        // run in dispatch thread
        String eventToString = (String)queueTool.invokeSmoothly(
            new QueueTool.QueueAction("event.toString()") {
                public Object launch() {
                    return event.toString();
                }
            }
        );
  output.printLine("Dispatch event " + eventToString);
  output.printGolden("Dispatch event " + event.getClass().toString());
  Dispatcher disp = new Dispatcher(event);
  queueTool.invokeAndWait(disp);
    }

    /**
     * Dispatches a MouseEvent.
     * @see #dispatchEvent(AWTEvent)
     * @param id <code>MouseEvent.MOUSE_*</code> value
     * @param mods <code>InputEvent.MOUSE1/2/3_BUTTON</code> | (modiviers value)
     * @param clickCount Click count
     * @param x Horizontal click point coordinate.
     * @param y vertical click point coordinate.
     * @param popup Difines if mouse event is popup event.
     */
    public void dispatchMouseEvent(int id, int mods, int clickCount, int x, int y, 
           boolean popup) {
  MouseEvent event = new MouseEvent(component, id, System.currentTimeMillis(), 
            mods, x, y, clickCount, popup);
  dispatchEvent(event);
    }

    /**
     * Dispatches MouseEvent at the center of component.
     * @see #dispatchEvent(AWTEvent)
     * @param id <code>MouseEvent.MOUSE_*</code> value
     * @param mods <code>InputEvent.MOUSE1/2/3_BUTTON</code> | (modiviers value)
     * @param clickCount Click count
     * @param popup Difines if mouse event is popup event.
     */
    public void dispatchMouseEvent(int id, int mods, int clickCount, 
           boolean popup) {
  int x = component.getWidth() /2;
  int y = component.getHeight()/2;
  dispatchMouseEvent(id, mods, clickCount, x, y, popup);
    }

    /**
     * Dispatches WindowEvent.
     * @see #dispatchEvent(AWTEvent)
     * @param id <code>WindowEvent.WINDOW_*</code> value
     */
    public void dispatchWindowEvent(int id) {
  WindowEvent event = new WindowEvent((Window)component, id);
  dispatchEvent(event);
    }

    /**
     * Dispatches KeyEvent.
     * @see #dispatchEvent(AWTEvent)
     * @param id <code>KeyEvent.KEY_PRESSED</code> or <code>KeyEvent.KEY_RELEASED</code> value.
     * @param mods Modifiers.
     * @param keyCode Key code,
     */
    public void dispatchKeyEvent(int id, int mods, int keyCode) {
  KeyEvent event = new KeyEvent(component, id, System.currentTimeMillis()
              , mods, keyCode);
  dispatchEvent(event);
    }

    /**
     * Dispatches KeyEvent.
     * @see #dispatchEvent(AWTEvent)
     * @param id <code>KeyEvent.KEY_TYPED</code> value.
     * @param mods Modifiers.
     * @param keyCode Key code,
     * @param keyChar Char to be tiped
     */
    public void dispatchKeyEvent(int id, int mods, int keyCode, char keyChar) {
  KeyEvent event = new KeyEvent(component, id, System.currentTimeMillis(), 
              mods, keyCode, keyChar);
  dispatchEvent(event);
    }

    /**
     * Waits until all events currently on the event queue have been processed.
     */
    public void waitForIdle() {
  makeRobotOperation("waitForIdle", null, null);
    }

    /**
     * Bind horizontal relative cursor coordinate to screen coordinate.
     * @param x Relative coordinate
     * @return Absolute coordinate
     */
    protected int getAbsoluteX(int x) {
  return((int)component.getLocationOnScreen().getX() + x);
    }

    /**
     * Bind vertical relative cursor coordinate to screen coordinate.
     * @param y Relative coordinate
     * @return Absolute coordinate
     */
    protected int getAbsoluteY(int y) {
  return((int)component.getLocationOnScreen().getY() + y);
    }

    /**
     * Delays robot.
     * @param time Time to dalay robot for.
     */
    public void delayRobot(long time) {
  Object[] params = {new Integer((int)time)};
  Class[] paramClasses = {Integer.TYPE};
  makeRobotOperation("delay", params, paramClasses);
    }

    /**
     * Moves mouse by robot.
     * @param x Component relative horizontal coordinate.
     * @param y Component relative vertical coordinate.
     * @throws ComponentIsNotVisibleException
     */
    public void robotMoveMouse(int x, int y) {
  if(motionListener == null) {
      initMotionListener();
  }
  output.printLine("Move mouse to (" + Integer.toString(x) + "," +
       Integer.toString(y) + ")");
  Object[] params = {new Integer(getAbsoluteX(x)), new Integer(getAbsoluteY(y))};
  Class[] paramClasses = {Integer.TYPE, Integer.TYPE};
  makeRobotOperation("mouseMove", params, paramClasses);
    }

    /**
     * Press mouse button by robot.
     * @param button Mouse button (InputEvent.MOUSE1/2/3_BUTTON value)
     * @param modifiers Modifiers
     * @throws ComponentIsNotVisibleException
     */
    public void robotPressMouse(int button, int modifiers) {
  if(!outsider) {
      waitMouseOver();
  }
  robotPressModifiers(modifiers);
  output.printLine("Press " + getMouseButtonDescription(button) + " mouse button");
  Object[] params = {new Integer(button)};
  Class[] paramClasses = {Integer.TYPE};
  makeRobotOperation("mousePress", params, paramClasses);
    }

    /**
     * Press mouse button with 0 modifiers.
     * @param button Mouse button (<code>InputEvent.MOUSE1/2/3_BUTTON</code> value)
     * @see #robotPressMouse(int, int)
     */
    public void robotPressMouse(int button) {
  robotPressMouse(button, 0);
    }

    /**
     * Releases mouse button by robot.
     * @param button Mouse button (<code>InputEvent.MOUSE1/2/3_BUTTON</code> value)
     * @param modifiers Modifiers
     * @throws ComponentIsNotVisibleException
     */
    public void robotReleaseMouse(int button, int modifiers) {
  output.printLine("Release " + getMouseButtonDescription(button) + " mouse button");
  Object[] params = {new Integer(button)};
  Class[] paramClasses = {Integer.TYPE};
  makeRobotOperation("mouseRelease", params, paramClasses);
  robotReleaseModifiers(modifiers);
    }

    /**
     * Releases mouse button with 0 modifiers.
     * @param button Mouse button (<code>InputEvent.MOUSE1/2/3_BUTTON</code> value)
     * @see #robotReleaseMouse(int, int)
     */
    public void robotReleaseMouse(int button) {
  robotReleaseMouse(button, 0);
    }

    /**
     * Press a key using <code>java.awt.Robot</code>.
     * @param keyCode Key (<code>KeyEvent.VK_*</code> value)
     * @param modifiers Mask of KeyEvent modifiers.
     * @throws ComponentIsNotVisibleException
     * @throws ComponentIsNotFocusedException
     */
    public void robotPressKey(int keyCode, int modifiers) {
  robotPressModifiers(modifiers);
  output.printLine("Press " + getKeyDescription(keyCode) + " key");
  Object[] params = {new Integer(keyCode)};
  Class[] paramClasses = {Integer.TYPE};
  makeRobotOperation("keyPress", params, paramClasses);
    }

    /**
     * Press key with no modifiers using <code>java.awt.Robot</code>.
     * @param keyCode Key (<code>KeyEvent.VK_*</code> value)
     * @see #robotPressKey(int, int)
     */
    public void robotPressKey(int keyCode) {
  robotPressKey(keyCode, 0);
    }

    /**
     * Releases key by robot.
     * @param keyCode Key (<code>KeyEvent.VK_*</code> value)
     * @param modifiers Mask of KeyEvent modifiers.
     * @throws ComponentIsNotVisibleException
     * @throws ComponentIsNotFocusedException
     */
    public void robotReleaseKey(int keyCode, int modifiers) {
  output.printLine("Release " + getKeyDescription(keyCode) + " key");
  Object[] params = {new Integer(keyCode)};
  Class[] paramClasses = {Integer.TYPE};
  makeRobotOperation("keyRelease", params, paramClasses);
  robotReleaseModifiers(modifiers);
    }

    /**
     * Releases key with 0 modifiers.
     * @param keyCode Key (<code>KeyEvent.VK_*</code> value)
     * @see #robotPressKey(int, int)
     */
    public void robotReleaseKey(int keyCode) {
  robotReleaseKey(keyCode, 0);
    } 

    /**
     * Invokes component method through <code>SwingUtilities.invokeAndWait(Runnable)</code>.
     * 
     * @param  method_name Name of a method to be invoked
     * @param  params Method params
     * @param  params_classes Method params' classes
     * @return an Object - methods result.
     * @see  org.netbeans.jemmy.ClassReference
     * @exception  IllegalAccessException
     * @exception  NoSuchMethodException
     * @exception  IllegalStateException
     * @exception  InvocationTargetException
     */
    public Object invokeMethod(String method_name, Object[] params, Class[] params_classes)
  throws InvocationTargetException, IllegalStateException, NoSuchMethodException, IllegalAccessException {
  Invoker invk = new Invoker(method_name, params, params_classes);
  try {
      return(queueTool.invokeAndWait(invk));
  } catch(JemmyException e) {
      if(invk.getException() != null) {
    if(invk.getException() instanceof InvocationTargetException) {
        throw((InvocationTargetException)invk.getException());
    } else if(invk.getException() instanceof IllegalStateException) {
        throw((IllegalStateException)invk.getException());
    } else if(invk.getException() instanceof NoSuchMethodException) {
        throw((NoSuchMethodException)invk.getException());
    } else if(invk.getException() instanceof IllegalAccessException) {
        throw((IllegalAccessException)invk.getException());
    }
      }
      throw(e);
  }
    }

    /**
     * Gets component field value through <code>SwingUtilities.invokeAndWait(Runnable)</code>.
     * 
     * @param  field_name Name of a field
     * @see  #setField(String, Object)
     * @see  org.netbeans.jemmy.ClassReference
     * @return an Object - field value
     * @exception  IllegalAccessException
     * @exception  IllegalStateException
     * @exception  InvocationTargetException
     * @exception  NoSuchFieldException
     */
    public Object getField(String field_name)
  throws InvocationTargetException, IllegalStateException, NoSuchFieldException, IllegalAccessException {
  Getter gtr = new Getter(field_name);
  try {
      return(queueTool.invokeAndWait(gtr));
  } catch(JemmyException e) {
      if(gtr.getException() != null) {
    if(gtr.getException() instanceof InvocationTargetException) {
        throw((InvocationTargetException)gtr.getException());
    } else if(gtr.getException() instanceof IllegalStateException) {
        throw((IllegalStateException)gtr.getException());
    } else if(gtr.getException() instanceof NoSuchFieldException) {
        throw((NoSuchFieldException)gtr.getException());
    } else if(gtr.getException() instanceof IllegalAccessException) {
        throw((IllegalAccessException)gtr.getException());
    }
      }
      throw(e);
  }
    }

    /**
     * Sets component field value through <code>SwingUtilities.invokeAndWait(Runnable)</code>.
     * 
     * @param  field_name Name of a field
     * @param  newValue New field value
     * @see  #getField(String)
     * @see  org.netbeans.jemmy.ClassReference
     * @exception  IllegalAccessException
     * @exception  IllegalStateException
     * @exception  InvocationTargetException
     * @exception  NoSuchFieldException
     */
    public void setField(String field_name, Object newValue)
  throws InvocationTargetException, IllegalStateException, NoSuchFieldException, IllegalAccessException {
  Setter str = new Setter(field_name, newValue);
  try {
      queueTool.invokeAndWait(str);
  } catch(JemmyException e) {
      if(str.getException() != null) {
    if(str.getException() instanceof InvocationTargetException) {
        throw((InvocationTargetException)str.getException());
    } else if(str.getException() instanceof IllegalStateException) {
        throw((IllegalStateException)str.getException());
    } else if(str.getException() instanceof NoSuchFieldException) {
        throw((NoSuchFieldException)str.getException());
    } else if(str.getException() instanceof IllegalAccessException) {
        throw((IllegalAccessException)str.getException());
    }
      }
      throw(e);
  }
    }

    /**
     * Invokes component method through <code>SwingUtilities.invokeAndWait(Runnable)</code>.
     * and catch all exceptions.
     * @param method_name Name of a method to be invoked
     * @param params Method params
     * @param params_classes Method params' classes
     * @param out TestOut instance to print exceptions stack trace to.
     * @return an Object - method result
     * @see #invokeMethod(String, Object[], Class[])
     * @see org.netbeans.jemmy.ClassReference
     */
    public Object invokeExistingMethod(String method_name, Object[] params, Class[] params_classes, 
               TestOut out) {
  try {
      return(invokeMethod(method_name, params, params_classes));
  } catch(InvocationTargetException e) {
      out.printStackTrace(e);
  } catch(IllegalStateException e) {
      out.printStackTrace(e);
  } catch(NoSuchMethodException e) {
      out.printStackTrace(e);
  } catch(IllegalAccessException e) {
      out.printStackTrace(e);
  }
  return(null);
    }

    /**
     * Gets component field value through <code>SwingUtilities.invokeAndWait(Runnable)</code>.
     * and catch all exceptions.
     * @param field_name Name of a field
     * @param out TestOut instance to print exceptions stack trace to.
     * @return an Object - fields value
     * @see #getField(String)
     * @see #setExistingField(String, Object, TestOut)
     * @see org.netbeans.jemmy.ClassReference
     */
    public Object getExistingField(String field_name,
           TestOut out) {
  try {
      return(getField(field_name));
  } catch(InvocationTargetException e) {
      out.printStackTrace(e);
  } catch(IllegalStateException e) {
      out.printStackTrace(e);
  } catch(NoSuchFieldException e) {
      out.printStackTrace(e);
  } catch(IllegalAccessException e) {
      out.printStackTrace(e);
  }
  return(null);
    }

    /**
     * Sets component field value through <code>SwingUtilities.invokeAndWait(Runnable)</code>.
     * and catch all exceptions.
     * @param field_name Name of a field
     * @param newValue New field value
     * @param out TestOut instance to print exceptions stack trace to.
     * @see #setField(String, Object)
     * @see #getExistingField(String, TestOut)
     * @see org.netbeans.jemmy.ClassReference
     */
    public void setExistingField(String field_name, Object newValue,
           TestOut out) {
  try {
      setField(field_name, newValue);
  } catch(InvocationTargetException e) {
      out.printStackTrace(e);
  } catch(IllegalStateException e) {
      out.printStackTrace(e);
  } catch(NoSuchFieldException e) {
      out.printStackTrace(e);
  } catch(IllegalAccessException e) {
      out.printStackTrace(e);
  }
    }

    /**
     * Invokes component method through <code>SwingUtilities.invokeAndWait(Runnable)</code>.
     * and catch all exceptions.
     * Exceptions are printed into TestOut object defined 
     * by setOutput(TestOut) method.
     * @param method_name Name of a method to be invoked
     * @param params Method params
     * @param params_classes Method params' classes
     * @return an Object - method result
     * @see #invokeExistingMethod(String, Object[], Class[], TestOut)
     * @see org.netbeans.jemmy.ClassReference
     */
    public Object invokeExistingMethod(String method_name, Object[] params, Class[] params_classes) {
  return(invokeExistingMethod(method_name, params, params_classes, output));
    }

    /**
     * Gets component field value through <code>SwingUtilities.invokeAndWait(Runnable)</code>.
     * and catch all exceptions.
     * Exceptions are printed into TestOut object defined 
     * by setOutput(TestOut) method.
     * @param field_name Name of a field
     * @return an Object - fields value
     * @see #getExistingField(String, TestOut)
     * @see #setExistingField(String, Object)
     * @see org.netbeans.jemmy.ClassReference
     */
    public Object getExistingField(String field_name) {
  return(getExistingField(field_name, output));
    }

    /**
     * Sets component field value through <code>SwingUtilities.invokeAndWait(Runnable)</code>.
     * and catch all exceptions.
     * Exceptions are printed into TestOut object defined 
     * by setOutput(TestOut) method.
     * @param field_name Name of a field
     * @param newValue New field value
     * @see #setExistingField(String, Object, TestOut)
     * @see #getExistingField(String)
     * @see org.netbeans.jemmy.ClassReference
     */
    public void setExistingField(String field_name, Object newValue) {
  setExistingField(field_name, output);
    }

    //recursivelly releases all modifiers keys
    private void robotReleaseModifiers(int modifiers) {
  if       ((modifiers & InputEvent.SHIFT_MASK) != 0) {
      robotReleaseKey(KeyEvent.VK_SHIFT,     modifiers - (InputEvent.SHIFT_MASK     & modifiers));
  } else if((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
      robotReleaseKey(KeyEvent.VK_ALT_GRAPH, modifiers - (InputEvent.ALT_GRAPH_MASK & modifiers));
  } else if((modifiers & InputEvent.ALT_MASK) != 0) {
      robotReleaseKey(KeyEvent.VK_ALT,       modifiers - (InputEvent.ALT_MASK       & modifiers));
  } else if((modifiers & InputEvent.META_MASK) != 0) {
      robotReleaseKey(KeyEvent.VK_META,      modifiers - (InputEvent.META_MASK      & modifiers));
  } else if((modifiers & InputEvent.CTRL_MASK) != 0) {
      robotReleaseKey(KeyEvent.VK_CONTROL,   modifiers - (InputEvent.CTRL_MASK      & modifiers));
  }
    }

    //throws ComponentIsNotVisibleException if component is not visible
    private void checkVisibility() {
  if(!component.isVisible()) {
      throw(new ComponentIsNotVisibleException(component));
  }
    }

    //throws ComponentIsNotFocusedException if component has not focus
    private void checkFocus() {
  if(!component.hasFocus()) {
      throw(new ComponentIsNotFocusedException(component));
  }
    }

    //creates java.awt.Robot instance
    private void createRobot() {
  try {
      ClassReference robotClassReverence = new ClassReference("java.awt.Robot");
      robotReference = new ClassReference(robotClassReverence.newInstance(null, null));
  } catch(ClassNotFoundException e) {
      output.printStackTrace(e);
  } catch(InstantiationException e) {
      output.printStackTrace(e);
  } catch(InvocationTargetException e) {
      output.printStackTrace(e);
  } catch(IllegalStateException e) {
      output.printStackTrace(e);
  } catch(NoSuchMethodException e) {
      output.printStackTrace(e);
  } catch(IllegalAccessException e) {
      output.printStackTrace(e);
  }
    }

    private void waitMouseOver() {
  try {
      Waiter wt = new Waiter(new Waitable() {
    public Object actionProduced(Object obj) {
        if(motionListener.getComponent() != null) {
      return("");
        } else {
      return(null);
        }
    }
    public String getDescription() {
        return("Mouse over component");
    }
      });
      wt.setTimeouts(timeouts.cloneThis());
      wt.getTimeouts().setTimeout("Waiter.WaitingTime", 
          timeouts.getTimeout("EventDispatcher.WaitComponentUnderMouseTimeout"));
      wt.setOutput(output.createErrorOutput());
      wt.waitAction(component);
  } catch(InterruptedException e) {
      output.printStackTrace(e);
  } catch(TimeoutExpiredException e) {
      throw(new NoComponentUnderMouseException());
  }
    }

    //produce a robot operations through reflection
    private void makeRobotOperation(String method, Object[] params, Class[] paramClasses) {
  try {
      robotReference.invokeMethod(method, params, paramClasses);
  } catch(InvocationTargetException e) {
      output.printStackTrace(e);
  } catch(IllegalStateException e) {
      output.printStackTrace(e);
  } catch(NoSuchMethodException e) {
      output.printStackTrace(e);
  } catch(IllegalAccessException e) {
      output.printStackTrace(e);
  }
  if ((model & JemmyProperties.QUEUE_MODEL_MASK) != 0) {
      try {
    waitQueueEmpty(output.createErrorOutput(), timeouts);
      } catch(TimeoutExpiredException e) {
    output.printStackTrace(e);
      }
  }
    }

    //recursivelly presses all modifiers keys
    private void robotPressModifiers(int modifiers) {
  if       ((modifiers & InputEvent.SHIFT_MASK) != 0) {
      robotPressKey(KeyEvent.VK_SHIFT,     modifiers & ~InputEvent.SHIFT_MASK);
  } else if((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
      robotPressKey(KeyEvent.VK_ALT_GRAPH, modifiers & ~InputEvent.ALT_GRAPH_MASK);
  } else if((modifiers & InputEvent.ALT_MASK) != 0) {
      robotPressKey(KeyEvent.VK_ALT,       modifiers & ~InputEvent.ALT_MASK);
  } else if((modifiers & InputEvent.META_MASK) != 0) {
      robotPressKey(KeyEvent.VK_META,      modifiers & ~InputEvent.META_MASK);
  } else if((modifiers & InputEvent.CTRL_MASK) != 0) {
      robotPressKey(KeyEvent.VK_CONTROL,   modifiers & ~InputEvent.CTRL_MASK);
  }
    }

    private void initMotionListener() {
  if(motionListener == null) {
       motionListener = new MotionListener();
       Toolkit.getDefaultToolkit().addAWTEventListener(motionListener, AWTEvent.MOUSE_EVENT_MASK);
      Object[] params = new Object[2];
      Class[] paramClasses = {Integer.TYPE, Integer.TYPE};
      params[0] = new Integer(getAbsoluteX(-1));
      params[1] = new Integer(getAbsoluteX(-1));
      makeRobotOperation("mouseMove", params, paramClasses);
      params[0] = new Integer(getAbsoluteX(0));
      params[1] = new Integer(getAbsoluteX(0));
      makeRobotOperation("mouseMove", params, paramClasses);
  }
    }


    private class Dispatcher extends QueueTool.QueueAction {
  AWTEvent event;
  public Dispatcher(AWTEvent e) {
      super(e.getClass().getName() + " event dispatching");
      event = e;
  }
  public Object launch() {
      if(event instanceof MouseEvent || event instanceof KeyEvent) {
    checkVisibility();
      }
      component.dispatchEvent(event);
      return(null);
  }
    }

    private class Invoker extends QueueTool.QueueAction {
  protected String methodName;
  protected Object[] params;
  protected Class[] paramClasses;
  public Invoker(String mn, Object[] p, Class[] pc) {
      super(mn + " method invocation");
      methodName = mn;
      params = p;
      paramClasses = pc;
  }
  public Object launch()
      throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
      checkVisibility();
      if(methodName.equals("keyPress") || methodName.equals("keyRelease")) {
    checkFocus();
      }
      return(reference.invokeMethod(methodName, params, paramClasses));
  }
    }

    private class Getter extends QueueTool.QueueAction {
  String fieldName;
  public Getter(String fn) {
      super(fn + " field receiving");
      fieldName = fn;
  }
  public Object launch()
      throws InvocationTargetException, NoSuchFieldException, IllegalAccessException {
      return(reference.getField(fieldName));
  }
    }

    private class Setter extends QueueTool.QueueAction {
  String fieldName;
  Object newValue;
  public Setter(String fn, Object nv) {
      super(fn + " field changing");
      fieldName = fn;
      newValue = nv;
  }
  public Object launch()
      throws InvocationTargetException, NoSuchFieldException, IllegalAccessException {
      reference.setField(fieldName, newValue);
      return(null);
  }
    }

    private static class MotionListener implements AWTEventListener {
  private Component mouseComponent;
  public void eventDispatched(AWTEvent event) {
      if(event instanceof MouseEvent) {
    MouseEvent e = (MouseEvent)event;
    if       (e.getID() == MouseEvent.MOUSE_ENTERED) {
        mouseComponent = e.getComponent();
    } else if(e.getID() == MouseEvent.MOUSE_EXITED) {
        mouseComponent = null;
    }
      }
  }
  public Component getComponent() {
      return(mouseComponent);
  }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.