ko-felix-test/src/main/java/org/netbeans/html/ko/felix/test/KnockoutFelixTCKImpl.java
author Jaroslav Tulach <jtulach@netbeans.org>
Tue, 26 Aug 2014 18:13:30 +0200
changeset 838 bdc3d696dd4a
parent 790 30f20d9c0986
child 886 88d62267a0b5
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
 */
jtulach@771
    43
package org.netbeans.html.ko.felix.test;
jaroslav@370
    44
jaroslav@371
    45
import java.io.BufferedReader;
jaroslav@370
    46
import java.io.IOException;
jaroslav@371
    47
import java.io.InputStreamReader;
jaroslav@444
    48
import java.lang.reflect.Constructor;
jaroslav@371
    49
import java.lang.reflect.Method;
jaroslav@371
    50
import java.net.URI;
jaroslav@371
    51
import java.net.URISyntaxException;
jaroslav@371
    52
import java.net.URL;
jaroslav@371
    53
import java.net.URLConnection;
jtulach@771
    54
import java.util.ArrayList;
jtulach@771
    55
import java.util.Collections;
jtulach@771
    56
import java.util.Enumeration;
jtulach@771
    57
import java.util.List;
jaroslav@370
    58
import java.util.Map;
jaroslav@371
    59
import java.util.concurrent.Callable;
jaroslav@574
    60
import java.util.concurrent.Executor;
jaroslav@396
    61
import java.util.concurrent.Executors;
jaroslav@370
    62
import net.java.html.BrwsrCtx;
jaroslav@396
    63
import net.java.html.boot.BrowserBuilder;
jaroslav@371
    64
import net.java.html.js.JavaScriptBody;
jtulach@838
    65
import org.netbeans.html.boot.spi.Fn;
jtulach@838
    66
import org.netbeans.html.context.spi.Contexts;
jtulach@838
    67
import org.netbeans.html.json.spi.Technology;
jtulach@838
    68
import org.netbeans.html.json.spi.Transfer;
jtulach@838
    69
import org.netbeans.html.json.tck.KnockoutTCK;
jaroslav@371
    70
import org.json.JSONException;
jaroslav@371
    71
import org.json.JSONObject;
jaroslav@371
    72
import org.openide.util.lookup.ServiceProvider;
jaroslav@396
    73
import org.osgi.framework.Bundle;
jaroslav@396
    74
import org.osgi.framework.BundleContext;
jaroslav@396
    75
import org.osgi.framework.FrameworkUtil;
jaroslav@370
    76
jaroslav@370
    77
/**
jaroslav@370
    78
 *
jtulach@790
    79
 * @author Jaroslav Tulach
jaroslav@370
    80
 */
jaroslav@371
    81
@ServiceProvider(service = KnockoutTCK.class)
jtulach@771
    82
public class KnockoutFelixTCKImpl extends KnockoutTCK implements Callable<Class[]> {
jaroslav@371
    83
    
jaroslav@371
    84
    private static Fn.Presenter browserContext;
jaroslav@371
    85
jaroslav@396
    86
    public static Class loadOSGiClass(String name, BundleContext ctx) throws Exception {
jaroslav@396
    87
        for (Bundle b : ctx.getBundles()) {
jaroslav@396
    88
            try {
jaroslav@396
    89
                Class<?> osgiClass = b.loadClass(name);
jaroslav@396
    90
                if (osgiClass != null && osgiClass.getClassLoader() != ClassLoader.getSystemClassLoader()) {
jaroslav@396
    91
                    return osgiClass;
jaroslav@396
    92
                }
jaroslav@396
    93
            } catch (ClassNotFoundException cnfe) {
jaroslav@396
    94
                // go on
jaroslav@396
    95
            }
jaroslav@396
    96
        }
jaroslav@396
    97
        throw new IllegalStateException("Cannot load " + name + " from the OSGi container!");
jaroslav@396
    98
    }
jaroslav@396
    99
jaroslav@391
   100
    @Override
jaroslav@391
   101
    public Class[] call() throws Exception {
jaroslav@391
   102
        return testClasses();
jaroslav@371
   103
    }
jaroslav@396
   104
    
jaroslav@396
   105
    public static void start(URI server) throws Exception {
jtulach@771
   106
        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFelixTCKImpl.class).
jaroslav@396
   107
            loadPage(server.toString()).
jaroslav@396
   108
            invoke("initialized");
jaroslav@396
   109
jaroslav@396
   110
        Executors.newSingleThreadExecutor().submit(new Runnable() {
jaroslav@396
   111
            @Override
jaroslav@396
   112
            public void run() {
jaroslav@396
   113
                try {
jtulach@771
   114
                    Bundle[] arr = FrameworkUtil.getBundle(BrowserBuilder.class).getBundleContext().getBundles();
jtulach@771
   115
                    final ClassLoader osgiClassLoader = new AllBundlesLoader(arr);
jtulach@771
   116
                    bb.classloader(osgiClassLoader);
jaroslav@396
   117
                    bb.showAndWait();
jaroslav@396
   118
                } catch (Throwable t) {
jaroslav@396
   119
                    t.printStackTrace();
jaroslav@396
   120
                }
jaroslav@396
   121
            }
jaroslav@396
   122
        });
jaroslav@396
   123
    }
