This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 248918
Collapse All | Expand All

(-)a/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java (-1 / +16 lines)
Lines 52-57 Link Here
52
import net.java.html.boot.BrowserBuilder;
52
import net.java.html.boot.BrowserBuilder;
53
import net.java.html.js.JavaScriptBody;
53
import net.java.html.js.JavaScriptBody;
54
import org.netbeans.html.boot.fx.AbstractFXPresenter;
54
import org.netbeans.html.boot.fx.AbstractFXPresenter;
55
import org.netbeans.html.context.spi.Contexts;
56
import org.netbeans.html.context.spi.Contexts.Id;
55
57
56
/** Utility methods to use {@link WebView} and {@link JavaScriptBody} code
58
/** Utility methods to use {@link WebView} and {@link JavaScriptBody} code
57
 * in existing <em>JavaFX</em> applications.
59
 * in existing <em>JavaFX</em> applications.
Lines 82-87 Link Here
82
     * <p>
84
     * <p>
83
     * This method sets {@link WebView#getUserData()} and {@link #runInBrowser(javafx.scene.web.WebView, java.lang.Runnable)}
85
     * This method sets {@link WebView#getUserData()} and {@link #runInBrowser(javafx.scene.web.WebView, java.lang.Runnable)}
84
     * relies on the value. Please don't alter it.
86
     * relies on the value. Please don't alter it.
87
     * <p>
88
     * Since introduction of {@link Id technology identifiers} the 
89
     * provided <code>args</code> strings are also passed to the 
90
     * {@link BrwsrCtx context} when it is being 
91
     * {@link Contexts#newBuilder(java.lang.Object...) created}
92
     * and can influence the selection
93
     * of available technologies 
94
     * (like {@link org.netbeans.html.json.spi.Technology},
95
     * {@link org.netbeans.html.json.spi.Transfer} or
96
     * {@link org.netbeans.html.json.spi.WSTransfer}).
85
     * 
97
     * 
86
     * @param webView the instance of Web View to tweak
98
     * @param webView the instance of Web View to tweak
87
     * @param url the URL of the HTML page to load into the view
99
     * @param url the URL of the HTML page to load into the view
Lines 94-100 Link Here
94
        Class<?> onPageLoad, String methodName,
106
        Class<?> onPageLoad, String methodName,
95
        String... args
107
        String... args
96
    ) {
108
    ) {
97
        BrowserBuilder.newBrowser(new Load(webView)).
109
        Object[] context = new Object[args.length + 1];
110
        System.arraycopy(args, 0, context, 1, args.length);
111
        context[0] = new Load(webView);
112
        BrowserBuilder.newBrowser(context).
98
            loadPage(url.toExternalForm()).
113
            loadPage(url.toExternalForm()).
99
            loadClass(onPageLoad).
114
            loadClass(onPageLoad).
100
            invoke(methodName, args).
115
            invoke(methodName, args).
(-)a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java (-1 / +11 lines)
Lines 65-70 Link Here
65
import org.netbeans.html.boot.spi.Fn;
65
import org.netbeans.html.boot.spi.Fn;
66
import org.netbeans.html.boot.spi.Fn.Presenter;
66
import org.netbeans.html.boot.spi.Fn.Presenter;
67
import org.netbeans.html.context.spi.Contexts;
67
import org.netbeans.html.context.spi.Contexts;
68
import org.netbeans.html.context.spi.Contexts.Id;
68
import org.netbeans.html.boot.impl.FindResources;
69
import org.netbeans.html.boot.impl.FindResources;
69
import org.netbeans.html.boot.impl.FnContext;
70
import org.netbeans.html.boot.impl.FnContext;
70
import org.netbeans.html.boot.impl.FnUtils;
71
import org.netbeans.html.boot.impl.FnUtils;
Lines 121-126 Link Here
121
    /** Entry method to obtain a new browser builder. Follow by calling 
122
    /** Entry method to obtain a new browser builder. Follow by calling 
122
     * its instance methods like {@link #loadClass(java.lang.Class)} and
123
     * its instance methods like {@link #loadClass(java.lang.Class)} and
123
     * {@link #loadPage(java.lang.String)}.
124
     * {@link #loadPage(java.lang.String)}.
125
     * Since introduction of {@link Id technology identifiers} the 
126
     * provided <code>context</code> objects are also passed to the 
127
     * {@link BrwsrCtx context} when it is being 
128
     * {@link Contexts#newBuilder(java.lang.Object...) created}
129
     * and can influence the selection
130
     * of available technologies 
131
     * (like {@link org.netbeans.html.json.spi.Technology},
132
     * {@link org.netbeans.html.json.spi.Transfer} or
133
     * {@link org.netbeans.html.json.spi.WSTransfer}) by name.
124
     * 
134
     * 
125
     * @param context any instances that should be available to the builder -
135
     * @param context any instances that should be available to the builder -
126
     *   implementation dependant
136
     *   implementation dependant
Lines 301-307 Link Here
301
                    if (browserClass != null) {
311
                    if (browserClass != null) {
302
                        browserClass[0] = newClazz;
312
                        browserClass[0] = newClazz;
303
                    }
313
                    }
304
                    Contexts.Builder cb = Contexts.newBuilder();
314
                    Contexts.Builder cb = Contexts.newBuilder(context);
305
                    if (!Contexts.fillInByProviders(newClazz, cb)) {
315
                    if (!Contexts.fillInByProviders(newClazz, cb)) {
306
                        LOG.log(Level.WARNING, "Using empty technology for {0}", newClazz);
316
                        LOG.log(Level.WARNING, "Using empty technology for {0}", newClazz);
307
                    }
317
                    }
(-)a/context/src/main/java/net/java/html/BrwsrCtx.java (-1 / +7 lines)
Lines 47-52 Link Here
47
import org.netbeans.html.context.impl.CtxAccssr;
47
import org.netbeans.html.context.impl.CtxAccssr;
48
import org.netbeans.html.context.impl.CtxImpl;
48
import org.netbeans.html.context.impl.CtxImpl;
49
import org.netbeans.html.context.spi.Contexts;
49
import org.netbeans.html.context.spi.Contexts;
50
import org.netbeans.html.context.spi.Contexts.Id;
50
51
51
/** Represents context where the <code>net.java.html.json.Model</code>
52
/** Represents context where the <code>net.java.html.json.Model</code>
52
 * and other objects
53
 * and other objects
Lines 54-60 Link Here
54
 * The context is also associated with the actual HTML technology
55
 * The context is also associated with the actual HTML technology
55
 * in the HTML page - there is likely to be different context for 
56
 * in the HTML page - there is likely to be different context for 
56
 * <a href="http://knockoutjs.com">knockout.js</a> and different one
57
 * <a href="http://knockoutjs.com">knockout.js</a> and different one
57
 * for <a href="http://angularjs.org">angular</a>.
58
 * for <a href="http://angularjs.org">angular</a>. Since version 1.1
59
 * the content of contexts can be selected by registering
60
 * implementations under specific
61
 * {@link Id technology identifiers} and requesting them during 
62
 * {@link Contexts#newBuilder(java.lang.Object...) construction} of the
63
 * context.
58
 *
64
 *
59
 * @author Jaroslav Tulach
65
 * @author Jaroslav Tulach
60
 */
