| /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| ~ 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.bundle.tracker.internal; |
| |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.sling.commons.compiler.source.JavaEscapeHelper; |
| import org.apache.sling.scripting.bundle.tracker.BundledRenderUnitCapability; |
| import org.apache.sling.scripting.bundle.tracker.ResourceType; |
| import org.apache.sling.scripting.bundle.tracker.TypeProvider; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.osgi.framework.Bundle; |
| import org.osgi.service.component.annotations.Component; |
| |
| @Component( |
| service = BundledScriptFinder.class |
| ) |
| public class BundledScriptFinder { |
| |
| private static final String NS_JAVAX_SCRIPT_CAPABILITY = "javax.script"; |
| private static final String SLASH = "/"; |
| private static final String DOT = "."; |
| |
| Executable getScript(Set<TypeProvider> providers, Set<TypeProvider> allProviders) { |
| for (TypeProvider provider : providers) { |
| BundledRenderUnitCapability capability = provider.getBundledRenderUnitCapability(); |
| for (String match : buildScriptMatches(capability.getResourceTypes(), |
| capability.getSelectors().toArray(new String[0]), capability.getMethod(), capability.getExtension())) { |
| String scriptExtension = capability.getScriptExtension(); |
| String scriptEngineName = capability.getScriptEngineName(); |
| if (StringUtils.isNotEmpty(scriptExtension) && StringUtils.isNotEmpty(scriptEngineName)) { |
| Executable executable = getExecutable(provider.getBundle(), match, scriptEngineName, scriptExtension, allProviders); |
| if (executable != null) { |
| return executable; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| Executable getScript(@NotNull Bundle bundle, @NotNull String path, @NotNull String scriptEngineName, |
| @NotNull Set<TypeProvider> providers) { |
| String className = JavaEscapeHelper.makeJavaPackage(path); |
| try { |
| Class<?> clazz = bundle.loadClass(className); |
| return new PrecompiledScript(providers, bundle, path, clazz, scriptEngineName); |
| } catch (ClassNotFoundException ignored) { |
| URL bundledScriptURL = bundle.getEntry(NS_JAVAX_SCRIPT_CAPABILITY + (path.startsWith("/") ? "" : SLASH) + path); |
| if (bundledScriptURL != null) { |
| return new Script(providers, bundle, path, bundledScriptURL, scriptEngineName); |
| } // do nothing here |
| } |
| |
| return null; |
| } |
| |
| @Nullable |
| private Executable getExecutable(@NotNull Bundle bundle, @NotNull String match, @NotNull String scriptEngineName, |
| @NotNull String scriptExtension, @NotNull Set<TypeProvider> providers) { |
| String path = match + DOT + scriptExtension; |
| return getScript(bundle, path, scriptEngineName, providers); |
| } |
| |
| private List<String> buildScriptMatches(Set<ResourceType> resourceTypes, String[] selectors, String method, String extension) { |
| List<String> matches = new ArrayList<>(); |
| for (ResourceType resourceType : resourceTypes) { |
| if (selectors.length > 0) { |
| for (int i = selectors.length - 1; i >= 0; i--) { |
| String base = |
| resourceType.getType() + |
| (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() + SLASH : |
| SLASH) + |
| String.join(SLASH, Arrays.copyOf(selectors, i + 1)); |
| if (StringUtils.isNotEmpty(extension)) { |
| if (StringUtils.isNotEmpty(method)) { |
| matches.add(base + DOT + extension + DOT + method); |
| } |
| matches.add(base + DOT + extension); |
| } |
| if (StringUtils.isNotEmpty(method)) { |
| matches.add(base + DOT + method); |
| } |
| matches.add(base); |
| } |
| } |
| String base = resourceType.getType() + |
| (StringUtils.isNotEmpty(resourceType.getVersion()) ? SLASH + resourceType.getVersion() : StringUtils.EMPTY); |
| |
| if (StringUtils.isNotEmpty(extension)) { |
| if (StringUtils.isNotEmpty(method)) { |
| matches.add(base + SLASH + resourceType.getResourceLabel() + DOT + extension + DOT + method); |
| } |
| matches.add(base + SLASH + resourceType.getResourceLabel() + DOT + extension); |
| } |
| if (StringUtils.isNotEmpty(method)) { |
| matches.add(base + SLASH + resourceType.getResourceLabel() + DOT + method); |
| } |
| matches.add(base + SLASH + resourceType.getResourceLabel()); |
| if (StringUtils.isNotEmpty(method)) { |
| matches.add(base + SLASH + method); |
| } |
| if (StringUtils.isNotEmpty(extension)) { |
| matches.add(base + SLASH + extension); |
| } |
| } |
| return Collections.unmodifiableList(matches); |
| } |
| } |