ko-osgi-test/src/test/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxIT.java
author Jaroslav Tulach <jtulach@netbeans.org>
Tue, 26 Aug 2014 18:13:30 +0200
changeset 838 bdc3d696dd4a
parent 790 30f20d9c0986
child 1018 82ec9872793a
permissions -rw-r--r--
During the API review process (bug 246133) the reviewers decided that in order to include html4j to NetBeans Platform, we need to stop using org.apidesign namespace and switch to NetBeans one. Repackaging all SPI packages into org.netbeans.html.smthng.spi.
jaroslav@370
     1
/**
jaroslav@370
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jaroslav@370
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jaroslav@370
     5
 *
jaroslav@370
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@370
     7
 * Other names may be trademarks of their respective owners.
jaroslav@370
     8
 *
jaroslav@370
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@370
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@370
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@370
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@370
    13
 * License. You can obtain a copy of the License at
jaroslav@370
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@370
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@370
    16
 * specific language governing permissions and limitations under the
jaroslav@370
    17
 * License.  When distributing the software, include this License Header
jaroslav@370
    18
 * Notice in each file and include the License file at
jaroslav@370
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@370
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@370
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@370
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@370
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@370
    24
 * your own identifying information:
jaroslav@370
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@370
    26
 *
jaroslav@370
    27
 * Contributor(s):
jaroslav@370
    28
 *
jaroslav@370
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@551
    30
 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
jaroslav@370
    31
 *
jaroslav@370
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@370
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@370
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@370
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@370
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@370
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@370
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@370
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@370
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@370
    41
 * made subject to such option by the copyright holder.
jaroslav@370
    42
 */
jaroslav@370
    43
package org.netbeans.html.ko.osgi.test;
jaroslav@370
    44
jaroslav@396
    45
import java.io.Closeable;
jaroslav@370
    46
import java.io.File;
jaroslav@370
    47
import java.io.IOException;
jaroslav@371
    48
import java.lang.annotation.Annotation;
jaroslav@371
    49
import java.lang.reflect.Method;
jaroslav@371
    50
import java.net.URI;
jaroslav@371
    51
import java.util.ArrayList;
jaroslav@370
    52
import java.util.HashMap;
jaroslav@371
    53
import java.util.List;
jaroslav@370
    54
import java.util.Map;
jaroslav@370
    55
import java.util.ServiceLoader;
jaroslav@371
    56
import java.util.concurrent.Callable;
jaroslav@370
    57
import java.util.jar.JarFile;
jaroslav@389
    58
import java.util.logging.Level;
jaroslav@389
    59
import java.util.logging.Logger;
jtulach@838
    60
import org.netbeans.html.boot.spi.Fn;
jtulach@838
    61
import org.netbeans.html.json.tck.KOTest;
jtulach@838
    62
import org.netbeans.html.json.tck.KnockoutTCK;
jaroslav@370
    63
import org.osgi.framework.Bundle;
jaroslav@370
    64
import org.osgi.framework.BundleException;
jaroslav@371
    65
import org.osgi.framework.Constants;
jaroslav@370
    66
import org.osgi.framework.launch.Framework;
jaroslav@370
    67
import org.osgi.framework.launch.FrameworkFactory;
jaroslav@391
    68
import static org.testng.Assert.assertNotNull;
jaroslav@391
    69
import static org.testng.Assert.fail;
jaroslav@371
    70
import org.testng.annotations.AfterClass;
jaroslav@371
    71
import org.testng.annotations.Factory;
jaroslav@370
    72
jaroslav@370
    73
/**
jaroslav@370
    74
 *
jtulach@790
    75
 * @author Jaroslav Tulach
jaroslav@370
    76
 */
jaroslav@391
    77