jaroslav@371
   124
jaroslav@391
   125
    public static void initialized() throws Exception {
jtulach@771
   126
        Bundle bundle = FrameworkUtil.getBundle(KnockoutFelixTCKImpl.class);
jaroslav@398
   127
        if (bundle == null) {
jaroslav@398
   128
            throw new IllegalStateException(
jtulach@771
   129
                "Should be loaded from a bundle. But was: " + KnockoutFelixTCKImpl.class.getClassLoader()
jaroslav@398
   130
            );
jaroslav@398
   131
        }
jaroslav@391
   132
        Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(
jtulach@771
   133
            "org.netbeans.html.ko.felix.test.KnockoutFelixIT"
jaroslav@391
   134
        );
jaroslav@396
   135
        Method m = classpathClass.getMethod("initialized", Class.class, Object.class);
jaroslav@391
   136
        browserContext = Fn.activePresenter();
jtulach@771
   137
        m.invoke(null, KnockoutFelixTCKImpl.class, browserContext);
jaroslav@371
   138
    }
jaroslav@371
   139
    
jaroslav@371
   140
    @Override
jaroslav@371
   141
    public BrwsrCtx createContext() {
jaroslav@391
   142
        try {
jaroslav@396
   143
            Class<?> fxCls = loadOSGiClass(
jaroslav@444
   144
                "org.netbeans.html.ko4j.FXContext",
jtulach@771
   145
                FrameworkUtil.getBundle(KnockoutFelixTCKImpl.class).getBundleContext()
jaroslav@396
   146
            );
jaroslav@444
   147
            final Constructor<?> cnstr = fxCls.getConstructor(Fn.Presenter.class);
jaroslav@444
   148
            cnstr.setAccessible(true);
jaroslav@444
   149
            Object fx = cnstr.newInstance(browserContext);
jaroslav@391
   150
            Contexts.Builder cb = Contexts.newBuilder().
jaroslav@391
   151
                register(Technology.class, (Technology)fx, 10).
jaroslav@574
   152
                register(Transfer.class, (Transfer)fx, 10).
jaroslav@574
   153
                register(Executor.class, (Executor)browserContext, 10);
jaroslav@371
   154
//        if (fx.areWebSocketsSupported()) {
jaroslav@371
   155
//            cb.register(WSTransfer.class, fx, 10);
jaroslav@371
   156
//        }
jaroslav@391
   157
            return cb.build();
jaroslav@391
   158
        } catch (Exception ex) {
jaroslav@391
   159
            throw new IllegalStateException(ex);
jaroslav@391
   160
        }
jaroslav@371
   161
    }
jaroslav@371
   162
jaroslav@371
   163
    @Override
jaroslav@371
   164
    public Object createJSON(Map<String, Object> values) {
jaroslav@371
   165
        JSONObject json = new JSONObject();
jaroslav@371
   166
        for (Map.Entry<String, Object> entry : values.entrySet()) {
jaroslav@371
   167
            try {
jaroslav@371
   168
                json.put(entry.getKey(), entry.getValue());
jaroslav@371
   169
            } catch (JSONException ex) {
jaroslav@371
   170
                throw new IllegalStateException(ex);
jaroslav@371
   171
            }
jaroslav@371
   172
        }
jaroslav@371
   173
        return json;
jaroslav@371
   174
    }
jaroslav@371
   175
jaroslav@371
   176
    @Override
jaroslav@371
   177
    @JavaScriptBody(args = { "s", "args" }, body = ""
jaroslav@371
   178
        + "var f = new Function(s); "
jaroslav@371
   179
        + "return f.apply(null, args);"
jaroslav@371
   180
    )
jaroslav@371
   181
    public native Object executeScript(String script, Object[] arguments);
jaroslav@371
   182
jaroslav@371
   183
    @JavaScriptBody(args = {  }, body = 
jaroslav@371
   184
          "var h;"
jaroslav@371
   185
        + "if (!!window && !!window.location && !!window.location.href)\n"
jaroslav@371
   186
        + "  h = window.location.href;\n"
jaroslav@371
   187
        + "else "
jaroslav@371
   188
        + "  h = null;"
jaroslav@371
   189
        + "return h;\n"
jaroslav@371
   190
    )
