| /* |
| * 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.javascript.wrapper; |
| |
| import org.apache.commons.collections.IteratorUtils; |
| import org.apache.sling.api.resource.Resource; |
| import org.apache.sling.scripting.javascript.SlingWrapper; |
| import org.mozilla.javascript.Context; |
| import org.mozilla.javascript.Function; |
| import org.mozilla.javascript.NativeArray; |
| import org.mozilla.javascript.ScriptRuntime; |
| import org.mozilla.javascript.Scriptable; |
| import org.mozilla.javascript.ScriptableObject; |
| import org.mozilla.javascript.Undefined; |
| import org.mozilla.javascript.Wrapper; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Resource in JavaScript has following signature: |
| * <ul> |
| * <li>[String] getName()</li> |
| * <li>[String] name</li> |
| * <li>[Object] getResourceMetadata()</li> |
| * <li>[Object] resourceMetadata</li> |
| * <li>[String] getPath()</li> |
| * <li>[String] path</li> |
| * <li>[String] getResourceType()</li> |
| * <li>[String] resourceType</li> |
| * <li>[String] getResourceSuperType()</li> |
| * <li>[String] resourceSuperType</li> |
| * <li>[Resource] getParent()</li> |
| * <li>[Resource] parent</li> |
| * <li>[ResourceResolver] getResourceResolver()</li> |
| * <li>[ResourceResolver] resourceResolver</li> |
| * <li>[Resource] getChild(String)</li> |
| * <li>[Resource[]] getChildren()</li> |
| * <li>[Resource[]] listChildren()</li> |
| * <li>[Boolean] isResourceType(String)</li> |
| */ |
| public class ScriptableResource extends ScriptableObject implements |
| SlingWrapper { |
| |
| private static final Logger LOGGER = LoggerFactory.getLogger(ScriptableResource.class); |
| |
| public static final String CLASSNAME = "Resource"; |
| |
| private static final Class<?>[] WRAPPED_CLASSES = { Resource.class }; |
| |
| private Resource resource; |
| |
| public ScriptableResource() { |
| } |
| |
| public ScriptableResource(Resource resource) { |
| this.resource = resource; |
| } |
| |
| public void jsConstructor(Object res) { |
| this.resource = (Resource) res; |
| } |
| |
| /** |
| * Maps getName() method as name property. |
| */ |
| public String jsGet_name() { |
| return this.jsFunction_getName(); |
| } |
| |
| /** |
| * Maps getName() method as getName() method. |
| */ |
| public String jsFunction_getName() { |
| return resource.getName(); |
| } |
| |
| /** |
| * Maps getPath() method as path property. |
| */ |
| public String jsGet_path() { |
| return this.jsFunction_getPath(); |
| } |
| |
| /** |
| * Maps getPath() method as getPath() method. |
| */ |
| public String jsFunction_getPath() { |
| return resource.getPath(); |
| } |
| |
| /** |
| * Maps getResourceType() to type property. This property is deprecated |
| * since it does not correctly map the getResourceType() method name to a |
| * property. |
| * |
| * @deprecated since 2.1.0 because it maps the method name incorrectly. |
| */ |
| @Deprecated |
| public String jsGet_type() { |
| return this.jsFunction_getResourceType(); |
| } |
| |
| /** |
| * Maps getResourceType() to resourceType property. |
| */ |
| public String jsGet_resourceType() { |
| return this.jsFunction_getResourceType(); |
| } |
| |
| /** |
| * Maps getResourceType() to the getResourceType() method. |
| */ |
| public String jsFunction_getResourceType() { |
| return resource.getResourceType(); |
| } |
| |
| public NativeArray jsFunction_listChildren() { |
| return jsFunction_getChildren(); |
| } |
| |
| public NativeArray jsFunction_getChildren() { |
| return new NativeArray(IteratorUtils.toArray(resource.listChildren())); |
| } |
| |
| /** |
| * Maps getParent() method as parent property. |
| */ |
| public Object jsGet_parent() { |
| return this.jsFunction_getParent(); |
| } |
| |
| /** |
| * Maps getParent() method as getParent() method. |
| */ |
| public Object jsFunction_getParent() { |
| return resource.getParent(); |
| } |
| |
| /** |
| * Maps getResourceSuperType() to resourceSuperType property. |
| */ |
| public String jsGet_resourceSuperType() { |
| return this.jsFunction_getResourceSuperType(); |
| } |
| |
| /** |
| * Maps getResourceSuperType() to the getResourceSuperType() method. |
| */ |
| public String jsFunction_getResourceSuperType() { |
| return resource.getResourceSuperType(); |
| } |
| |
| public boolean jsFunction_isResourceType(String type) { |
| return resource.isResourceType(type); |
| } |
| |
| /** |
| * Maps getResourceMetadata() to meta property. This property is deprecated |
| * since it does not correctly map the getResourceType() method name to a |
| * property. |
| * |
| * @deprecated since 2.1.0 because it maps the method name incorrectly. |
| */ |
| @Deprecated |
| public Object jsGet_meta() { |
| return jsFunction_getResourceMetadata(); |
| } |
| |
| /** |
| * Maps getResourceMetadata() to resourceMetadata property. |
| */ |
| public Object jsGet_resourceMetadata() { |
| return jsFunction_getResourceMetadata(); |
| } |
| |
| /** |
| * Maps getResourceMetadata() to getMetadata() method. This method is |
| * deprecated since it has the wrong name to support the |
| * getResourceMetadata() method. |
| * |
| * @deprecated since 2.1.0 because the method is named incorrectly. |
| */ |
| @Deprecated |
| public Object jsFunction_getMetadata() { |
| return jsFunction_getResourceMetadata(); |
| } |
| |
| /** |
| * Maps getResourceMetadata() to getResourceMetadata method. |
| */ |
| public Object jsFunction_getResourceMetadata() { |
| return toJS(resource.getResourceMetadata()); |
| } |
| |
| /** |
| * Maps getResourceResolver() to resourceResolver property. |
| */ |
| public Object jsFunction_getResourceResolver() { |
| return toJS(resource.getResourceResolver()); |
| } |
| |
| /** |
| * Maps getResourceResolver() to getResourceResolver method. |
| */ |
| public Object jsGet_resourceResolver() { |
| return jsFunction_getResourceResolver(); |
| } |
| |
| /** |
| * Maps getChild(String childPath) to getChild method. |
| * |
| * @param childPath the child path |
| * @return the child resource if one exists at {@code childPath} or {@code null} |
| */ |
| public Object jsFunction_getChild(String childPath) { |
| return resource.getChild(childPath); |
| } |
| |
| /** |
| * Helper method to easily retrieve the default adapted object of the |
| * resource. In case of Object Content Mapping support, this method will |
| * return the correctly mapped content object for this resource. |
| * <p> |
| * Calling this method is equivalent to calling the adaptTo method with the |
| * argument "java.lang.Object". |
| */ |
| public Object jsFunction_getObject() { |
| return toJS(resource.adaptTo(Object.class)); |
| } |
| |
| /** |
| * Implements the adaptTo() method for JavaScript scripts. This method takes |
| * either a java.lang.Class object or a String containing the fully |
| * qualified name of the class to adapt to. |
| * <p> |
| * Supporting String as an argument to this method allows for much easier |
| * use in JavaScript since instead of for example writing |
| * <i>"javax.jcr.Node"</i> instead of the much clumsier |
| * <i>Packages.javax.jcr.Node</i>. |
| * |
| * @param cx The current Rhino context |
| * @param thisObj The ScriptableResource object in which the method is |
| * called. |
| * @param args The argument vector. Only the first argument is used which is |
| * expected to be a Class object or a String. If no argument is |
| * supplied or it has the wrong type, this method just returns |
| * <code>null</code>. |
| * @param funObj The object representing the JavaScript adaptTo function. |
| * @return The object to which the resource adapts or <code>null</code> if |
| * the resource does not adapt to the required type or if the |
| * argument is of the wrong type or missing. |
| */ |
| public static Object jsFunction_adaptTo(Context cx, Scriptable thisObj, |
| Object[] args, Function funObj) { |
| |
| // get and unwrap the argument |
| Object arg = (args.length > 0) ? args[0] : null; |
| while (arg instanceof Wrapper) { |
| arg = ((Wrapper) arg).unwrap(); |
| } |
| |
| // try to get the Class object for the argument |
| Class<?> adapter = null; |
| if (arg instanceof Class<?>) { |
| |
| adapter = (Class<?>) arg; |
| |
| } else if (arg != null && arg != Undefined.instance) { |
| |
| // try loading the class from the String |
| String className = ScriptRuntime.toString(arg); |
| try { |
| ClassLoader loader = Thread.currentThread().getContextClassLoader(); |
| if (loader == null) { |
| loader = thisObj.getClass().getClassLoader(); |
| } |
| adapter = loader.loadClass(className); |
| } catch (Exception e) { |
| LOGGER.error("Unable to adapt object.", e); |
| } |
| |
| } |
| |
| if (adapter != null) { |
| ScriptableResource sr = (ScriptableResource) thisObj; |
| return sr.toJS(sr.resource.adaptTo(adapter)); |
| } |
| |
| return Undefined.instance; |
| } |
| |
| // --------- ScriptableObject API |
| |
| @Override |
| public String getClassName() { |
| return CLASSNAME; |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public Object getDefaultValue(Class typeHint) { |
| if (resource != null) { |
| return resource.getPath(); |
| } |
| |
| return String.valueOf((Object) null); |
| } |
| |
| public void setResource(Resource entry) { |
| this.resource = entry; |
| } |
| |
| // ---------- SlingWrapper API |
| |
| public Class<?>[] getWrappedClasses() { |
| return WRAPPED_CLASSES; |
| } |
| |
| // ---------- Wrapper interface -------------------------------------------- |
| |
| // returns the wrapped resource |
| public Object unwrap() { |
| return resource; |
| } |
| |
| // ---------- Internal helper ---------------------------------------------- |
| |
| private Object toJS(Object javaObject) { |
| if (javaObject == null) { |
| return Undefined.instance; |
| } |
| |
| return ScriptRuntime.toObject(this, javaObject); |
| } |
| } |