| /* |
| * 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.servlets.resolver.internal; |
| |
| import java.util.Iterator; |
| import java.util.concurrent.atomic.AtomicReference; |
| import java.util.function.Supplier; |
| |
| import javax.servlet.Servlet; |
| |
| import org.apache.sling.api.resource.AbstractResource; |
| import org.apache.sling.api.resource.Resource; |
| import org.apache.sling.api.resource.ResourceMetadata; |
| import org.apache.sling.api.resource.ResourceResolver; |
| import org.apache.sling.api.resource.ResourceUtil; |
| import org.apache.sling.api.resource.ResourceWrapper; |
| import org.apache.sling.api.scripting.SlingScript; |
| import org.apache.sling.servlets.resolver.internal.resource.ServletResource; |
| |
| /** |
| * ScriptResource is a resource wrapper of a resource fetched by a |
| * per thread resource resolver. |
| * As the script engines usually keep a reference to this resource |
| * for a longer time, the resource switches internally to |
| * a resource fetched by the shared resource resolver. |
| * |
| * We can't extend ResourceWrapper as its not possible to clear |
| * the wrapped resource field. |
| */ |
| public class ScriptResource extends AbstractResource { |
| |
| private AtomicReference<Resource> sharedResource = new AtomicReference<>(); |
| |
| private final ResourceResolver sharedResourceResolver; |
| |
| private final Supplier<ResourceResolver> perThreadResourceResolver; |
| |
| private final String path; |
| |
| public ScriptResource(final Resource resource, |
| final Supplier<ResourceResolver> perThreadScriptResolver, |
| final ResourceResolver sharedResourceResolver) { |
| this.path = resource.getPath(); |
| this.sharedResourceResolver = sharedResourceResolver; |
| this.perThreadResourceResolver = perThreadScriptResolver; |
| } |
| |
| private Resource getActiveResource() { |
| ResourceResolver perThreadResolver = this.perThreadResourceResolver.get(); |
| if ( perThreadResolver != null && perThreadResolver.isLive() ) { |
| return perThreadResolver.getResource(this.path); |
| } |
| Resource resource = this.sharedResource.get(); |
| if ( resource == null ) { |
| resource = this.sharedResourceResolver.getResource(this.path); |
| this.sharedResource.set(resource); |
| } |
| return resource; |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.Resource#getResourceType() |
| */ |
| @Override |
| public String getResourceType() { |
| return this.getActiveResource().getResourceType(); |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.Resource#getResourceSuperType() |
| */ |
| @Override |
| public String getResourceSuperType() { |
| return this.getActiveResource().getResourceSuperType(); |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.Resource#getResourceResolver() |
| */ |
| @Override |
| public ResourceResolver getResourceResolver() { |
| return this.getActiveResource().getResourceResolver(); |
| } |
| |
| /** |
| * @see org.apache.sling.api.adapter.SlingAdaptable#adaptTo(java.lang.Class) |
| */ |
| @SuppressWarnings("unchecked") |
| @Override |
| public <T> T adaptTo(final Class<T> type) { |
| if ( type == Servlet.class ) { |
| Resource activeResource = this.getActiveResource(); |
| while (activeResource instanceof ResourceWrapper) { |
| activeResource = ((ResourceWrapper) activeResource).getResource(); |
| } |
| if (! (activeResource instanceof ServletResource)) { |
| final Servlet s = (Servlet) super.adaptTo(type); |
| if ( s != null ) { |
| return (T)s; |
| } |
| } |
| } else if ( type == SlingScript.class ) { |
| final SlingScript s = (SlingScript)super.adaptTo(type); |
| if ( s != null ) { |
| return (T)s; |
| } |
| } |
| return this.getActiveResource().adaptTo(type); |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.Resource#getPath() |
| */ |
| @Override |
| public String getPath() { |
| return this.path; |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.Resource#getResourceMetadata() |
| */ |
| @Override |
| public ResourceMetadata getResourceMetadata() { |
| return this.getActiveResource().getResourceMetadata(); |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.AbstractResource#getName() |
| */ |
| @Override |
| public String getName() { |
| return ResourceUtil.getName(this.path); |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.AbstractResource#getParent() |
| */ |
| @Override |
| public Resource getParent() { |
| return this.getActiveResource().getParent(); |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.AbstractResource#getChild(java.lang.String) |
| */ |
| @Override |
| public Resource getChild(String relPath) { |
| return this.getActiveResource().getChild(relPath); |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.AbstractResource#listChildren() |
| */ |
| @Override |
| public Iterator<Resource> listChildren() { |
| return this.getActiveResource().listChildren(); |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.AbstractResource#getChildren() |
| */ |
| @Override |
| public Iterable<Resource> getChildren() { |
| return this.getActiveResource().getChildren(); |
| } |
| |
| /** |
| * @see org.apache.sling.api.resource.AbstractResource#isResourceType(java.lang.String) |
| */ |
| @Override |
| public boolean isResourceType(String resourceType) { |
| return this.getActiveResource().isResourceType(resourceType); |
| } |
| } |