selenium.server/src/org/netbeans/modules/selenium/server/SeleniumServerRunner.java
author Martin Fousek <marfous@netbeans.org>
Thu, 01 Nov 2012 09:53:16 +0100
branchrelease72
changeset 17894 7ceebbb201a7
parent 17795 ed07e23ee4d1
child 17940 c5cac35f0ad7
permissions -rw-r--r--
#217956 - UI Element / User-extensions are not configurable via Selenium Server Configuartion
jsedek@14783
     1
/*
jsedek@14783
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jsedek@14783
     3
 *
jsedek@14783
     4
 * Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved.
jsedek@14783
     5
 *
jsedek@14783
     6
 * The contents of this file are subject to the terms of either the GNU
jsedek@14783
     7
 * General Public License Version 2 only ("GPL") or the Common
jsedek@14783
     8
 * Development and Distribution License("CDDL") (collectively, the
jsedek@14783
     9
 * "License"). You may not use this file except in compliance with the
jsedek@14783
    10
 * License. You can obtain a copy of the License at
jsedek@14783
    11
 * http://www.netbeans.org/cddl-gplv2.html
jsedek@14783
    12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jsedek@14783
    13
 * specific language governing permissions and limitations under the
jsedek@14783
    14
 * License.  When distributing the software, include this License Header
jsedek@14783
    15
 * Notice in each file and include the License file at
jsedek@14783
    16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
jsedek@14783
    17
 * particular file as subject to the "Classpath" exception as provided
jsedek@14783
    18
 * by Sun in the GPL Version 2 section of the License file that
jsedek@14783
    19
 * accompanied this code. If applicable, add the following below the
jsedek@14783
    20
 * License Header, with the fields enclosed by brackets [] replaced by
jsedek@14783
    21
 * your own identifying information:
jsedek@14783
    22
 * "Portions Copyrighted [year] [name of copyright owner]"
jsedek@14783
    23
 *
jsedek@14783
    24
 * Contributor(s):
jsedek@14783
    25
 *
jsedek@14783
    26
 * The Original Software is NetBeans. The Initial Developer of the Original
jsedek@14783
    27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
jsedek@14783
    28
 * Microsystems, Inc. All Rights Reserved.
jsedek@14783
    29
 *
jsedek@14783
    30
 * If you wish your version of this file to be governed by only the CDDL
jsedek@14783
    31
 * or only the GPL Version 2, indicate your decision by adding
jsedek@14783
    32
 * "[Contributor] elects to include this software in this distribution
jsedek@14783
    33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jsedek@14783
    34
 * single choice of license, a recipient has the option to distribute
jsedek@14783
    35
 * your version of this file under either the CDDL, the GPL Version 2 or
jsedek@14783
    36
 * to extend the choice of license to its licensees as provided above.
jsedek@14783
    37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jsedek@14783
    38
 * Version 2 license, then the option applies only if the new code is
jsedek@14783
    39
 * made subject to such option by the copyright holder.
jsedek@14783
    40
 */
jsedek@14783
    41
package org.netbeans.modules.selenium.server;
jsedek@14783
    42
jsedek@14783
    43
import java.beans.PropertyChangeEvent;
jsedek@14783
    44
import java.beans.PropertyChangeListener;
marfous@17795
    45
import java.io.File;
marfous@17590
    46
import java.lang.reflect.InvocationTargetException;
jsedek@14784
    47
import java.net.BindException;
marfous@17590
    48
import java.net.MalformedURLException;
marfous@17590
    49
import java.net.URL;
marfous@17590
    50
import java.net.URLClassLoader;
jsedek@14784
    51
import java.util.logging.Level;
jsedek@14784
    52
import java.util.logging.Logger;
jsedek@14783
    53
import org.netbeans.api.server.properties.InstanceProperties;
marfous@17590
    54
import org.openide.modules.InstalledFileLocator;
jsedek@14783
    55
import org.openide.util.RequestProcessor;
jsedek@14783
    56
import org.openide.util.Task;
jsedek@14783
    57
jsedek@14783
    58
/**
jsedek@14783
    59
 *
jsedek@14783
    60
 * @author Jindrich Sedek
marfous@17590
    61
 * @author Martin Fousek
jsedek@14783
    62
 */
jsedek@14783
    63