66
 */
(-)a/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java (-14 / +41 lines)
Lines 44-51 Link Here
44
44
45
import java.util.ArrayList;
45
import java.util.ArrayList;
46
import java.util.Collections;
46
import java.util.Collections;
47
import java.util.Comparator;
47
import java.util.List;
48
import java.util.List;
48
import net.java.html.BrwsrCtx;
49
import net.java.html.BrwsrCtx;
50
import org.netbeans.html.context.spi.Contexts;
49
51
50
/** Implementation detail. Holds list of technologies for particular
52
/** Implementation detail. Holds list of technologies for particular
51
 * {@link BrwsrCtx}.
53
 * {@link BrwsrCtx}.
Lines 54-66 Link Here
54
 */
56
 */
55
public final class CtxImpl {
57
public final class CtxImpl {
56
    private final List<Bind<?>> techs;
58
    private final List<Bind<?>> techs;
59
    private final Object[] context;
57
    
60
    
58
    public CtxImpl() {
61
    public CtxImpl(Object[] context) {
59
        techs = new ArrayList<Bind<?>>();
62
        this(context, new ArrayList<Bind<?>>());
60
    }
63
    }
61
    
64
    
62
    private CtxImpl(List<Bind<?>> techs) {
65
    private CtxImpl(Object[] context, List<Bind<?>> techs) {
63
        this.techs = techs;
66
        this.techs = techs;
67
        this.context = context;
64
    }
68
    }
65
    
69
    
66
    public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
70
    public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
Lines 74-82 Link Here
74
    }
78
    }
75
79
76
    public BrwsrCtx build() {
80
    public BrwsrCtx build() {
77
        Collections.sort(techs);
81
        Collections.sort(techs, new BindCompare());
78
        final List<Bind<?>> arr = Collections.unmodifiableList(techs);
82
        final List<Bind<?>> arr = Collections.unmodifiableList(techs);
79
        CtxImpl impl = new CtxImpl(arr);
83
        CtxImpl impl = new CtxImpl(context, arr);
80
        BrwsrCtx ctx = CtxAccssr.getDefault().newContext(impl);
84
        BrwsrCtx ctx = CtxAccssr.getDefault().newContext(impl);
81
        return ctx;
85
        return ctx;
82
    }
86
    }
Lines 85-91 Link Here
85
        techs.add(new Bind<Tech>(type, impl, priority));
89
        techs.add(new Bind<Tech>(type, impl, priority));
86
    }
90
    }
87
    
91
    
88
    private static final class Bind<Tech> implements Comparable<Bind<?>> {
92
    private static final class Bind<Tech> {
89
        private final Class<Tech> clazz;
93
        private final Class<Tech> clazz;
90
        private final Tech impl;
94
        private final Tech impl;
91
        private final int priority;
95
        private final int priority;
Lines 97-112 Link Here
97
        }
101
        }
98
102
99
        @Override
103
        @Override
100
        public int compareTo(Bind<?> o) {
101
            if (priority != o.priority) {
102
                return priority - o.priority;
103
            }
104
            return clazz.getName().compareTo(o.clazz.getName());
105
        }
106
107
        @Override
108
        public String toString() {
104
        public String toString() {
109
            return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
105
            return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
110
        }
106
        }
111
    }
107
    }
108
    
109
    private final class BindCompare implements Comparator<Bind<?>> {
110
        boolean isPrefered(Bind<?> b) {
111
            final Class<?> implClazz = b.impl.getClass();
112
            Contexts.Id id = implClazz.getAnnotation(Contexts.Id.class);
113
            if (id == null) {
114
                return false;
115
            }
116
            for (String v : id.value()) {
117
                for (Object c : context) {
118
                    if (v.equals(c)) {
119
                        return true;
120
                    }
121
                }
122
            }
123
            return false;
124
        }
125
        
126
        @Override
127
        public int compare(Bind<?> o1, Bind<?> o2) {
128
            boolean p1 = isPrefered(o1);
129
            boolean p2 = isPrefered(o2);
130
            if (p1 != p2) {
131
                return p1 ? -1 : 1;
132
            }
133
            if (o1.priority != o2.priority) {
134
                return o1.priority - o2.priority;
135
            }
136
            return o1.clazz.getName().compareTo(o2.clazz.getName());
137
        }
138
    } // end of BindCompare
112
}
139
}
(-)a/context/src/main/java/org/netbeans/html/context/spi/Contexts.java (-4 / +38 lines)
Lines 42-47 Link Here
42
 */
42
 */
43
package org.netbeans.html.context.spi;
43
package org.netbeans.html.context.spi;
44
44
45
import java.lang.annotation.ElementType;
46
import java.lang.annotation.Retention;
47
import java.lang.annotation.RetentionPolicy;
48
import java.lang.annotation.Target;
45
import java.util.ServiceLoader;
49
import java.util.ServiceLoader;
46
import net.java.html.BrwsrCtx;
50
import net.java.html.BrwsrCtx;
47
import org.netbeans.html.context.impl.CtxImpl;
51
import org.netbeans.html.context.impl.CtxImpl;
Lines 59-69 Link Here
59
63
60
    /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the
64
    /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the