jaroslav@371
   191
    private static native String findBaseURL();
jaroslav@371
   192
    
jaroslav@371
   193
    @Override
jaroslav@371
   194
    public URI prepareURL(String content, String mimeType, String[] parameters) {
jaroslav@371
   195
        try {
jaroslav@371
   196
            final URL baseURL = new URL(findBaseURL());
jaroslav@371
   197
            StringBuilder sb = new StringBuilder();
jaroslav@371
   198
            sb.append("/dynamic?mimeType=").append(mimeType);
jaroslav@371
   199
            for (int i = 0; i < parameters.length; i++) {
jaroslav@371
   200
                sb.append("&param" + i).append("=").append(parameters[i]);
jaroslav@371
   201
            }
jaroslav@371
   202
            String mangle = content.replace("\n", "%0a")
jaroslav@371
   203
                .replace("\"", "\\\"").replace(" ", "%20");
jaroslav@371
   204
            sb.append("&content=").append(mangle);
jaroslav@371
   205
jaroslav@371
   206
            URL query = new URL(baseURL, sb.toString());
jaroslav@371
   207
            URLConnection c = query.openConnection();
jaroslav@371
   208
            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
jaroslav@371
   209
            URI connectTo = new URI(br.readLine());
jaroslav@371
   210
            return connectTo;
jaroslav@371
   211
        } catch (IOException ex) {
jaroslav@371
   212
            throw new IllegalStateException(ex);
jaroslav@371
   213
        } catch (URISyntaxException ex) {
jaroslav@371
   214
            throw new IllegalStateException(ex);
jaroslav@371
   215
        }
jaroslav@371
   216
    }
jaroslav@371
   217
jaroslav@371
   218
    @Override
jaroslav@371
   219
    public boolean canFailWebSocketTest() {
jtulach@623
   220
        return true;
jaroslav@371
   221
    }
jaroslav@391
   222
jtulach@771
   223
    private static final class AllBundlesLoader extends ClassLoader {
jtulach@771
   224
        private final Bundle[] arr;
jtulach@771
   225
jtulach@771
   226
        public AllBundlesLoader(Bundle[] arr) {
jtulach@771
   227
            super(ClassLoader.getSystemClassLoader().getParent());
jtulach@771
   228
            this.arr = arr;
jtulach@771
   229
        }
jtulach@771
   230
jtulach@771
   231
        @Override
jtulach@771
   232
        public Class<?> loadClass(String name) throws ClassNotFoundException {
jtulach@771
   233
            return loadClass(name, false);
jtulach@771
   234
        }
jtulach@771
   235
jtulach@771
   236
        @Override
jtulach@771
   237
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
jtulach@771
   238
            ClassNotFoundException err = null;
jtulach@771
   239
            for (Bundle b : arr) {
jtulach@771
   240
                try {
jtulach@771
   241
                    Class<?> cls = b.loadClass(name);
jtulach@771
   242
                    if (FrameworkUtil.getBundle(cls) == b) {
jtulach@771
   243
                        return cls;
jtulach@771
   244
                    }
jtulach@771
   245
                } catch (ClassNotFoundException ex) {
jtulach@771
   246
                    err = ex;
jtulach@771
   247
                }
jtulach@771
   248
            }
jtulach@771
   249
            throw err;
jtulach@771
   250
        }
jtulach@771
   251
jtulach@771
   252
        @Override
jtulach@771
   253
        protected URL findResource(String name) {
jtulach@771
   254
            for (Bundle b : arr) {
jtulach@771
   255
                URL r = b.getResource(name);
jtulach@771
   256
                if (r != null) {
jtulach@771
   257
                    return r;
jtulach@771
   258
                }
jtulach@771
   259
            }
jtulach@771
   260
            return null;
jtulach@771
   261
        }
jtulach@771
   262
jtulach@771
   263
        @Override
jtulach@771
   264
        protected Enumeration<URL> findResources(String name) throws IOException {
jtulach@771
   265
            List<URL> ret = new ArrayList<URL>();
jtulach@771
   266
            for (Bundle b : arr) {
jtulach@771
   267
                Enumeration<URL> en = b.getResources(name);
jtulach@771
   268
                if (en != null) while (en.hasMoreElements()) {
jtulach@771
   269
                    URL u = en.nextElement();
jtulach@771
   270
                    ret.add(u);
jtulach@771
   271
                }
jtulach@771
   272
            }
jtulach@771
   273
            return Collections.enumeration(ret);
jtulach@771
   274
        }
jtulach@771
   275
        
jtulach@771
   276
        
jtulach@771
   277
        
jtulach@771
   278
    }
jaroslav@370
   279
}