| /* |
| * 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.jsp.taglib; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import javax.servlet.jsp.PageContext; |
| |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.sling.api.adapter.Adaptable; |
| import org.apache.sling.api.resource.Resource; |
| import org.apache.sling.api.resource.ResourceResolver; |
| import org.apache.sling.api.resource.ValueMap; |
| import org.apache.sling.api.scripting.SlingBindings; |
| import org.apache.sling.api.scripting.SlingScriptHelper; |
| import org.apache.sling.caconfig.resource.ConfigurationResourceResolver; |
| import org.apache.sling.scripting.jsp.taglib.helpers.XSSSupport; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Class containing the TagLib Functions for Sling. |
| */ |
| public class SlingFunctions { |
| |
| /** |
| * The SLF4J Logger. |
| */ |
| private static final Logger log = LoggerFactory.getLogger(SlingFunctions.class); |
| |
| /** |
| * Adapt the adaptable to the adapter class. |
| * |
| * @param adaptable the adaptable instance |
| * @param adapter the class to which to adapt the adaptable |
| * @return the adapted class instance |
| * @throws ClassNotFoundException the adapter class was not found by the |
| * Classloader |
| */ |
| public static Object adaptTo(Adaptable adaptable, String adapter) throws ClassNotFoundException { |
| log.trace("adaptTo"); |
| Object adapted = null; |
| |
| if (adaptable != null) { |
| log.debug("Adapting {} to class {}", adaptable, adapter); |
| try { |
| Class<?> adapterClass = loadClass(adapter); |
| adapted = adaptable.adaptTo(adapterClass); |
| } catch (ClassNotFoundException e) { |
| log.error("Could not load class " + adapter, e); |
| } |
| } else { |
| log.debug("Null adaptable specified"); |
| } |
| return adapted; |
| } |
| |
| /** |
| * XSS encodes the specified text using the specified mode. |
| * |
| * @param value The text to encode |
| * @param mode The XSS mode to use, see XSSSupport for the list of available |
| * modes |
| * @return the encoded text |
| */ |
| public static String encode(String value, String mode) { |
| return XSSSupport.encode(value, XSSSupport.getEncodingMode(mode)); |
| } |
| |
| /** |
| * Searches for resources using the given query formulated in the given |
| * language. |
| * |
| * @param resourceResolver the resource resolver to use to find resources with |
| * the specified query |
| * @param query The query string to use to find the resources. |
| * @param language The language in which the query is formulated. |
| * @return An Iterator of Resource objects matching the query. |
| */ |
| public static Iterator<Resource> findResources(ResourceResolver resourceResolver, String query, String language) { |
| log.trace("findResources"); |
| |
| Iterator<Resource> resources = null; |
| if (resourceResolver != null) { |
| log.debug("Finding resources with query {} of type {}", query, language); |
| resources = resourceResolver.findResources(query, language); |
| } else { |
| log.warn("Null resolver specified"); |
| } |
| return resources; |
| } |
| |
| /** |
| * Method for retrieving an absolute parent resource. |
| * |
| * @param current the current resource |
| * @param level the absolute level for the parent resource to retrieve |
| * @return the parent resource at the level |
| */ |
| public static final Resource getAbsoluteParent(Resource current, String level) { |
| log.trace("getAbsoluteParent"); |
| Resource parent = null; |
| if (level != null) { |
| String[] segments = current.getPath().split("\\/"); |
| int end = Integer.parseInt(level, 10); |
| String parentPath = "/" + StringUtils.join(Arrays.copyOfRange(segments, 1, end + 1), "/"); |
| log.debug("Retrieving {} parent resource at path {}", level, parentPath); |
| parent = current.getResourceResolver().getResource(parentPath); |
| } else { |
| log.debug("Retrieving parent resource"); |
| parent = current.getParent(); |
| } |
| return parent; |
| } |
| |
| /** |
| * Method for retrieving the CA Config resource for a specified resource |
| * |
| * @param resource the resource for which to retrieve the CA Config resource |
| * @param bucket the bucket name of the configuration to retrieve |
| * @param name the configuration name to retrieve |
| * @return the config resource |
| */ |
| public static final Resource getCAConfigResource(Resource resource, String bucket, String name) { |
| log.trace("getCAConfigResource"); |
| ConfigurationResourceResolver caResourceResolver = resource.getResourceResolver() |
| .adaptTo(ConfigurationResourceResolver.class); |
| return caResourceResolver.getResource(resource, bucket, name); |
| } |
| |
| /** |
| * Method for retrieving the CA Config resources for a specified resource |
| * |
| * @param resource the resource for which to retrieve the CA Config resources |
| * @param bucket the bucket name of the configuration to retrieve |
| * @param name the configuration name to retrieve |
| * @return the config resources |
| */ |
| public static final Iterator<Resource> getCAConfigResources(Resource resource, String bucket, String name) { |
| log.trace("getCAConfigResource"); |
| ConfigurationResourceResolver caResourceResolver = resource.getResourceResolver() |
| .adaptTo(ConfigurationResourceResolver.class); |
| return caResourceResolver.getResourceCollection(resource, bucket, name).iterator(); |
| } |
| |
| /** |
| * Function for retrieving all of the parent resources of a specified resource, |
| * returning them in hierarchy order. |
| * |
| * @param current the current resource for which to retrieve the parents |
| * @param startDepth The depth at which to start, for example given a path of: |
| * /content/page1/page2/page3 and a start depth of 3, the |
| * parents page2/page3 would be returned |
| * @return an iterator of the parent resources in order |
| */ |
| public static final Iterator<Resource> getParents(Resource current, String startDepth) { |
| List<Resource> parents = new ArrayList<>(); |
| while (true) { |
| Resource parent = current.getParent(); |
| if (parent != null) { |
| parents.add(parent); |
| current = parent; |
| } else { |
| break; |
| } |
| } |
| Collections.reverse(parents); |
| |
| int depth = Integer.parseInt(startDepth, 10); |
| if (depth <= parents.size()) { |
| parents = parents.subList(depth, parents.size()); |
| } else { |
| parents.clear(); |
| } |
| return parents.iterator(); |
| } |
| |
| /** |
| * Gets the resource at the relative path to the provided resource. |
| * |
| * @param base the resource relative to which to find the path |
| * @param path the relative path at which to find the resource |
| * @return the resource |
| */ |
| public static Resource getRelativeResource(Resource base, String path) { |
| log.trace("getRelativeResource"); |
| |
| Resource relative = null; |
| if (base != null) { |
| log.debug("Getting relative resource of {} at path {}", base.getPath(), path); |
| relative = base.getResourceResolver().getResource(base, path); |
| } else { |
| log.warn("Null base resource specified"); |
| } |
| |
| return relative; |
| } |
| |
| /** |
| * Method allow for the retrieval of resources. |
| * |
| * @param resolver the current resource resolver |
| * @param path the path of the resource to retrieve |
| * @return the resource at the path or null |
| */ |
| public static final Resource getResource(ResourceResolver resolver, String path) { |
| log.trace("getResource"); |
| |
| log.debug("Getting resource at path {}", path); |
| if (resolver == null) { |
| throw new IllegalArgumentException("Null resource resolver"); |
| } |
| return resolver.getResource(path); |
| } |
| |
| /** |
| * Method for retrieving the ResourceResolver from the page context. |
| * |
| * @return the resource resolver |
| */ |
| protected static final ResourceResolver getResourceResolver(PageContext pageContext) { |
| final SlingBindings bindings = (SlingBindings) pageContext.getRequest() |
| .getAttribute(SlingBindings.class.getName()); |
| final SlingScriptHelper scriptHelper = bindings.getSling(); |
| return scriptHelper.getRequest().getResourceResolver(); |
| } |
| |
| /** |
| * Gets the value of the specified key from the ValueMap and either coerses the |
| * value into the specified type or uses the specified type as a default |
| * depending on the parameter passed in. |
| * |
| * @param properties the ValueMap from which to retrieve the value |
| * @param key the key for the value to retrieve |
| * @param defaultOrType either the default value or the class to which to coerce |
| * the value |
| * @return the value for the specified key or the default |
| */ |
| @SuppressWarnings("unchecked") |
| public static final <E> E getValue(ValueMap properties, String key, Object defaultOrType) { |
| if (defaultOrType instanceof Class<?>) { |
| return properties.get(key, (Class<E>) defaultOrType); |
| } else { |
| return properties.get(key, (E) defaultOrType); |
| } |
| } |
| |
| /** |
| * Method for checking whether or not a resource has child resources. |
| * |
| * @param resource the resource to check for child resources |
| * @return true if the resource has child resources, false otherwise |
| * @since 2.2.2 |
| */ |
| public static final boolean hasChildren(Resource resource) { |
| return resource != null ? resource.listChildren().hasNext() : false; |
| } |
| |
| /** |
| * Method for allowing the invocation of the Sling Resource listChildren method. |
| * |
| * @param resource the resource of which to list the children |
| * @return the children of the resource |
| * @see org.apache.sling.api.resource.Resource#listChildren() |
| */ |
| public static final Iterator<Resource> listChildren(Resource resource) { |
| log.trace("listChildren"); |
| |
| Iterator<Resource> children = null; |
| if (resource != null) { |
| log.debug("Listing children at path {}", resource.getPath()); |
| children = resource.listChildren(); |
| } else { |
| log.warn("Null resource specified"); |
| } |
| return children; |
| } |
| |
| /** |
| * Loads the Class for the name from the current thread's classload. |
| * |
| * @param className The name of the class to load |
| * @return the class |
| * @throws ClassNotFoundException a class with the specified name could not be |
| * found |
| */ |
| private static Class<?> loadClass(String className) throws ClassNotFoundException { |
| return Thread.currentThread().getContextClassLoader().loadClass(className); |
| } |
| } |