61
     * end call the {@link Builder#build()} method to generate the context.
65
     * end call the {@link Builder#build()} method to generate the context.
62
     *
66
     * 
67
     * @param context instances of various classes or names of {@link Id technologies} 
68
     *    to be preferred and used in the built {@link BrwsrCtx context}.
69
     * @return new instance of the builder
70
     * @since 1.1
71
     */
72
    public static Builder newBuilder(Object... context) {
73
        return new Builder(context);
74
    }
75
    /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the
76
     * end call the {@link Builder#build()} method to generate the context.
77
     * Simply calls {@link #newBuilder(java.lang.Object...) newBuilder(new Object[0])}.
78
     * 
63
     * @return new instance of the builder
79
     * @return new instance of the builder
64
     */
80
     */
65
    public static Builder newBuilder() {
81
    public static Builder newBuilder() {
66
        return new Builder();
82
        return newBuilder(new Object[0]);
67
    }
83
    }
68
84
69
    /** Seeks for the specified technology in the provided context.
85
    /** Seeks for the specified technology in the provided context.
Lines 118-123 Link Here
118
        }
134
        }
119
        return found;
135
        return found;
120
    }
136
    }
137
    
138
    /** Identifies the technologies passed to {@link Builder context builder}
139
     * by a name. Each implementation of a technology 
140
     * {@link Builder#register(java.lang.Class, java.lang.Object, int) registered into a context}
141
     * can be annotated with a name (or multiple names). Such implementation
142
     * will later be 
143
     * {@link Contexts#fillInByProviders(java.lang.Class, org.netbeans.html.context.spi.Contexts.Builder)  preferred during lookup}
144
     * if their name(s) has been requested in when 
145
     * {@link Contexts#newBuilder(java.lang.Object...)  creating a context}.
146
     * @since 1.1
147
     */
148
    @Retention(RetentionPolicy.RUNTIME)
149
    @Target(ElementType.TYPE)
150
    public @interface Id {
151
        /** Identifier(s) for the implementation. */
152
        public String[] value();
153
    }
121
154
122
    /** Implementors of various HTML technologies should
155
    /** Implementors of various HTML technologies should
123
     * register their implementation via <code>org.openide.util.lookup.ServiceProvider</code>, so
156
     * register their implementation via <code>org.openide.util.lookup.ServiceProvider</code>, so
Lines 152-160 Link Here
152
     * @author Jaroslav Tulach
185
     * @author Jaroslav Tulach
153
     */
186
     */
154
    public static final class Builder {
187
    public static final class Builder {
155
        private final CtxImpl impl = new CtxImpl();
188
        private final CtxImpl impl;
156
189
157
        Builder() {
190
        public Builder(Object[] context) {
191
            this.impl = new CtxImpl(context);
158
        }
192
        }
159
        
193
        
160
        /** Registers new technology into the context. Each technology is
194
        /** Registers new technology into the context. Each technology is
(-)a/context/src/test/java/net/java/html/BrwsrCtxTest.java (+45 lines)
Lines 44-49 Link Here
44
44
45
import org.netbeans.html.context.spi.Contexts;
45
import org.netbeans.html.context.spi.Contexts;
46
import static org.testng.Assert.*;
46
import static org.testng.Assert.*;
47
import org.testng.annotations.Test;
47
48
48
/**
49
/**
49
 *
50
 *
Lines 72-75 Link Here
72
        assertTrue(arr[0], "Runnable was executed");
73
        assertTrue(arr[0], "Runnable was executed");
73
    }
74
    }
74
    
75
    
76
    
77
    @Test public void defaultOrderOfRegistrations() {
78
        BrwsrCtx ctx = registerRs(Contexts.newBuilder());
79
        Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass();
80
        assertEquals(clazz, R1.class, "R1 is registered at value 10");
81
    }
82
    
83
    @Test public void preferOne() {
84
        BrwsrCtx ctx = registerRs(Contexts.newBuilder("one"));
85
        Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass();
86
        assertEquals(clazz, R1.class, "R1 is registered at value 10");
87
    }
88
89
    @Test public void preferTwo() {
90
        BrwsrCtx ctx = registerRs(Contexts.newBuilder("two"));
91
        Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass();
92
        assertEquals(clazz, R2.class, "R2 is preferred");
93
    }
94
95
    @Test public void preferBoth() {
96
        BrwsrCtx ctx = registerRs(Contexts.newBuilder("one", "two"));
97
        Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass();
98
        assertEquals(clazz, R1.class, "R1 is registered at value 10");
99
    }
100
    
101
    private static BrwsrCtx registerRs(Contexts.Builder b) {
102
        b.register(Runnable.class, new R1(), 10);
103
        b.register(Runnable.class, new R2(), 20);
104
        return b.build();
105
    }
106
107
    @Contexts.Id("one")
108
    static final class R1 implements Runnable {
109
        @Override
110
        public void run() {
111
        }
112
    }
113
    @Contexts.Id("two")
114
    static final class R2 implements Runnable {
115
        @Override
116
        public void run() {
117
        }
118
    }
119
    
75
}
120
}
(-)a/json/src/main/java/org/netbeans/html/json/spi/Technology.java (+7 lines)
Lines 45-54 Link Here
45
import net.java.html.BrwsrCtx;
45
import net.java.html.BrwsrCtx;
46
import net.java.html.json.Model;
46
import net.java.html.json.Model;
47
import net.java.html.json.Models;
47
import net.java.html.json.Models;
48
import org.netbeans.html.context.spi.Contexts.Id;
48
49
49
/** An implementation of a binding between model classes (see {@link Model})
50
/** An implementation of a binding between model classes (see {@link Model})
50
 * and particular technology like <a href="http://knockoutjs.com">knockout.js</a>
51
 * and particular technology like <a href="http://knockoutjs.com">knockout.js</a>
51
 * in a browser window, etc.
52
 * in a browser window, etc.
53
 * Since introduction of {@link Id technology identifiers} one can choose between
54
 * different background implementations to handle the conversion and
55
 * communication requests. The currently known provider is
56
 * <code>org.netbeans.html:ko4j</code> module which registers 
57
 * a <a href="http://knockoutjs.com" target="_blank">knockout.js</a>
58
 * implementation called <b>ko4j</b>.
52
 *
59
 *
53
 * @author Jaroslav Tulach
60
 * @author Jaroslav Tulach
54
 */
61
 */
(-)a/json/src/main/java/org/netbeans/html/json/spi/Transfer.java (+8 lines)
Lines 45-53 Link Here
45
import java.io.IOException;
45
import java.io.IOException;
46
import java.io.InputStream;
46
import java.io.InputStream;
47
import org.netbeans.html.context.spi.Contexts.Builder;
47
import org.netbeans.html.context.spi.Contexts.Builder;
48
import org.netbeans.html.context.spi.Contexts.Id;
48
49
49
/** A {@link Builder service provider interface} responsible for 
50
/** A {@link Builder service provider interface} responsible for 
50
 * conversion of JSON objects to Java ones and vice-versa.
51
 * conversion of JSON objects to Java ones and vice-versa.
52
 * Since introduction of {@link Id technology identifiers} one can choose between
53
 * different background implementations to handle the conversion and
54
 * communication requests. The known providers include
55
 * <code>org.netbeans.html:ko4j</code> module which registers 
56
 * a native browser implementation called <b>xhr</b>, and a
57
 * <code>org.netbeans.html:ko-ws-tyrus</code> module which registers 
58
 * Java based implementation named <b>tyrus</b>.
51
 *
59
 *
52
 * @author Jaroslav Tulach
60
 * @author Jaroslav Tulach
53
 */
61
 */
(-)a/json/src/main/java/org/netbeans/html/json/spi/WSTransfer.java (-1 / +9 lines)
Lines 44-52 Link Here
44
44
45
import net.java.html.BrwsrCtx;
45
import net.java.html.BrwsrCtx;
46
import org.netbeans.html.context.spi.Contexts.Provider;
46
import org.netbeans.html.context.spi.Contexts.Provider;
47
import org.netbeans.html.context.spi.Contexts.Id;
47
48
48
/** Interface for providers of WebSocket protocol. Register into a 
49
/** Interface for providers of WebSocket protocol. Register into a 
49
 * {@link BrwsrCtx context} in your own {@link Provider}
50
 * {@link BrwsrCtx context} in your own {@link Provider}.
51
 * Since introduction of {@link Id technology identifiers} one can choose between
52
 * different background implementations to handle the conversion and
53
 * communication requests. The known providers include
54
 * <code>org.netbeans.html:ko4j</code> module which registers 
55
 * a native browser implementation called <b>websocket</b>, and a
56
 * <code>org.netbeans.html:ko-ws-tyrus</code> module which registers 
57
 * Java based implementation named <b>tyrus</b>.
50
 *
58
 *
51
 * @author Jaroslav Tulach
59
 * @author Jaroslav Tulach
52
 * @param <WebSocket> internal implementation type representing the socket
60
 * @param <WebSocket> internal implementation type representing the socket
(-)a/ko-felix-test/src/main/java/org/netbeans/html/ko/felix/test/KnockoutFelixTCKImpl.java (-9 / +14 lines)
Lines 46-51 Link Here
46
import java.io.IOException;
46
import java.io.IOException;
47
import java.io.InputStreamReader;
47
import java.io.InputStreamReader;
48
import java.lang.reflect.Constructor;
48
import java.lang.reflect.Constructor;
49
import java.lang.reflect.InvocationTargetException;
49
import java.lang.reflect.Method;
50
import java.lang.reflect.Method;
50
import java.net.URI;
51
import java.net.URI;
51
import java.net.URISyntaxException;
52
import java.net.URISyntaxException;
Lines 140-155 Link Here
140
    @Override
141
    @Override
141
    public BrwsrCtx createContext() {
142
    public BrwsrCtx createContext() {
142
        try {
143
        try {
143
            Class<?> fxCls = loadOSGiClass(
144
                "org.netbeans.html.ko4j.FXContext",
145
                FrameworkUtil.getBundle(KnockoutFelixTCKImpl.class).getBundleContext()
146
            );
147
            final Constructor<?> cnstr = fxCls.getConstructor(Fn.Presenter.class);
148
            cnstr.setAccessible(true);
149
            Object fx = cnstr.newInstance(browserContext);
150
            Contexts.Builder cb = Contexts.newBuilder().
144
            Contexts.Builder cb = Contexts.newBuilder().
151
                register(Technology.class, (Technology)fx, 10).
145
                register(Technology.class, (Technology)osgiInstance("KOTech"), 10).
152
                register(Transfer.class, (Transfer)fx, 10).
146
                register(Transfer.class, (Transfer)osgiInstance("KOTransfer"), 10).
153
                register(Executor.class, (Executor)browserContext, 10);
147
                register(Executor.class, (Executor)browserContext, 10);
154
//        if (fx.areWebSocketsSupported()) {
148
//        if (fx.areWebSocketsSupported()) {
155
//            cb.register(WSTransfer.class, fx, 10);
149
//            cb.register(WSTransfer.class, fx, 10);
Lines 160-165 Link Here
160
        }
154
        }
161
    }
155
    }
162
156
157
    private Object osgiInstance(String simpleName) throws IllegalAccessException, SecurityException, IllegalArgumentException, Exception, NoSuchMethodException, InstantiationException, InvocationTargetException {
158
        Class<?> fxCls = loadOSGiClass(
159
                "org.netbeans.html.ko4j." + simpleName,
160
                FrameworkUtil.getBundle(KnockoutFelixTCKImpl.class).getBundleContext()
161
        );
162
        final Constructor<?> cnstr = fxCls.getDeclaredConstructor();
163
        cnstr.setAccessible(true);
164
        Object fx = cnstr.newInstance();
165
        return fx;
166
    }
167
163
    @Override
168
    @Override
164
    public Object createJSON(Map<String, Object> values) {
169
    public Object createJSON(Map<String, Object> values) {
165
        JSONObject json = new JSONObject();
170
        JSONObject json = new JSONObject();
(-)a/ko-osgi-test/src/main/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxTCKImpl.java (-9 / +13 lines)
Lines 46-51 Link Here
46
import java.io.IOException;
46
import java.io.IOException;
47
import java.io.InputStreamReader;
47
import java.io.InputStreamReader;
48
import java.lang.reflect.Constructor;
48
import java.lang.reflect.Constructor;
49
import java.lang.reflect.InvocationTargetException;
49
import java.lang.reflect.Method;
50
import java.lang.reflect.Method;
50
import java.net.URI;
51
import java.net.URI;
51
import java.net.URISyntaxException;
52
import java.net.URISyntaxException;
Lines 135-150 Link Here
135
    @Override
136
    @Override
136
    public BrwsrCtx createContext() {
137
    public BrwsrCtx createContext() {
137
        try {
138
        try {
138
            Class<?> fxCls = loadOSGiClass(
139
                "org.netbeans.html.ko4j.FXContext",
140
                FrameworkUtil.getBundle(KnockoutEquinoxTCKImpl.class).getBundleContext()
141
            );
142
            final Constructor<?> cnstr = fxCls.getConstructor(Fn.Presenter.class);
143
            cnstr.setAccessible(true);
144
            Object fx = cnstr.newInstance(browserContext);
145
            Contexts.Builder cb = Contexts.newBuilder().
139
            Contexts.Builder cb = Contexts.newBuilder().
146
                register(Technology.class, (Technology)fx, 10).
140
                register(Technology.class, (Technology)osgiInstance("KOTech"), 10).
147
                register(Transfer.class, (Transfer)fx, 10).
141
                register(Transfer.class, (Transfer)osgiInstance("KOTransfer"), 10).
148
                register(Executor.class, (Executor)browserContext, 10);
142
                register(Executor.class, (Executor)browserContext, 10);
149
//        if (fx.areWebSocketsSupported()) {
143
//        if (fx.areWebSocketsSupported()) {
150
//            cb.register(WSTransfer.class, fx, 10);
144
//            cb.register(WSTransfer.class, fx, 10);
Lines 154-159 Link Here
154
            throw new IllegalStateException(ex);
148
            throw new IllegalStateException(ex);
155
        }
149
        }
156
    }
150
    }
151
    private Object osgiInstance(String simpleName) throws IllegalAccessException, SecurityException, IllegalArgumentException, Exception, NoSuchMethodException, InstantiationException, InvocationTargetException {
152
        Class<?> fxCls = loadOSGiClass(
153
                "org.netbeans.html.ko4j." + simpleName,
154
                FrameworkUtil.getBundle(KnockoutEquinoxTCKImpl.class).getBundleContext()
155
        );
156
        final Constructor<?> cnstr = fxCls.getDeclaredConstructor();
157
        cnstr.setAccessible(true);
158
        Object fx = cnstr.newInstance();
159
        return fx;
160
    }
157
161
158
    @Override
162
    @Override
159
    public Object createJSON(Map<String, Object> values) {
163
    public Object createJSON(Map<String, Object> values) {
(-)a/ko-ws-tyrus/src/main/java/org/netbeans/html/wstyrus/TyrusContext.java (+1 lines)
Lines 82-87 Link Here
82
 *
82
 *
83
 * @author Jaroslav Tulach
83
 * @author Jaroslav Tulach
84
 */
84
 */
85
@Contexts.Id("tyrus")
85
@ServiceProvider(service = Contexts.Provider.class)
86
@ServiceProvider(service = Contexts.Provider.class)
86
public final class TyrusContext 
87
public final class TyrusContext 
87
implements Contexts.Provider, WSTransfer<Comm>, Transfer {
88
implements Contexts.Provider, WSTransfer<Comm>, Transfer {
(-)a/ko4j/src/main/java/org/netbeans/html/ko4j/KO4J.java (-14 / +39 lines)
Lines 42-48 Link Here
42
 */
42
 */
43
package org.netbeans.html.ko4j;
43
package org.netbeans.html.ko4j;
44
44
45
import java.util.logging.Logger;
45
import net.java.html.json.Model;
46
import net.java.html.json.Model;
47
import net.java.html.json.OnReceive;
46
import org.netbeans.html.boot.spi.Fn;
48
import org.netbeans.html.boot.spi.Fn;
47
import org.netbeans.html.context.spi.Contexts;
49
import org.netbeans.html.context.spi.Contexts;
48
import org.netbeans.html.context.spi.Contexts.Provider;
50
import org.netbeans.html.context.spi.Contexts.Provider;
Lines 54-88 Link Here
54
/** Support for <a href="http://knockoutjs.com">knockout.js</a>
56
/** Support for <a href="http://knockoutjs.com">knockout.js</a>
55
 * and its Java binding via {@link Model model classes}.
57
 * and its Java binding via {@link Model model classes}.
56
 * Registers {@link Provider}, so {@link java.util.ServiceLoader} can find it.
58
 * Registers {@link Provider}, so {@link java.util.ServiceLoader} can find it.
59
 * The provider registers following technologies:
60
 * <ul>
61
 * <li><b>ko4j</b> - bindings for <a href="http://knockoutjs.com">knockout.js</a>
62
 *   and the classes generated by the {@link Model} annotation.
63
 * </li>
64
 * <li><b>xhr</b> - <a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest</a>
65
 *   based implementation for <em>REST</em> calls 
66
 *   (<b>GET</b>, <b>PUT</b>, <b>POST</b>, <b>DELETE</b> methods) 
67
 *   for {@link OnReceive} annotation.
68
 * </li>
69
 * <li><b>websocket</b> - 
70
 *   native browser <a href="http://www.w3.org/TR/websockets/">websockets</a>
71
 *   based implementation for {@link OnReceive} annotation and its <b>WebSocket</b>
72
 *   subprotocol.
73
 * </li>
74
 * </ul>
57
 *
75
 *
58
 * @author Jaroslav Tulach
76
 * @author Jaroslav Tulach
59
 * @since 0.7
77
 * @since 0.7
60
 */
78
 */
61
@ServiceProvider(service = Provider.class)
79
@ServiceProvider(service = Provider.class)
62
public final class KO4J implements Provider {
80
public final class KO4J implements Provider {
63
    private final Fn.Presenter presenter;
81
    static final Logger LOG = Logger.getLogger(KOSockets.class.getName());
64
    private FXContext c;
82
    private KOTech ko4j;
83
    private KOTransfer trans;
84
    private KOSockets socks;
65
    
85
    
66
    public KO4J() {
86
    public KO4J() {
67
        this(null);
87
        this(null);
68
    }
88
    }
69
    
89
90
    @Deprecated
70
    public KO4J(Fn.Presenter presenter) {
91
    public KO4J(Fn.Presenter presenter) {
71
        this.presenter = presenter;
72
    }
73
    
74
    private FXContext getKO() {
75
        if (c == null) {
76
            c = new FXContext(presenter == null ? Fn.activePresenter() : presenter);
77
        }
78
        return c;
79
    }
92
    }
80
    
93
    
81
    /** Return instance of the knockout.js for Java technology.
94
    /** Return instance of the knockout.js for Java technology.
82
     * @return non-null instance
95
     * @return non-null instance
83
     */
96
     */
84
    public Technology knockout() {
97
    public Technology knockout() {
85
        return getKO();
98
        if (ko4j == null) {
99
            ko4j = new KOTech();
100
        }
101
        return ko4j;
86
    }
102
    }
87
    
103
    
88
    /** Browser based implementation of transfer interface. Uses
104
    /** Browser based implementation of transfer interface. Uses
Lines 91-97 Link Here
91
     * @return non-null instance
107
     * @return non-null instance
92
     */
108
     */
93
    public Transfer transfer() {
109
    public Transfer transfer() {
94
        return getKO();
110
        if (trans == null) {
111
            trans = new KOTransfer();
112
        }
113
        return trans;
95
    }
114
    }
96
    
115
    
97
    /** Returns browser based implementation of websocket transfer.
116
    /** Returns browser based implementation of websocket transfer.
Lines 102-108 Link Here
102
     *   <code>WebSocket</code> object in the browser
121
     *   <code>WebSocket</code> object in the browser
103
     */
122
     */
104
    public WSTransfer<?> websockets() {
123
    public WSTransfer<?> websockets() {
105
        return getKO().areWebSocketsSupported() ? getKO() : null;
124
        if (!KOSockets.areWebSocketsSupported()) {
125
            return null;
126
        }
127
        if (socks == null) {
128
            socks = new KOSockets();
129
        }
130
        return socks;
106
    }
131
    }
107
132
108
    /** Registers technologies at position 100:
133
    /** Registers technologies at position 100:
(-)a/ko4j/src/main/java/org/netbeans/html/ko4j/FXContext.java (-160 / +9 lines)
Lines 42-61 Link Here
42
 */
42
 */
43
package org.netbeans.html.ko4j;
43
package org.netbeans.html.ko4j;
44
44
45
import java.io.ByteArrayOutputStream;
45
import net.java.html.js.JavaScriptBody;
46
import java.io.Closeable;
46
import org.netbeans.html.context.spi.Contexts;
47
import java.io.IOException;
48
import java.io.InputStream;
49
import java.io.InputStreamReader;
50
import java.io.Reader;
51
import java.net.URL;
52
import java.util.logging.Logger;
53
import org.netbeans.html.boot.spi.Fn;
54
import org.netbeans.html.json.spi.FunctionBinding;
55
import org.netbeans.html.json.spi.JSONCall;
47
import org.netbeans.html.json.spi.JSONCall;
56
import org.netbeans.html.json.spi.PropertyBinding;
57
import org.netbeans.html.json.spi.Technology;
58
import org.netbeans.html.json.spi.Transfer;
59
import org.netbeans.html.json.spi.WSTransfer;
48
import org.netbeans.html.json.spi.WSTransfer;
60
49
61
/** This is an implementation package - just
50
/** This is an implementation package - just
Lines 65-198 Link Here
65
 *
54
 *
66
 * @author Jaroslav Tulach
55
 * @author Jaroslav Tulach
67
 */
56
 */
68
final class FXContext
57
@Contexts.Id("websocket")
69
implements Technology.BatchInit<Object>, Technology.ValueMutated<Object>,
58
final class KOSockets
70
Transfer, WSTransfer<LoadWS> {
59
implements WSTransfer<LoadWS> {
71
    static final Logger LOG = Logger.getLogger(FXContext.class.getName());
60
    KOSockets() {
72
    private Object[] jsObjects;
73
    private int jsIndex;
74
75
    public FXContext(Fn.Presenter browserContext) {
76
    }
61
    }
77
    
62
    
78
    @Override
63
    @Override
79
    public Object wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
80
        String[] propNames = new String[propArr.length];
81
        boolean[] propReadOnly = new boolean[propArr.length];
82
        Object[] propValues = new Object[propArr.length];
83
        for (int i = 0; i < propNames.length; i++) {
84
            propNames[i] = propArr[i].getPropertyName();
85
            propReadOnly[i] = propArr[i].isReadOnly();
86
            propValues[i] = propArr[i].getValue();
87
        }
88
        String[] funcNames = new String[funcArr.length];
89
        for (int i = 0; i < funcNames.length; i++) {
90
            funcNames[i] = funcArr[i].getFunctionName();
91
        }
92
        Object ret = getJSObject();
93
        Knockout.wrapModel(ret, model, 
94
            propNames, propReadOnly, propValues, propArr,
95
            funcNames, funcArr
96
        );
97
        return ret;
98
    }
99
    
100
    private Object getJSObject() {
101
        int len = 64;
102
        if (jsObjects != null && jsIndex < (len = jsObjects.length)) {
103
            return jsObjects[jsIndex++];
104
        }
105
        jsObjects = Knockout.allocJS(len * 2);
106
        jsIndex = 1;
107
        return jsObjects[0];
108
    }
109
    
110
    @Override
111
    public Object wrapModel(Object model) {
112
        throw new UnsupportedOperationException();
113
    }
114
115
    @Override
116
    public void bind(PropertyBinding b, Object model, Object data) {
117
        throw new UnsupportedOperationException();
118
    }
119
120
    @Override
121
    public void valueHasMutated(Object data, String propertyName) {
122
        Knockout.valueHasMutated(data, propertyName, null, null);
123
    }
124
    
125
    @Override
126
    public void valueHasMutated(Object data, String propertyName, Object oldValue, Object newValue) {
127
        Knockout.valueHasMutated(data, propertyName, oldValue, newValue);
128
    }
129
130
    @Override
131
    public void expose(FunctionBinding fb, Object model, Object d) {
132
        throw new UnsupportedOperationException();
133
    }
134
135
    @Override
136
    public void applyBindings(Object data) {
137
        Knockout.applyBindings(data);
138
    }
139
140
    @Override
141
    public Object wrapArray(Object[] arr) {
142
        return arr;
143
    }
144
145
    @Override
146
    public void extract(Object obj, String[] props, Object[] values) {
147
        LoadJSON.extractJSON(obj, props, values);
148
    }
149
150
    @Override
151
    public void loadJSON(final JSONCall call) {
152
        if (call.isJSONP()) {
153
            String me = LoadJSON.createJSONP(call);
154
            LoadJSON.loadJSONP(call.composeURL(me), me);
155
        } else {
156
            String data = null;
157
            if (call.isDoOutput()) {
158
                try {
159
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
160
                    call.writeData(bos);
161
                    data = new String(bos.toByteArray(), "UTF-8");
162
                } catch (IOException ex) {
163
                    call.notifyError(ex);
164
                }
165
            }
166
            LoadJSON.loadJSON(call.composeURL(null), call, call.getMethod(), data);
167
        }
168
    }
169
170
    @Override
171
    public <M> M toModel(Class<M> modelClass, Object data) {
172
        return modelClass.cast(Knockout.toModel(data));
173
    }
174
175
    @Override
176
    public Object toJSON(InputStream is) throws IOException {
177
        StringBuilder sb = new StringBuilder();
178
        InputStreamReader r = new InputStreamReader(is);
179
        for (;;) {
180
            int ch = r.read();
181
            if (ch == -1) {
182
                break;
183
            }
184
            sb.append((char)ch);
185
        }
186
        return LoadJSON.parse(sb.toString());
187
    }
188
189
    @Override
190
    public void runSafe(final Runnable r) {
191
        LOG.warning("Technology.runSafe has been deprecated. Use BrwsrCtx.execute!");
192
        r.run();
193
    }
194
195
    @Override
196
    public LoadWS open(String url, JSONCall onReply) {
64
    public LoadWS open(String url, JSONCall onReply) {
197
        return new LoadWS(onReply, url);
65
        return new LoadWS(onReply, url);
198
    }
66
    }
Lines 207-233 Link Here
207
        socket.close();
75
        socket.close();
208
    }
76
    }
209
77
210
    boolean areWebSocketsSupported() {
78
    @JavaScriptBody(args = {}, body = "if (window['WebSocket']) return true; else return false;")
211
        return Knockout.areWebSocketsSupported();
79
    static final boolean areWebSocketsSupported() {
80
        return false;
212
    }
81
    }
213
214
    private static final class TrueFn extends Fn implements Fn.Presenter {
215
        @Override
216
        public Object invoke(Object thiz, Object... args) throws Exception {
217
            return true;
218
        }
219
220
        @Override
221
        public Fn defineFn(String code, String... names) {
222
            return this;
223
        }
224
225
        @Override
226
        public void displayPage(URL page, Runnable onPageLoad) {
227
        }
228
229
        @Override
230
        public void loadScript(Reader code) throws Exception {
231
        }
232
    } // end of TrueFn
233
}
82
}
(-)a/ko4j/src/main/java/org/netbeans/html/ko4j/FXContext.java (-100 / +11 lines)
Lines 42-62 Link Here
42
 */
42
 */
43
package org.netbeans.html.ko4j;
43
package org.netbeans.html.ko4j;
44
44
45
import java.io.ByteArrayOutputStream;
45
import org.netbeans.html.context.spi.Contexts;
46
import java.io.Closeable;
47
import java.io.IOException;
48
import java.io.InputStream;
49
import java.io.InputStreamReader;
50
import java.io.Reader;
51
import java.net.URL;
52
import java.util.logging.Logger;
53
import org.netbeans.html.boot.spi.Fn;
54
import org.netbeans.html.json.spi.FunctionBinding;
46
import org.netbeans.html.json.spi.FunctionBinding;
55
import org.netbeans.html.json.spi.JSONCall;
56
import org.netbeans.html.json.spi.PropertyBinding;
47
import org.netbeans.html.json.spi.PropertyBinding;
57
import org.netbeans.html.json.spi.Technology;
48
import org.netbeans.html.json.spi.Technology;
58
import org.netbeans.html.json.spi.Transfer;
49
import static org.netbeans.html.ko4j.KO4J.LOG;
59
import org.netbeans.html.json.spi.WSTransfer;
60
50
61
/** This is an implementation package - just
51
/** This is an implementation package - just
62
 * include its JAR on classpath and use official {@link Context} API
52
 * include its JAR on classpath and use official {@link Context} API
Lines 65-78 Link Here
65
 *
55
 *
66
 * @author Jaroslav Tulach
56
 * @author Jaroslav Tulach
67
 */
57
 */
68
final class FXContext
58
@Contexts.Id("ko4j")
69
implements Technology.BatchInit<Object>, Technology.ValueMutated<Object>,
59
final class KOTech
70
Transfer, WSTransfer<LoadWS> {
60
implements Technology.BatchInit<Object>, Technology.ValueMutated<Object> {
71
    static final Logger LOG = Logger.getLogger(FXContext.class.getName());
72
    private Object[] jsObjects;
61
    private Object[] jsObjects;
73
    private int jsIndex;
62
    private int jsIndex;
74
63
75
    public FXContext(Fn.Presenter browserContext) {
64
    public KOTech() {
76
    }
65
    }
77
    
66
    
78
    @Override
67
    @Override
Lines 141-233 Link Here
141
    public Object wrapArray(Object[] arr) {
130
    public Object wrapArray(Object[] arr) {
142
        return arr;
131
        return arr;
143
    }
132
    }
144
133
    
145
    @Override
134
    @Override
146
    public void extract(Object obj, String[] props, Object[] values) {
135
    public void runSafe(final Runnable r) {
147
        LoadJSON.extractJSON(obj, props, values);
136
        LOG.warning("Technology.runSafe has been deprecated. Use BrwsrCtx.execute!");
148
    }
137
        r.run();
149
138
    }    
150
    @Override
151
    public void loadJSON(final JSONCall call) {
152
        if (call.isJSONP()) {
153
            String me = LoadJSON.createJSONP(call);
154
            LoadJSON.loadJSONP(call.composeURL(me), me);
155
        } else {
156
            String data = null;
157
            if (call.isDoOutput()) {
158
                try {
159
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
160
                    call.writeData(bos);
161
                    data = new String(bos.toByteArray(), "UTF-8");
162
                } catch (IOException ex) {
163
                    call.notifyError(ex);
164
                }
165
            }
166
            LoadJSON.loadJSON(call.composeURL(null), call, call.getMethod(), data);
167
        }
168
    }
169
139
170
    @Override
140
    @Override
171
    public <M> M toModel(Class<M> modelClass, Object data) {
141
    public <M> M toModel(Class<M> modelClass, Object data) {
172
        return modelClass.cast(Knockout.toModel(data));
142
        return modelClass.cast(Knockout.toModel(data));
173
    }
143
    }
174
175
    @Override
176
    public Object toJSON(InputStream is) throws IOException {
177
        StringBuilder sb = new StringBuilder();
178
        InputStreamReader r = new InputStreamReader(is);
179
        for (;;) {
180
            int ch = r.read();
181
            if (ch == -1) {
182
                break;
183
            }
184
            sb.append((char)ch);
185
        }
186
        return LoadJSON.parse(sb.toString());
187
    }
188
189
    @Override
190
    public void runSafe(final Runnable r) {
191
        LOG.warning("Technology.runSafe has been deprecated. Use BrwsrCtx.execute!");
192
        r.run();
193
    }
194
195
    @Override
196
    public LoadWS open(String url, JSONCall onReply) {
197
        return new LoadWS(onReply, url);
198
    }
199
200
    @Override
201
    public void send(LoadWS socket, JSONCall data) {
202
        socket.send(data);
203
    }
204
205
    @Override
206
    public void close(LoadWS socket) {
207
        socket.close();
208
    }
209
210
    boolean areWebSocketsSupported() {
211
        return Knockout.areWebSocketsSupported();
212
    }
213
214
    private static final class TrueFn extends Fn implements Fn.Presenter {
215
        @Override
216
        public Object invoke(Object thiz, Object... args) throws Exception {
217
            return true;
218
        }
219
220
        @Override
221
        public Fn defineFn(String code, String... names) {
222
            return this;
223
        }
224
225
        @Override
226
        public void displayPage(URL page, Runnable onPageLoad) {
227
        }
228
229
        @Override
230
        public void loadScript(Reader code) throws Exception {
231
        }
232
    } // end of TrueFn
233
}
144
}
(-)a/ko4j/src/main/java/org/netbeans/html/ko4j/FXContext.java (-134 / +5 lines)
Lines 43-62 Link Here
43
package org.netbeans.html.ko4j;
43
package org.netbeans.html.ko4j;
44
44
45
import java.io.ByteArrayOutputStream;
45
import java.io.ByteArrayOutputStream;
46
import java.io.Closeable;
47
import java.io.IOException;
46
import java.io.IOException;
48
import java.io.InputStream;
47
import java.io.InputStream;
49
import java.io.InputStreamReader;
48
import java.io.InputStreamReader;
50
import java.io.Reader;
49
import org.netbeans.html.context.spi.Contexts;
51
import java.net.URL;
52
import java.util.logging.Logger;
53
import org.netbeans.html.boot.spi.Fn;
54
import org.netbeans.html.json.spi.FunctionBinding;
55
import org.netbeans.html.json.spi.JSONCall;
50
import org.netbeans.html.json.spi.JSONCall;
56
import org.netbeans.html.json.spi.PropertyBinding;
57
import org.netbeans.html.json.spi.Technology;
58
import org.netbeans.html.json.spi.Transfer;
51
import org.netbeans.html.json.spi.Transfer;
59
import org.netbeans.html.json.spi.WSTransfer;
60
52
61
/** This is an implementation package - just
53
/** This is an implementation package - just
62
 * include its JAR on classpath and use official {@link Context} API
54
 * include its JAR on classpath and use official {@link Context} API
Lines 65-148 Link Here
65
 *
57
 *
66
 * @author Jaroslav Tulach
58
 * @author Jaroslav Tulach
67
 */
59
 */
68
final class FXContext
60
@Contexts.Id("xhr")
69
implements Technology.BatchInit<Object>, Technology.ValueMutated<Object>,
61
final class KOTransfer
70
Transfer, WSTransfer<LoadWS> {
62
implements Transfer {
71
    static final Logger LOG = Logger.getLogger(FXContext.class.getName());
63
    KOTransfer() {
72
    private Object[] jsObjects;
73
    private int jsIndex;
74
75
    public FXContext(Fn.Presenter browserContext) {
76
    }
64
    }
77
    
65
    
78
    @Override
66
    @Override
79
    public Object wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
80
        String[] propNames = new String[propArr.length];
81
        boolean[] propReadOnly = new boolean[propArr.length];
82
        Object[] propValues = new Object[propArr.length];
83
        for (int i = 0; i < propNames.length; i++) {
84
            propNames[i] = propArr[i].getPropertyName();
85
            propReadOnly[i] = propArr[i].isReadOnly();
86
            propValues[i] = propArr[i].getValue();
87
        }
88
        String[] funcNames = new String[funcArr.length];
89
        for (int i = 0; i < funcNames.length; i++) {
90
            funcNames[i] = funcArr[i].getFunctionName();
91
        }
92
        Object ret = getJSObject();
93
        Knockout.wrapModel(ret, model, 
94
            propNames, propReadOnly, propValues, propArr,
95
            funcNames, funcArr
96
        );
97
        return ret;
98
    }
99
    
100
    private Object getJSObject() {
101
        int len = 64;
102
        if (jsObjects != null && jsIndex < (len = jsObjects.length)) {
103
            return jsObjects[jsIndex++];
104
        }
105
        jsObjects = Knockout.allocJS(len * 2);
106
        jsIndex = 1;
107
        return jsObjects[0];
108
    }
109
    
110
    @Override
111
    public Object wrapModel(Object model) {
112
        throw new UnsupportedOperationException();
113
    }
114
115
    @Override
116
    public void bind(PropertyBinding b, Object model, Object data) {
117
        throw new UnsupportedOperationException();
118
    }
119
120
    @Override
121
    public void valueHasMutated(Object data, String propertyName) {
122
        Knockout.valueHasMutated(data, propertyName, null, null);
123
    }
124
    
125
    @Override
126
    public void valueHasMutated(Object data, String propertyName, Object oldValue, Object newValue) {
127
        Knockout.valueHasMutated(data, propertyName, oldValue, newValue);
128
    }
129
130
    @Override
131
    public void expose(FunctionBinding fb, Object model, Object d) {
132
        throw new UnsupportedOperationException();
133
    }
134
135
    @Override
136
    public void applyBindings(Object data) {
137
        Knockout.applyBindings(data);
138
    }
139
140
    @Override
141
    public Object wrapArray(Object[] arr) {
142
        return arr;
143
    }
144
145
    @Override
146
    public void extract(Object obj, String[] props, Object[] values) {
67
    public void extract(Object obj, String[] props, Object[] values) {
147
        LoadJSON.extractJSON(obj, props, values);
68
        LoadJSON.extractJSON(obj, props, values);
148
    }
69
    }
Lines 168-178 Link Here
168
    }
89
    }
169
90
170
    @Override
91
    @Override
171
    public <M> M toModel(Class<M> modelClass, Object data) {
172
        return modelClass.cast(Knockout.toModel(data));
173
    }
174
175
    @Override
176
    public Object toJSON(InputStream is) throws IOException {
92
    public Object toJSON(InputStream is) throws IOException {
177
        StringBuilder sb = new StringBuilder();
93
        StringBuilder sb = new StringBuilder();
178
        InputStreamReader r = new InputStreamReader(is);
94
        InputStreamReader r = new InputStreamReader(is);
Lines 185-233 Link Here
185
        }
101
        }
186
        return LoadJSON.parse(sb.toString());
102
        return LoadJSON.parse(sb.toString());
187
    }
103
    }
188
189
    @Override
190
    public void runSafe(final Runnable r) {
191
        LOG.warning("Technology.runSafe has been deprecated. Use BrwsrCtx.execute!");
192
        r.run();
193
    }
194
195
    @Override
196
    public LoadWS open(String url, JSONCall onReply) {
197
        return new LoadWS(onReply, url);
198
    }
199
200
    @Override
201
    public void send(LoadWS socket, JSONCall data) {
202
        socket.send(data);
203
    }
204
205
    @Override
206
    public void close(LoadWS socket) {
207
        socket.close();
208
    }
209
210
    boolean areWebSocketsSupported() {
211
        return Knockout.areWebSocketsSupported();
212
    }
213
214
    private static final class TrueFn extends Fn implements Fn.Presenter {
215
        @Override
216
        public Object invoke(Object thiz, Object... args) throws Exception {
217
            return true;
218
        }
219
220
        @Override
221
        public Fn defineFn(String code, String... names) {
222
            return this;
223
        }
224
225
        @Override
226
        public void displayPage(URL page, Runnable onPageLoad) {
227
        }
228
229
        @Override
230
        public void loadScript(Reader code) throws Exception {
231
        }
232
    } // end of TrueFn
233
}
104
}
(-)a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java (-5 lines)
Lines 153-161 Link Here
153
    static Object toModel(Object wrapper) {
153
    static Object toModel(Object wrapper) {
154
        return toModelImpl(wrapper);
154
        return toModelImpl(wrapper);
155
    }
155
    }
156
    
157
    @JavaScriptBody(args = {}, body = "if (window['WebSocket']) return true; else return false;")
158
    static final boolean areWebSocketsSupported() {
159
        return false;
160
    }
161
}
156
}
(-)a/ko4j/src/test/java/org/netbeans/html/ko4j/KnockoutFXTest.java (-6 / +5 lines)
Lines 66-72 Link Here
66
import org.netbeans.html.json.spi.WSTransfer;
66
import org.netbeans.html.json.spi.WSTransfer;
67
import org.netbeans.html.json.tck.KOTest;
67
import org.netbeans.html.json.tck.KOTest;
68
import org.netbeans.html.json.tck.KnockoutTCK;
68
import org.netbeans.html.json.tck.KnockoutTCK;
69
import org.netbeans.html.boot.impl.FnContext;
70
import org.openide.util.lookup.ServiceProvider;
69
import org.openide.util.lookup.ServiceProvider;
71
import org.testng.Assert;
70
import org.testng.Assert;
72
import static org.testng.Assert.*;
71
import static org.testng.Assert.*;
Lines 154-165 Link Here
154
    
