You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2014/11/28 11:18:09 UTC
svn commit: r1642281 [14/14] - in /sling/trunk/contrib/scripting/sightly: ./
engine/ engine/src/main/antlr4/org/apache/sling/parser/expr/generated/
engine/src/main/antlr4/org/apache/sling/scripting/
engine/src/main/antlr4/org/apache/sling/scripting/sig...
Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.impl.loop;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+import org.apache.sling.scripting.sightly.use.SightlyUseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Simulates an event loop for the Rhino JS engine.
+ */
+public class EventLoop {
+
+ private static final Logger log = LoggerFactory.getLogger(EventLoop.class);
+
+ private Queue<Task> taskQueue = new LinkedList<Task>();
+ private boolean isRunning;
+
+ /**
+ * Add a task to the queue. If the queue is empty, start running tasks. If it
+ * isn't empty, continue running the available tasks
+ * @param task the task to be added
+ */
+ public void schedule(Task task) {
+ taskQueue.offer(task);
+ run();
+ }
+
+ private void run() {
+ if (isRunning) {
+ return;
+ }
+ isRunning = true;
+ try {
+ // Holds the first exception encountered. If there is such a first exception, it will be
+ // rethrown
+ Exception thrownException = null;
+ while (!taskQueue.isEmpty()) {
+ Task task = taskQueue.poll();
+ try {
+ task.run();
+ } catch (Exception e) {
+ if (thrownException == null) {
+ thrownException = e; //first exception
+ } else {
+ log.error("Additional error occurred while running JS script: ", e);
+ }
+ }
+ }
+ if (thrownException != null) {
+ throw new SightlyUseException(thrownException);
+ }
+ } finally {
+ isRunning = false;
+ }
+ }
+
+}
Propchange: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoop.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoopInterop.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoopInterop.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoopInterop.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoopInterop.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.impl.loop;
+
+import org.mozilla.javascript.Context;
+
+/**
+ * Event-loop utilities for interoperability with JS code
+ */
+public class EventLoopInterop {
+
+ public static final String EVENT_LOOP_KEY = "EventLoop";
+
+ public static EventLoop obtainEventLoop(Context context) {
+ EventLoop eventLoop = getEventLoop(context);
+ if (eventLoop == null) {
+ eventLoop = new EventLoop();
+ context.putThreadLocal(EVENT_LOOP_KEY, eventLoop);
+ }
+ return eventLoop;
+ }
+
+ public static void cleanupEventLoop(Context context) {
+ context.removeThreadLocal(EVENT_LOOP_KEY);
+ }
+
+ public static Task schedule(Context context, Runnable runnable) {
+ Task task = new Task(runnable);
+ obtainEventLoop(context).schedule(task);
+ return task;
+ }
+
+ private static EventLoop getEventLoop(Context context) {
+ return (EventLoop) context.getThreadLocal(EVENT_LOOP_KEY);
+ }
+
+}
Propchange: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/EventLoopInterop.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/Task.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/Task.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/Task.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/Task.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.impl.loop;
+
+/**
+ * Task in an event loop
+ */
+public class Task {
+
+ private final Runnable runnable;
+ private boolean active;
+
+ public Task(Runnable runnable) {
+ this.runnable = runnable;
+ this.active = true;
+ }
+
+ public void run() {
+ if (active) {
+ runnable.run();
+ }
+ }
+
+ public void deactivate() {
+ this.active = false;
+ }
+}
Propchange: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/loop/Task.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.impl.rhino;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.sling.scripting.sightly.Record;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+
+
+/**
+ * Instances of this class can be used in both Sightly & JS scripts
+ */
+public class HybridObject implements Scriptable, Record<Object> {
+
+ private final Scriptable scriptable;
+ private final JsValueAdapter jsValueAdapter;
+
+ public HybridObject(Scriptable scriptable, JsValueAdapter jsValueAdapter) {
+ this.scriptable = scriptable;
+ this.jsValueAdapter = jsValueAdapter;
+ }
+
+ // Record implementation
+
+ @Override
+ public Object get(String name) {
+ if (name == null) {
+ return null;
+ }
+ Context.enter();
+ try {
+ return getAdapted(name);
+ } finally {
+ Context.exit();
+ }
+ }
+
+ @Override
+ public Set<String> properties() {
+ Object[] properties = scriptable.getIds();
+ Set<String> keys = new HashSet<String>();
+ for (Object property: properties) {
+ if (property instanceof String) {
+ keys.add((String) property);
+ }
+ }
+ return keys;
+ }
+
+ private Object getAdapted(String key) {
+ Object obj = ScriptableObject.getProperty(scriptable, key);
+ if (obj == null) {
+ return null;
+ }
+ if (obj instanceof Function) {
+ return jsValueAdapter.adapt(JsUtils.callFn((Function) obj, null, scriptable, scriptable, new Object[0]));
+ }
+ return jsValueAdapter.adapt(obj);
+ }
+
+ // Scriptable implementation
+
+ @Override
+ public String getClassName() {
+ return scriptable.getClassName();
+ }
+
+ @Override
+ public Object get(String name, Scriptable start) {
+ return scriptable.get(name, start);
+ }
+
+ @Override
+ public Object get(int index, Scriptable start) {
+ return scriptable.get(index, start);
+ }
+
+ @Override
+ public boolean has(String name, Scriptable start) {
+ return scriptable.has(name, start);
+ }
+
+ @Override
+ public boolean has(int index, Scriptable start) {
+ return scriptable.has(index, start);
+ }
+
+ @Override
+ public void put(String name, Scriptable start, Object value) {
+ scriptable.put(name, start, value);
+ }
+
+ @Override
+ public void put(int index, Scriptable start, Object value) {
+ scriptable.put(index, start, value);
+ }
+
+ @Override
+ public void delete(String name) {
+ scriptable.delete(name);
+ }
+
+ @Override
+ public void delete(int index) {
+ scriptable.delete(index);
+ }
+
+ @Override
+ public Scriptable getPrototype() {
+ return scriptable.getPrototype();
+ }
+
+ @Override
+ public void setPrototype(Scriptable prototype) {
+ scriptable.setPrototype(prototype);
+ }
+
+ @Override
+ public Scriptable getParentScope() {
+ return scriptable.getParentScope();
+ }
+
+ @Override
+ public void setParentScope(Scriptable parent) {
+ scriptable.setParentScope(parent);
+ }
+
+ @Override
+ public Object[] getIds() {
+ return scriptable.getIds();
+ }
+
+ @Override
+ public Object getDefaultValue(Class hint) {
+ return scriptable.getDefaultValue(hint);
+ }
+
+ @Override
+ public boolean hasInstance(Scriptable instance) {
+ return scriptable.hasInstance(instance);
+ }
+}
Propchange: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/HybridObject.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsUtils.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsUtils.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsUtils.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsUtils.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.impl.rhino;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * Utilities when inter-operating with JS scripts
+ */
+public class JsUtils {
+
+ public static Object callFn(Function function, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
+ boolean exitContext = false;
+ if (Context.getCurrentContext() == null) {
+ Context.enter();
+ exitContext = true;
+ }
+ Context context = (cx == null) ? Context.getCurrentContext() : cx;
+ Object result = function.call(context, scope, thisObj, args);
+ if (exitContext) {
+ Context.exit();
+ }
+ return result;
+ }
+
+
+
+}
Propchange: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsUtils.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsValueAdapter.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsValueAdapter.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsValueAdapter.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsValueAdapter.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.js.impl.rhino;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeArray;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.Wrapper;
+import org.apache.sling.scripting.sightly.js.impl.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.impl.async.AsyncExtractor;
+
+/**
+ * Converts JS objects to Java objects
+ */
+public class JsValueAdapter {
+
+ private static final Map<String, Class<?>> knownConversions = new HashMap<String, Class<?>>();
+
+ static {
+ knownConversions.put("String", String.class);
+ knownConversions.put("Date", Date.class);
+ }
+
+ private final AsyncExtractor asyncExtractor;
+
+ public JsValueAdapter(AsyncExtractor asyncExtractor) {
+ this.asyncExtractor = asyncExtractor;
+ }
+
+ /**
+ * Convert a given JS value to a Java object
+ * @param jsValue the original JS value
+ * @return the Java correspondent
+ */
+ @SuppressWarnings("unchecked")
+ public Object adapt(Object jsValue) {
+ if (jsValue == null || jsValue == Context.getUndefinedValue() || jsValue == ScriptableObject.NOT_FOUND) {
+ return null;
+ }
+ if (jsValue instanceof Wrapper) {
+ return adapt(((Wrapper) jsValue).unwrap());
+ }
+ if (asyncExtractor.isPromise(jsValue)) {
+ return adapt(forceAsync(jsValue));
+ }
+ if (jsValue instanceof ScriptableObject) {
+ return extractScriptable((ScriptableObject) jsValue);
+ }
+ if (jsValue instanceof CharSequence) {
+ //convert any string-like type to plain java strings
+ return jsValue.toString();
+ }
+ if (jsValue instanceof Map) {
+ return convertMap((Map) jsValue);
+ }
+ if (jsValue instanceof Iterable) {
+ return convertIterable((Iterable) jsValue);
+ }
+ if (jsValue instanceof Number) {
+ return convertNumber((Number) jsValue);
+ }
+ if (jsValue instanceof Object[]) {
+ return convertIterable(Arrays.asList((Object[]) jsValue));
+ }
+ return jsValue;
+ }
+
+ private Object convertNumber(Number numValue) {
+ if (numValue instanceof Double) {
+ if (isLong((Double) numValue)) {
+ return numValue.longValue();
+ }
+ }
+ if (numValue instanceof Float) {
+ if (isLong((Float) numValue)) {
+ return numValue.longValue();
+ }
+ }
+ return numValue;
+ }
+
+ private boolean isLong(double x) {
+ return x == Math.floor(x);
+ }
+
+ private Object forceAsync(Object jsValue) {
+ AsyncContainer asyncContainer = new AsyncContainer();
+ asyncExtractor.extract(jsValue, asyncContainer.createCompletionCallback());
+ return asyncContainer.getResult();
+ }
+
+ private Object extractScriptable(ScriptableObject scriptableObject) {
+ Object obj = tryKnownConversion(scriptableObject);
+ if (obj != null) { return obj; }
+ if (scriptableObject instanceof NativeArray) {
+ return convertNativeArray((NativeArray) scriptableObject);
+ }
+ if (scriptableObject instanceof Function) {
+ return callFunction((Function) scriptableObject);
+ }
+ return new HybridObject(scriptableObject, this);
+ }
+
+ private Object callFunction(Function function) {
+ Object result = JsUtils.callFn(function, null, function, function, new Object[0]);
+ return adapt(result);
+ }
+
+ private Object[] convertNativeArray(NativeArray nativeArray) {
+ int length = (int) nativeArray.getLength();
+ Object[] objects = new Object[length];
+ for (int i = 0; i < length; i++) {
+ Object jsItem = nativeArray.get(i, nativeArray);
+ objects[i] = adapt(jsItem);
+ }
+ return objects;
+ }
+
+ private Map<Object, Object> convertMap(Map<Object, Object> original) {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+ for (Map.Entry<Object, Object> entry : original.entrySet()) {
+ map.put(entry.getKey(), adapt(entry.getValue()));
+ }
+ return map;
+ }
+
+ private List<Object> convertIterable(Iterable<Object> iterable) {
+ List<Object> objects = new ArrayList<Object>();
+ for (Object obj : iterable) {
+ objects.add(adapt(obj));
+ }
+ return objects;
+ }
+
+ private static Object tryKnownConversion(ScriptableObject object) {
+ String className = object.getClassName();
+ Class<?> cls = knownConversions.get(className);
+ return (cls == null) ? null : Context.jsToJava(object, cls);
+ }
+}
Propchange: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/rhino/JsValueAdapter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.js.impl.use;
+
+import javax.script.Bindings;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.scripting.sightly.js.impl.JsEnvironment;
+import org.apache.sling.scripting.sightly.js.impl.Utils;
+import org.apache.sling.scripting.sightly.js.impl.async.UnaryCallback;
+import org.apache.sling.scripting.sightly.use.SightlyUseException;
+
+/**
+ * Resolves dependencies specified by the Use function
+ */
+public class DependencyResolver {
+
+ private final Resource caller;
+ private final JsEnvironment jsEnvironment;
+ private final Bindings globalBindings;
+
+ public DependencyResolver(Resource resource, JsEnvironment jsEnvironment, Bindings globalBindings) {
+ this.caller = resource;
+ this.jsEnvironment = jsEnvironment;
+ this.globalBindings = globalBindings;
+ }
+
+ /**
+ * Resolve a dependency
+ * @param dependency the dependency identifier
+ * @param callback the callback that will receive the resolved dependency
+ */
+ public void resolve(String dependency, UnaryCallback callback) {
+ if (!Utils.isJsScript(dependency)) {
+ throw new SightlyUseException("Only JS scripts are allowed as dependencies. Invalid dependency: " + dependency);
+ }
+ jsEnvironment.run(caller, dependency, globalBindings, Utils.EMPTY_BINDINGS, callback);
+ }
+
+}
Propchange: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/DependencyResolver.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/UseFunction.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/UseFunction.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/UseFunction.java (added)
+++ sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/UseFunction.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.js.impl.use;
+
+import javax.script.Bindings;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.mozilla.javascript.BaseFunction;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeArray;
+import org.mozilla.javascript.NativeObject;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+import org.apache.sling.scripting.sightly.js.impl.async.AsyncContainer;
+import org.apache.sling.scripting.sightly.js.impl.async.UnaryCallback;
+import org.apache.sling.scripting.sightly.js.impl.loop.EventLoopInterop;
+import org.apache.sling.scripting.sightly.js.impl.rhino.JsUtils;
+
+/**
+ * The JavaScript {@code use} function
+ */
+public class UseFunction extends BaseFunction {
+
+ private final DependencyResolver dependencyResolver;
+ private final Scriptable thisObj;
+
+ public UseFunction(DependencyResolver dependencyResolver, Bindings arguments) {
+ this.dependencyResolver = dependencyResolver;
+ this.thisObj = createThisBinding(arguments);
+ }
+
+ @Override
+ public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
+ Function function;
+ List<String> depNames;
+ if (args.length == 0) {
+ throw new IllegalArgumentException("Not enough arguments for use");
+ } else if (args.length == 1) {
+ function = decodeCallback(args[0]);
+ depNames = Collections.emptyList();
+ } else {
+ function = decodeCallback(args[1]);
+ depNames = decodeDepNames(args[0]);
+ }
+ return use(depNames, function, cx, scope);
+ }
+
+ private Object use(List<String> depNames, final Function callback, final Context cx, final Scriptable scope) {
+ final AsyncContainer asyncContainer = new AsyncContainer();
+ if (depNames.isEmpty()) {
+ callImmediate(callback, asyncContainer, cx, scope);
+ } else {
+ final int[] counter = {depNames.size()};
+ final Object[] dependencies = new Object[depNames.size()];
+ for (int i = 0; i < depNames.size(); i++) {
+ final int dependencyPos = i;
+ dependencyResolver.resolve(depNames.get(i), new UnaryCallback() {
+ @Override
+ public void invoke(Object arg) {
+ counter[0]--;
+ dependencies[dependencyPos] = arg;
+ if (counter[0] == 0) {
+ Object result = JsUtils.callFn(callback, cx, scope, thisObj, dependencies);
+ asyncContainer.complete(result);
+ }
+ }
+ });
+ }
+ }
+ return asyncContainer;
+ }
+
+ private void callImmediate(final Function callback, final AsyncContainer asyncContainer, final Context cx, final Scriptable scope) {
+ EventLoopInterop.schedule(cx, new Runnable() {
+ @Override
+ public void run() {
+ Object value = JsUtils.callFn(callback, cx, scope, thisObj, new Object[0]);
+ asyncContainer.complete(value);
+ }
+ });
+ }
+
+ private Function decodeCallback(Object obj) {
+ if (!(obj instanceof Function)) {
+ throw new IllegalArgumentException("No callback argument supplied");
+ }
+ return (Function) obj;
+ }
+
+ private List<String> decodeDepNames(Object obj) {
+ if (obj instanceof NativeArray) {
+ return decodeDepArray((NativeArray) obj);
+ }
+ return Collections.singletonList(jsToString(obj));
+ }
+
+ private List<String> decodeDepArray(NativeArray nativeArray) {
+ int depLength = (int) nativeArray.getLength();
+ List<String> depNames = new ArrayList<String>(depLength);
+ for (int i = 0; i < depLength; i++) {
+ String depName = jsToString(nativeArray.get(i, nativeArray));
+ depNames.add(depName);
+ }
+ return depNames;
+ }
+
+ private String jsToString(Object obj) {
+ return (String) Context.jsToJava(obj, String.class);
+ }
+
+ private Scriptable createThisBinding(Bindings arguments) {
+ NativeObject nativeObject = new NativeObject();
+ for (Map.Entry<String, Object> entry : arguments.entrySet()) {
+ ScriptableObject.putProperty(nativeObject, entry.getKey(), entry.getValue());
+ }
+ return nativeObject;
+ }
+}
Propchange: sling/trunk/contrib/scripting/sightly/js-use-provider/src/main/java/org/apache/sling/scripting/sightly/js/impl/use/UseFunction.java
------------------------------------------------------------------------------
svn:mime-type = text/plain