public class KnockoutEquinoxIT {
jaroslav@391
    78
    private static final Logger LOG = Logger.getLogger(KnockoutEquinoxIT.class.getName());
jaroslav@370
    79
    private static Framework framework;
jaroslav@371
    80
    private static File dir;
jaroslav@371
    81
    static Framework framework() throws Exception {
jaroslav@371
    82
        if (framework != null) {
jaroslav@371
    83
            return framework;
jaroslav@371
    84
        }
jaroslav@370
    85
        for (FrameworkFactory ff : ServiceLoader.load(FrameworkFactory.class)) {
jaroslav@391
    86
            
jaroslav@391
    87
            String basedir = System.getProperty("basedir");
jaroslav@391
    88
            assertNotNull("basedir preperty provided", basedir);
jaroslav@391
    89
            File target = new File(basedir, "target");
jaroslav@391
    90
            dir = new File(target, "osgi");
jaroslav@391
    91
            dir.mkdirs();
jaroslav@391
    92
            
jaroslav@470
    93
            Map<String,String> config = new HashMap<String, String>();
jaroslav@371
    94
            config.put(Constants.FRAMEWORK_STORAGE, dir.getPath());
jaroslav@371
    95
            config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true");
jaroslav@390
    96
            config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "sun.misc,"
jaroslav@390
    97
                + "javafx.application,"
jtulach@743
    98
                + "javafx.beans,"
jaroslav@390
    99
                + "javafx.beans.property,"
jaroslav@390
   100
                + "javafx.beans.value,"
jaroslav@390
   101
                + "javafx.collections,"
jaroslav@390
   102
                + "javafx.concurrent,"
jaroslav@390
   103
                + "javafx.event,"
jaroslav@390
   104
                + "javafx.geometry,"
jaroslav@390
   105
                + "javafx.scene,"
jaroslav@390
   106
                + "javafx.scene.control,"
jtulach@743
   107
                + "javafx.scene.image,"
jaroslav@390
   108
                + "javafx.scene.layout,"
jaroslav@390
   109
                + "javafx.scene.text,"
jaroslav@390
   110
                + "javafx.scene.web,"
jaroslav@390
   111
                + "javafx.stage,"
jaroslav@390
   112
                + "javafx.util,"
jaroslav@390
   113
                + "netscape.javascript"
jaroslav@390
   114
            );
jaroslav@393
   115
            config.put("osgi.hook.configurators.include", "org.netbeans.html.equinox.agentclass.AgentHook");
jaroslav@370
   116
            framework = ff.newFramework(config);
jaroslav@370
   117
            framework.init();
jaroslav@370
   118
            loadClassPathBundles(framework);
jaroslav@370
   119
            framework.start();
jaroslav@371
   120
            for (Bundle b : framework.getBundleContext().getBundles()) {
jaroslav@389
   121
                try {
jaroslav@401
   122
                    if (b.getSymbolicName().contains("equinox-agentclass-hook")) {
jaroslav@401
   123
                        continue;
jaroslav@401
   124
                    }
jaroslav@401
   125
                    if (b.getSymbolicName().contains("grizzly.websockets-server")) {
jaroslav@401
   126
                        continue;
jaroslav@401
   127
                    }
jaroslav@389
   128
                    b.start();
jaroslav@389
   129
                    LOG.log(Level.INFO, "Started {0}", b.getSymbolicName());
jaroslav@389
   130
                } catch (BundleException ex) {
jaroslav@389
   131
                    LOG.log(Level.WARNING, "Cannot start bundle " + b.getSymbolicName(), ex);
jaroslav@389
   132
                }
jaroslav@371
   133
            }
jaroslav@371
   134
            return framework;
jaroslav@370
   135
        }
jaroslav@370
   136
        fail("No OSGi framework in the path");
jaroslav@371
   137
        return null;
jaroslav@370
   138
    }
jaroslav@371
   139
    
jaroslav@371
   140
    @AfterClass public static void cleanUp() throws Exception {
jaroslav@371
   141
        if (framework != null) framework.stop();
jaroslav@371
   142
        clearUpDir(dir);
jaroslav@371
   143
    }
jaroslav@371
   144
    private static void clearUpDir(File dir) {
jaroslav@371
   145
        if (dir.isDirectory()) {
jaroslav@371
   146
            for (File f : dir.listFiles()) {
jaroslav@371
   147
                clearUpDir(f);
jaroslav@371
   148
            }
jaroslav@371
   149
        }
jaroslav@371
   150
        dir.delete();
jaroslav@371
   151
    }
jaroslav@371
   152
    
jaroslav@371
   153
    
jaroslav@370
   154
jaroslav@370
   155
    private static void loadClassPathBundles(Framework f) throws IOException, BundleException {
jaroslav@370
   156
        for (String jar : System.getProperty("java.class.path").split(File.pathSeparator)) {
jaroslav@370
   157
            File file = new File(jar);
jaroslav@370
   158
            if (!file.isFile()) {
jaroslav@390
   159
                LOG.info("Not loading " + file);
jaroslav@370
   160
                continue;
jaroslav@370
   161
            }
jaroslav@370
   162
            JarFile jf = new JarFile(file);
jaroslav@370
   163
            final String name = jf.getManifest().getMainAttributes().getValue("Bundle-SymbolicName");
jaroslav@370
   164
            jf.close();
jaroslav@370
   165
            if (name != null) {
jaroslav@370
   166
                if (name.contains("org.eclipse.osgi")) {
jaroslav@370
   167
                    continue;
jaroslav@370
   168
                }
jaroslav@371
   169
                if (name.contains("testng")) {
jaroslav@371
   170
                    continue;
jaroslav@371
   171
                }
jaroslav@371
   172
                final String path = "reference:" + file.toURI().toString();
jaroslav@398
   173
                try {
jaroslav@398
   174
                    Bundle b = f.getBundleContext().installBundle(path);
jaroslav@398
   175
                } catch (BundleException ex) {
jaroslav@398
   176
                    LOG.log(Level.WARNING, "Cannot install " + file, ex);
jaroslav@398
   177
                }
jaroslav@370
   178
            }
jaroslav@370
   179
        }
jaroslav@370
   180
    }