class SeleniumServerRunner implements Runnable, PropertyChangeListener {
jsedek@14783
    64
marfous@17590
    65
    private static final Logger LOGGER = Logger.getLogger(SeleniumServerRunner.class.getName());
marfous@17590
    66
jsedek@14783
    67
    private static final SeleniumServerRunner instance = new SeleniumServerRunner();
marfous@17590
    68
    private static Object server = null;
jsedek@14783
    69
    private boolean isRunning = false;
jsedek@14783
    70
    private static Action action = null;
jsedek@14783
    71
    private static Task latestTask = null;
jsedek@14783
    72
jsedek@14783
    73
    private SeleniumServerRunner() {
jsedek@14783
    74
    }
jsedek@14783
    75
jsedek@14783
    76
    static Task startServer() {
jsedek@14783
    77
        if (isRunning()) {
jsedek@14783
    78
            return Task.EMPTY;
jsedek@14783
    79
        }
jsedek@14783
    80
        action = Action.START;
jsedek@14783
    81
        return postTask();
jsedek@14783
    82
    }
jsedek@14783
    83
jsedek@14783
    84
    static Task stopServer() {
jsedek@14783
    85
        if (!isRunning()) {
jsedek@14783
    86
            return Task.EMPTY;
jsedek@14783
    87
        }
jsedek@14783
    88
        action = Action.STOP;
jsedek@14783
    89
        return postTask();
jsedek@14783
    90
    }
jsedek@14783
    91
jsedek@14783
    92
    static Task restartServer() {
jsedek@14783
    93
        if (!isRunning()) {
jsedek@14783
    94
            return startServer();
jsedek@14783
    95
        } else {
jsedek@14783
    96
            action = Action.RESTART;
jsedek@14783
    97
            return postTask();
jsedek@14783
    98
        }
jsedek@14783
    99
    }
jsedek@14783
   100
jsedek@14783
   101
    static boolean isRunning() {
jsedek@14783
   102
        return instance.isRunning;
jsedek@14783
   103
    }
jsedek@14783
   104
jsedek@14783
   105
    private static Task postTask(){
jsedek@14783
   106
        Task t = RequestProcessor.getDefault().post(instance);
jsedek@14783
   107
        latestTask = t;
jsedek@14783
   108
        return t;
jsedek@14783
   109
    }
jsedek@14783
   110
marfous@17402
   111
    @Override
jsedek@14783
   112
    public void run() {
jsedek@14783
   113
        try {
jsedek@14783
   114
            if (server == null) {
jsedek@14783
   115
                initializeServer();
jsedek@14783
   116
            }
jsedek@14783
   117
            switch (action) {
jsedek@14783
   118
                case START:
marfous@17893
   119
                    callSeleniumServerMethod("boot");
marfous@17590
   120
                    callSeleniumServerMethod("start");
jsedek@14783
   121
                    break;
jsedek@14783
   122
                case STOP:
marfous@17590
   123
                    callSeleniumServerMethod("stop");
jsedek@14783
   124
                    break;
jsedek@14783
   125
                case RESTART:
marfous@17590
   126
                    callSeleniumServerMethod("stop");
marfous@17893
   127
                    callSeleniumServerMethod("boot");
marfous@17590
   128
                    callSeleniumServerMethod("start");
jsedek@14783
   129
                    break;
jsedek@14783
   130
                case RELOAD:
marfous@17590
   131
                    callSeleniumServerMethod("stop");
jsedek@14783
   132
                    server = null;
jsedek@14783
   133
                    initializeServer();
marfous@17893
   134
                    callSeleniumServerMethod("boot");
marfous@17590
   135
                    callSeleniumServerMethod("start");
jsedek@14783
   136
                    break;
jsedek@14783
   137
                default:
jsedek@14783
   138
                    assert false : "Invalid option";
jsedek@14783
   139
            }
marfous@17402
   140
            if (action == null) {
marfous@17402
   141
                return;
marfous@17402
   142
            }
jsedek@14783
   143
            isRunning = (!action.equals(Action.STOP));
jsedek@14783
   144
            action = null;
marfous@17590
   145
        } catch (BindException bi) {
marfous@17590
   146
            LOGGER.log(Level.INFO, "Port already in use - the server is probably already running.", bi); //NOI18N
jsedek@14783
   147
        } catch (Exception exc) {
marfous@17590
   148
            LOGGER.log(Level.INFO, null, exc);
jsedek@14783
   149
        }
jsedek@14783
   150
    }
jsedek@14783
   151
marfous@17590
   152
    protected static URLClassLoader getSeleniumServerClassLoader() {
marfous@17590
   153
        URL url = null;
marfous@17590
   154
        try {
marfous@17590
   155
            url = InstalledFileLocator.getDefault().locate(
marfous@17740
   156
                        "modules/ext/selenium/selenium-server-2.16.1.jar", //NOI18N
marfous@17590
   157
                        null, //NOI18N
marfous@17590
   158
                        false).toURI().toURL();
marfous@17590
   159
        } catch (MalformedURLException ex) {
marfous@17590
   160
            LOGGER.log(Level.SEVERE, null, ex);
marfous@17590
   161
        }
marfous@17590
   162
        return URLClassLoader.newInstance(new URL[] {url}); //NOI18N
marfous@17590
   163
    }
marfous@17590
   164
marfous@17590
   165
    private void callSeleniumServerMethod(String method) {
marfous@17590
   166
        ClassLoader original = Thread.currentThread().getContextClassLoader();
marfous@17590
   167
        try {
marfous@17590
   168
            ClassLoader curr = server.getClass().getClassLoader();
marfous@17590
   169
            Thread.currentThread().setContextClassLoader(curr);
marfous@17590
   170
            server.getClass().getMethod(method).invoke(server);
marfous@17590
   171
        } catch (IllegalAccessException ex) {
marfous@17745
   172
            LOGGER.log(Level.WARNING, null, ex);
marfous@17590
   173
        } catch (IllegalArgumentException ex) {
marfous@17745
   174
            LOGGER.log(Level.WARNING, null, ex);
marfous@17590
   175
        } catch (NoSuchMethodException ex) {
marfous@17745
   176
            LOGGER.log(Level.WARNING, null, ex);
marfous@17590
   177
        } catch (SecurityException ex) {
marfous@17745
   178
            LOGGER.log(Level.WARNING, null, ex);
marfous@17590
   179
        } catch (InvocationTargetException ex) {
marfous@17745
   180
            LOGGER.log(Level.WARNING, null, ex);
marfous@17590
   181
        } finally {
marfous@17590
   182
            Thread.currentThread().setContextClassLoader(original);
marfous@17590
   183
        }
marfous@17590
   184
    }
marfous@17590
   185
marfous@17590
   186
    private static void initializeServer() throws Exception {
marfous@17590
   187
        URLClassLoader urlClassLoader = getSeleniumServerClassLoader();
marfous@17590
   188
        Class seleniumServer = urlClassLoader.loadClass("org.openqa.selenium.server.SeleniumServer"); //NOI18N
marfous@17590
   189
        Class remoteControlConfiguration = urlClassLoader.loadClass(
marfous@17590
   190
                "org.openqa.selenium.server.RemoteControlConfiguration"); //NOI18N
marfous@17590
   191
jsedek@14783
   192
        InstanceProperties ip = SeleniumProperties.getInstanceProperties();
marfous@17590
   193
        Object remoteControlConfigurationInstance = remoteControlConfiguration.newInstance();
marfous@17795
   194
        int port = ip.getInt(SeleniumProperties.PORT, SeleniumProperties.getSeleniumDefaultPort());
marfous@17590
   195
        remoteControlConfiguration.getMethod("setPort", int.class).invoke(
marfous@17795
   196
            remoteControlConfigurationInstance, port); //NOI18N
marfous@17795
   197
        boolean runInSingleWindow = ip.getBoolean(SeleniumProperties.SINGLE_WINDOW, false);
marfous@17795
   198
        remoteControlConfiguration.getMethod("setSingleWindow", Boolean.TYPE).invoke( //NOI18N
marfous@17795
   199
                remoteControlConfigurationInstance, runInSingleWindow);
marfous@17795
   200
		String firefoxProfileDir = ip.getString(SeleniumProperties.FIREFOX_PROFILE, ""); //NOI18N
marfous@17795
   201
		if (!firefoxProfileDir.isEmpty()) {
marfous@17795
   202
				File ffProfileDir = new File(firefoxProfileDir);
marfous@17795
   203
				if (ffProfileDir.exists()) {
marfous@17795
   204
					remoteControlConfiguration.getMethod("setFirefoxProfileTemplate", File.class).invoke( //NOI18N
marfous@17795
   205
						remoteControlConfigurationInstance, ffProfileDir);
marfous@17795
   206
				}
marfous@17795
   207
		}
marfous@17893
   208
        String userExtensionsString = ip.getString(SeleniumProperties.USER_EXTENSIONS, ""); //NOI18N
marfous@17893
   209
        if (!userExtensionsString.isEmpty()) {
marfous@17893
   210
            File userExtensionFile = new File(userExtensionsString);
marfous@17893
   211
            if (userExtensionFile.exists()) {
marfous@17893
   212
                remoteControlConfiguration.getMethod("setUserExtensions", File.class).invoke( //NOI18N
marfous@17893
   213
                        remoteControlConfigurationInstance, userExtensionFile);
marfous@17893
   214
            }
marfous@17893
   215
        }
marfous@17893
   216
        
marfous@17590
   217
        server = seleniumServer.getConstructor(remoteControlConfiguration).
marfous@17590
   218
                newInstance(remoteControlConfigurationInstance);
jsedek@14783
   219
    }
jsedek@14783
   220
marfous@17402
   221
    @Override
jsedek@14783
   222
    public void propertyChange(PropertyChangeEvent evt) {
jsedek@14783
   223
        if (SeleniumProperties.PORT.equals(evt.getPropertyName())){
jsedek@14783
   224
            action = Action.RELOAD;
jsedek@14783
   225
            RequestProcessor.getDefault().post(instance);
jsedek@14783
   226
        }
jsedek@14783
   227
    }
jsedek@14783
   228
jsedek@14783
   229
    // listen on SeleniumProperties
jsedek@14783
   230
    static PropertyChangeListener getPropertyChangeListener() {
jsedek@14783
   231
        return instance;
jsedek@14783
   232
    }
jsedek@14783
   233
jsedek@14783
   234
    private static enum Action {
jsedek@14783
   235
jsedek@14783
   236
        START, STOP, RESTART, RELOAD
jsedek@14783
   237
    }
jsedek@14783
   238
jsedek@14783
   239
    static void waitAllTasksFinished(){
jsedek@14783
   240
        if (latestTask == null){
jsedek@14783
   241
            return;
jsedek@14783
   242
        }
jsedek@14783
   243
        while (!latestTask.isFinished()){
jsedek@14783
   244
            latestTask.waitFinished();
jsedek@14783
   245
        }
jsedek@14783
   246
    }
jsedek@14783
   247
}