jaroslav@123
|
1 |
/**
|
jaroslav@358
|
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
jaroslav@123
|
3 |
*
|
jaroslav@358
|
4 |
* Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
jaroslav@123
|
5 |
*
|
jaroslav@358
|
6 |
* Oracle and Java are registered trademarks of Oracle and/or its affiliates.
|
jaroslav@358
|
7 |
* Other names may be trademarks of their respective owners.
|
jaroslav@123
|
8 |
*
|
jaroslav@358
|
9 |
* The contents of this file are subject to the terms of either the GNU
|
jaroslav@358
|
10 |
* General Public License Version 2 only ("GPL") or the Common
|
jaroslav@358
|
11 |
* Development and Distribution License("CDDL") (collectively, the
|
jaroslav@358
|
12 |
* "License"). You may not use this file except in compliance with the
|
jaroslav@358
|
13 |
* License. You can obtain a copy of the License at
|
jaroslav@358
|
14 |
* http://www.netbeans.org/cddl-gplv2.html
|
jaroslav@358
|
15 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
|
jaroslav@358
|
16 |
* specific language governing permissions and limitations under the
|
jaroslav@358
|
17 |
* License. When distributing the software, include this License Header
|
jaroslav@358
|
18 |
* Notice in each file and include the License file at
|
jaroslav@358
|
19 |
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
|
jaroslav@358
|
20 |
* particular file as subject to the "Classpath" exception as provided
|
jaroslav@358
|
21 |
* by Oracle in the GPL Version 2 section of the License file that
|
jaroslav@358
|
22 |
* accompanied this code. If applicable, add the following below the
|
jaroslav@358
|
23 |
* License Header, with the fields enclosed by brackets [] replaced by
|
jaroslav@358
|
24 |
* your own identifying information:
|
jaroslav@358
|
25 |
* "Portions Copyrighted [year] [name of copyright owner]"
|
jaroslav@358
|
26 |
*
|
jaroslav@358
|
27 |
* Contributor(s):
|
jaroslav@358
|
28 |
*
|
jaroslav@358
|
29 |
* The Original Software is NetBeans. The Initial Developer of the Original
|
jaroslav@358
|
30 |
* Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
|
jaroslav@358
|
31 |
*
|
jaroslav@358
|
32 |
* If you wish your version of this file to be governed by only the CDDL
|
jaroslav@358
|
33 |
* or only the GPL Version 2, indicate your decision by adding
|
jaroslav@358
|
34 |
* "[Contributor] elects to include this software in this distribution
|
jaroslav@358
|
35 |
* under the [CDDL or GPL Version 2] license." If you do not indicate a
|
jaroslav@358
|
36 |
* single choice of license, a recipient has the option to distribute
|
jaroslav@358
|
37 |
* your version of this file under either the CDDL, the GPL Version 2 or
|
jaroslav@358
|
38 |
* to extend the choice of license to its licensees as provided above.
|
jaroslav@358
|
39 |
* However, if you add GPL Version 2 code and therefore, elected the GPL
|
jaroslav@358
|
40 |
* Version 2 license, then the option applies only if the new code is
|
jaroslav@358
|
41 |
* made subject to such option by the copyright holder.
|
jaroslav@123
|
42 |
*/
|
jaroslav@123
|
43 |
package org.apidesign.html.boot.spi;
|
jaroslav@123
|
44 |
|
jaroslav@322
|
45 |
import java.io.Closeable;
|
jaroslav@349
|
46 |
import java.io.InputStream;
|
jaroslav@349
|
47 |
import java.io.InputStreamReader;
|
jaroslav@163
|
48 |
import java.io.Reader;
|
jaroslav@123
|
49 |
import java.net.URL;
|
jaroslav@349
|
50 |
import java.util.HashMap;
|
jaroslav@349
|
51 |
import java.util.HashSet;
|
jaroslav@349
|
52 |
import java.util.Map;
|
jaroslav@349
|
53 |
import java.util.Set;
|
jaroslav@322
|
54 |
import net.java.html.js.JavaScriptBody;
|
jaroslav@362
|
55 |
import org.netbeans.html.boot.impl.FnContext;
|
jaroslav@123
|
56 |
|
jaroslav@289
|
57 |
/** Represents single JavaScript function that can be invoked.
|
jaroslav@289
|
58 |
* Created via {@link Presenter#defineFn(java.lang.String, java.lang.String...)}.
|
jaroslav@123
|
59 |
*
|
jaroslav@123
|
60 |
* @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
|
jaroslav@123
|
61 |
*/
|
jaroslav@123
|
62 |
public abstract class Fn {
|
jaroslav@288
|
63 |
private final Presenter presenter;
|
jaroslav@288
|
64 |
|
jaroslav@289
|
65 |
/**
|
jaroslav@289
|
66 |
* @deprecated Ineffective as of 0.6.
|
jaroslav@289
|
67 |
* Provide a presenter via {@link #Fn(org.apidesign.html.boot.spi.Fn.Presenter)}
|
jaroslav@289
|
68 |
* constructor
|
jaroslav@289
|
69 |
*/
|
jaroslav@289
|
70 |
@Deprecated
|
jaroslav@289
|
71 |
protected Fn() {
|
jaroslav@289
|
72 |
this(null);
|
jaroslav@289
|
73 |
}
|
jaroslav@289
|
74 |
|
jaroslav@289
|
75 |
/** Creates new function object and associates it with given presenter.
|
jaroslav@289
|
76 |
*
|
jaroslav@289
|
77 |
* @param presenter the browser presenter associated with this function
|
jaroslav@289
|
78 |
* @since 0.6
|
jaroslav@289
|
79 |
*/
|
jaroslav@288
|
80 |
protected Fn(Presenter presenter) {
|
jaroslav@288
|
81 |
this.presenter = presenter;
|
jaroslav@288
|
82 |
}
|
jaroslav@289
|
83 |
|
jaroslav@289
|
84 |
/** True, if currently active presenter is the same as presenter this
|
jaroslav@289
|
85 |
* function has been created for via {@link #Fn(org.apidesign.html.boot.spi.Fn.Presenter)}.
|
jaroslav@289
|
86 |
*
|
jaroslav@289
|
87 |
* @return true, if proper presenter is used
|
jaroslav@289
|
88 |
*/
|
jaroslav@288
|
89 |
public final boolean isValid() {
|
jaroslav@309
|
90 |
return FnContext.currentPresenter() == presenter;
|
jaroslav@288
|
91 |
}
|
jaroslav@288
|
92 |
|
jaroslav@323
|
93 |
/** Helper method to check if the provided instance is valid function.
|
jaroslav@323
|
94 |
* Checks if the parameter is non-null and if so, does {@link #isValid()}
|
jaroslav@323
|
95 |
* check.
|
jaroslav@323
|
96 |
*
|
jaroslav@323
|
97 |
* @param fnOrNull function or <code>null</code>
|
jaroslav@323
|
98 |
* @return true if the parameter is non-null and valid
|
jaroslav@323
|
99 |
* @since 0.7
|
jaroslav@323
|
100 |
*/
|
jaroslav@323
|
101 |
public static boolean isValid(Fn fnOrNull) {
|
jaroslav@323
|
102 |
return fnOrNull != null && fnOrNull.isValid();
|
jaroslav@323
|
103 |
}
|
jaroslav@323
|
104 |
|
jaroslav@323
|
105 |
/** Helper method to find current presenter and ask it to define new
|
jaroslav@323
|
106 |
* function by calling {@link Presenter#defineFn(java.lang.String, java.lang.String...)}.
|
jaroslav@323
|
107 |
*
|
jaroslav@323
|
108 |
* @param caller the class who wishes to define the function
|
jaroslav@323
|
109 |
* @param code the body of the function (can reference <code>this</code> and <code>names</code> variables)
|
jaroslav@323
|
110 |
* @param names names of individual parameters
|
jaroslav@323
|
111 |
* @return the function object that can be {@link Fn#invoke(java.lang.Object, java.lang.Object...) invoked}
|
jaroslav@323
|
112 |
* @since 0.7
|
jaroslav@323
|
113 |
*/
|
jaroslav@323
|
114 |
public static Fn define(Class<?> caller, String code, String... names) {
|
jaroslav@323
|
115 |
return FnContext.currentPresenter().defineFn(code, names);
|
jaroslav@323
|
116 |
}
|
jaroslav@323
|
117 |
|
jaroslav@349
|
118 |
private static final Map<String,Set<Presenter>> LOADED = new HashMap<String, Set<Presenter>>();
|
jaroslav@349
|
119 |
public static Fn preload(final Fn fn, final Class<?> caller, final String resource) {
|
jaroslav@349
|
120 |
return new Fn() {
|
jaroslav@349
|
121 |
@Override
|
jaroslav@349
|
122 |
public Object invoke(Object thiz, Object... args) throws Exception {
|
jaroslav@349
|
123 |
final Presenter p = FnContext.currentPresenter();
|
jaroslav@349
|
124 |
Set<Presenter> there = LOADED.get(resource);
|
jaroslav@349
|
125 |
if (there == null) {
|
jaroslav@349
|
126 |
there = new HashSet<Presenter>();
|
jaroslav@349
|
127 |
LOADED.put(resource, there);
|
jaroslav@349
|
128 |
}
|
jaroslav@349
|
129 |
if (there.add(p)) {
|
jaroslav@349
|
130 |
InputStream is = caller.getClassLoader().getResourceAsStream(resource);
|
jaroslav@349
|
131 |
try {
|
jaroslav@349
|
132 |
InputStreamReader r = new InputStreamReader(is, "UTF-8");
|
jaroslav@349
|
133 |
p.loadScript(r);
|
jaroslav@349
|
134 |
} finally {
|
jaroslav@349
|
135 |
is.close();
|
jaroslav@349
|
136 |
}
|
jaroslav@349
|
137 |
}
|
jaroslav@349
|
138 |
return fn.invoke(thiz, args);
|
jaroslav@349
|
139 |
}
|
jaroslav@349
|
140 |
};
|
jaroslav@349
|
141 |
}
|
jaroslav@349
|
142 |
|
jaroslav@322
|
143 |
/** The currently active presenter.
|
jaroslav@322
|
144 |
*
|
jaroslav@322
|
145 |
* @return the currently active presenter or <code>null</code>
|
jaroslav@322
|
146 |
* @since 0.7
|
jaroslav@322
|
147 |
*/
|
jaroslav@322
|
148 |
public static Presenter activePresenter() {
|
jaroslav@322
|
149 |
return FnContext.currentPresenter();
|
jaroslav@322
|
150 |
}
|
jaroslav@322
|
151 |
|
jaroslav@322
|
152 |
/** Activates given presenter. Used by the code generated by
|
jaroslav@322
|
153 |
* {@link JavaScriptBody} annotation:
|
jaroslav@322
|
154 |
* <pre>
|
jaroslav@322
|
155 |
* try ({@link Closeable} c = Fn.activate(presenter)) {
|
jaroslav@322
|
156 |
* doCallsInPresenterContext();
|
jaroslav@322
|
157 |
* }
|
jaroslav@322
|
158 |
* </pre>
|
jaroslav@322
|
159 |
*
|
jaroslav@322
|
160 |
* @param p the presenter that should be active until closable is closed
|
jaroslav@322
|
161 |
* @return the closable to close
|
jaroslav@322
|
162 |
* @since 0.7
|
jaroslav@322
|
163 |
*/
|
jaroslav@322
|
164 |
public static Closeable activate(Presenter p) {
|
jaroslav@322
|
165 |
return FnContext.activate(p);
|
jaroslav@322
|
166 |
}
|
jaroslav@322
|
167 |
|
jaroslav@289
|
168 |
/** Invokes the defined function with specified <code>this</code> and
|
jaroslav@289
|
169 |
* appropriate arguments.
|
jaroslav@289
|
170 |
*
|
jaroslav@289
|
171 |
* @param thiz the meaning of <code>this</code> inside of the JavaScript
|
jaroslav@289
|
172 |
* function - can be <code>null</code>
|
jaroslav@289
|
173 |
* @param args arguments for the function
|
jaroslav@289
|
174 |
* @return return value from the function
|
jaroslav@289
|
175 |
* @throws Exception if something goes wrong, as exception may be thrown
|
jaroslav@289
|
176 |
*/
|
jaroslav@289
|
177 |
public abstract Object invoke(Object thiz, Object... args) throws Exception;
|
jaroslav@289
|
178 |
|
jaroslav@289
|
179 |
/** The representation of a <em>presenter</em> - usually a browser window.
|
jaroslav@315
|
180 |
* Should be provided by a library included in the application and registered
|
jaroslav@315
|
181 |
* in <code>META-INF/services</code>, for example with
|
jaroslav@315
|
182 |
* <code>@ServiceProvider(service = Fn.Presenter.class)</code> annotation.
|
jaroslav@289
|
183 |
*/
|
jaroslav@127
|
184 |
public interface Presenter {
|
jaroslav@289
|
185 |
/** Creates new function with given parameter names and provided body.
|
jaroslav@289
|
186 |
*
|
jaroslav@289
|
187 |
* @param code the body of the function. Can refer to variables named
|
jaroslav@289
|
188 |
* as <code>names</code>
|
jaroslav@289
|
189 |
* @param names names of parameters of the function - these will be
|
jaroslav@289
|
190 |
* available when the <code>code</code> body executes
|
jaroslav@289
|
191 |
*
|
jaroslav@289
|
192 |
* @return function that can be later invoked
|
jaroslav@289
|
193 |
*/
|
jaroslav@127
|
194 |
public Fn defineFn(String code, String... names);
|
jaroslav@289
|
195 |
|
jaroslav@289
|
196 |
/** Opens the browser, loads provided page and when the
|
jaroslav@289
|
197 |
* page is ready, it calls back to the provider runnable.
|
jaroslav@289
|
198 |
*
|
jaroslav@289
|
199 |
* @param page the URL for the page to display
|
jaroslav@289
|
200 |
* @param onPageLoad callback when the page is ready
|
jaroslav@289
|
201 |
*/
|
jaroslav@128
|
202 |
public void displayPage(URL page, Runnable onPageLoad);
|
jaroslav@289
|
203 |
|
jaroslav@289
|
204 |
/** Loads a script into the browser JavaScript interpreter and
|
jaroslav@289
|
205 |
* executes it.
|
jaroslav@289
|
206 |
* @param code the script to execute
|
jaroslav@289
|
207 |
* @throws Exception if something goes wrong, throw an exception
|
jaroslav@289
|
208 |
*/
|
jaroslav@163
|
209 |
public void loadScript(Reader code) throws Exception;
|
jaroslav@123
|
210 |
}
|
jaroslav@123
|
211 |
}
|