jaroslav@370
   181
    
jaroslav@396
   182
    private static Class<?> loadOSGiClass(Class<?> c) throws Exception {
jaroslav@396
   183
        return KnockoutEquinoxTCKImpl.loadOSGiClass(c.getName(), KnockoutEquinoxIT.framework().getBundleContext());
jaroslav@370
   184
    }
jaroslav@371
   185
    
jaroslav@371
   186
    private static Class<?> browserClass;
jaroslav@396
   187
    private static Object browserContext;
jaroslav@371
   188
    
jaroslav@371
   189
    @Factory public static Object[] compatibilityTests() throws Exception {
jaroslav@396
   190
        Class<?> tck = loadOSGiClass(KnockoutTCK.class);
jaroslav@396
   191
        Class<?> peer = loadOSGiClass(KnockoutEquinoxTCKImpl.class);
jaroslav@371
   192
        // initialize the TCK
jaroslav@371
   193
        Callable<Class[]> inst = (Callable<Class[]>) peer.newInstance();
jaroslav@371
   194
        
jaroslav@371
   195
        Class[] arr = inst.call();
jaroslav@371
   196
        for (int i = 0; i < arr.length; i++) {
jaroslav@371
   197
            if (arr[i].getClassLoader() == ClassLoader.getSystemClassLoader()) {
jaroslav@371
   198
                fail("Should be an OSGi class: " + arr[i]);
jaroslav@371
   199
            }
jaroslav@371
   200
        }
jaroslav@371
   201
        
jaroslav@371
   202
        URI uri = DynamicHTTP.initServer();
jaroslav@371
   203
jaroslav@396
   204
        Method start = peer.getMethod("start", URI.class);
jaroslav@396
   205
        start.invoke(null, uri);
jaroslav@371
   206
        
jaroslav@371
   207
        ClassLoader l = getClassLoader();
jaroslav@371
   208
        List<Object> res = new ArrayList<Object>();
jaroslav@371
   209
        for (int i = 0; i < arr.length; i++) {
jaroslav@393
   210
            seekKOTests(arr[i], res);
jaroslav@371
   211
        }
jaroslav@371
   212
        return res.toArray();
jaroslav@371
   213
    }
jaroslav@371
   214
jaroslav@371
   215
    private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
jaroslav@371
   216
        Class<? extends Annotation> koTest =
jaroslav@371
   217
            c.getClassLoader().loadClass(KOTest.class.getName()).
jaroslav@371
   218
            asSubclass(Annotation.class);
jaroslav@371
   219
        for (Method m : c.getMethods()) {
jaroslav@371
   220
            if (m.getAnnotation(koTest) != null) {
jaroslav@371
   221
                res.add(new KOFx(browserContext, m));
jaroslav@371
   222
            }
jaroslav@371
   223
        }
jaroslav@371
   224
    }
jaroslav@371
   225
jaroslav@371
   226
    static synchronized ClassLoader getClassLoader() throws InterruptedException {
jaroslav@371
   227
        while (browserClass == null) {
jaroslav@391
   228
            KnockoutEquinoxIT.class.wait();
jaroslav@371
   229
        }
jaroslav@371
   230
        return browserClass.getClassLoader();
jaroslav@371
   231
    }
jaroslav@371
   232
    
jaroslav@396
   233
    public static synchronized void initialized(Class<?> browserCls, Object presenter) throws Exception {
jaroslav@371
   234
        browserClass = browserCls;
jaroslav@396
   235
        browserContext = presenter;
jaroslav@391
   236
        KnockoutEquinoxIT.class.notifyAll();
jaroslav@371
   237
    }
jaroslav@396
   238
jaroslav@396
   239
    static Closeable activateInOSGi(Object presenter) throws Exception {
jaroslav@396
   240
        Class<?> presenterClass = loadOSGiClass(Fn.Presenter.class);
jaroslav@396
   241
        Class<?> fnClass = loadOSGiClass(Fn.class);
jaroslav@396
   242
        Method m = fnClass.getMethod("activate", presenterClass);
jaroslav@396
   243
        return (Closeable) m.invoke(null, presenter);
jaroslav@396
   244
    }
jaroslav@370
   245
}