153
    
155
    @Override
154
    @Override
156
    public BrwsrCtx createContext() {
155
    public BrwsrCtx createContext() {
157
        FXContext fx = new FXContext(browserContext);
156
        KO4J ko4j = new KO4J();
158
        Contexts.Builder cb = Contexts.newBuilder().
157
        Contexts.Builder cb = Contexts.newBuilder().
159
            register(Technology.class, fx, 10).
158
            register(Technology.class, ko4j.knockout(), 10).
160
            register(Transfer.class, fx, 10);
159
            register(Transfer.class, ko4j.transfer(), 10);
161
        if (fx.areWebSocketsSupported()) {
160
        if (ko4j.websockets() != null) {
162
            cb.register(WSTransfer.class, fx, 10);
161
            cb.register(WSTransfer.class, ko4j.websockets(), 10);
163
        }
162
        }
164
        cb.register(Executor.class, (Executor)browserContext, 10);
163
        cb.register(Executor.class, (Executor)browserContext, 10);
165
        cb.register(Fn.Presenter.class, browserContext, 10);
164
        cb.register(Fn.Presenter.class, browserContext, 10);
(-)a/src/main/javadoc/overview.html (+21 lines)
Lines 75-80 Link Here
75
         yet the application code can be written in Java.
75
         yet the application code can be written in Java.
76
        </p>
76
        </p>
77
        
77
        
78
        <h3>What's New in Version 1.1?</h3>
79
        
80
        <p>
81
            The content of a {@link net.java.html.BrwsrCtx context}
82
            can be selected by registering implementations under specific
83
            {@link org.netbeans.html.context.spi.Contexts.Id technology identifiers} 
84
            and requesting them during 
85
            {@link org.netbeans.html.context.spi.Contexts#newBuilder(java.lang.Object...) construction} 
86
            of the context. <code>org.netbeans.html:ko4j</code> module's implementation
87
            offers <b>ko4j</b>, <b>xhr</b> and <b>websocket</b> identifiers
88
            for its registered services 
89
            (e.g. {@link org.netbeans.html.json.spi.Technology},
90
            {@link org.netbeans.html.json.spi.Transfer} and
91
            {@link org.netbeans.html.json.spi.WSTransfer}).
92
            <code>org.netbeans.html:ko-ws-tyrus</code>
93
            module registers its 
94
            {@link org.netbeans.html.json.spi.Transfer Java based JSON} and 
95
            {@link org.netbeans.html.json.spi.WSTransfer WebSocket} implementations
96
            under the name <b>tyrus</b>.
97
        </p>
98
        
78
        <h3>What's New in Version 1.0?</h3>
99
        <h3>What's New in Version 1.0?</h3>
79
        
100
        
80
        <p>
101
        <p>

Return to bug 248918