[maven-release-plugin] copy for tag no
git-svn-id: https://svn.apache.org/repos/asf/sling/tags/no@1759311 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/README.txt b/README.txt
deleted file mode 100644
index be32065..0000000
--- a/README.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-Apache Sling Resource Resolver
-
-This bundle provides the Resource Resolver and Resource Resolver Factory
-
-Getting Started
-===============
-
-This component uses a Maven 3 (http://maven.apache.org/) build
-environment. It requires a Java 6 JDK (or higher) and Maven (http://maven.apache.org/)
-3.0.3 or later. We recommend to use the latest Maven version.
-
-If you have Maven installed, you can compile and
-package the jar using the following command:
-
- mvn package
-
-See the Maven documentation for other build features.
-
-The latest source code for this component is available in the
-Subversion (http://subversion.apache.org/) source repository of
-the Apache Software Foundation. If you have Subversion installed,
-you can checkout the latest source using the following command:
-
- svn checkout http://svn.apache.org/repos/asf/sling/trunk/resourceresolver
-
-See the Subversion documentation for other source control features.
-
diff --git a/pom.xml b/pom.xml
index 1dd01c4..4de43c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,207 +1,174 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
- 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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
+
<parent>
<groupId>org.apache.sling</groupId>
<artifactId>sling</artifactId>
- <version>26</version>
+ <version>28</version>
<relativePath />
</parent>
- <artifactId>org.apache.sling.resourceresolver</artifactId>
- <version>1.4.14</version>
- <packaging>bundle</packaging>
+ <artifactId>htl-maven-plugin</artifactId>
+ <version>1.0.0</version>
+ <packaging>maven-plugin</packaging>
- <name>Apache Sling Resource Resolver</name>
- <description>
- This bundle provides the Resource Resolver and the Resource Resolver Factory.
- </description>
+ <name>Apache Sling HTL Maven Plugin</name>
+ <description>The Apache Sling HTL Maven Plugin provides support for validating HTML Template Language scripts from projects.</description>
<scm>
- <connection>
- scm:svn:http://svn.apache.org/repos/asf/sling/tags/no
- </connection>
- <developerConnection>
- scm:svn:https://svn.apache.org/repos/asf/sling/tags/no
- </developerConnection>
- <url>
- http://svn.apache.org/viewvc/sling/tags/no
- </url>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/sling/tags/no</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/tags/no</developerConnection>
+ <url>http://svn.apache.org/viewvc/sling/tags/no</url>
</scm>
<properties>
- <site.jira.version.id>12314286</site.jira.version.id>
- <site.javadoc.exclude>**.internal.**</site.javadoc.exclude>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.version>3.3.3</maven.version>
</properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.scripting.sightly.compiler</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.plugin-tools</groupId>
+ <artifactId>maven-plugin-annotations</artifactId>
+ <version>3.4</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ <version>3.0.24</version>
+ </dependency>
+ <dependency>
+ <groupId>org.sonatype.plexus</groupId>
+ <artifactId>plexus-build-api</artifactId>
+ <version>0.0.7</version>
+ </dependency>
+
+
+ <!-- Testing Dependencies -->
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-container-default</artifactId>
+ <version>1.6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.plugin-testing</groupId>
+ <artifactId>maven-plugin-testing-harness</artifactId>
+ <version>3.3.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-compat</artifactId>
+ <scope>test</scope>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
<build>
<plugins>
<plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-scr-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.sling</groupId>
- <artifactId>maven-sling-plugin</artifactId>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>3.4</version>
<executions>
<execution>
- <id>generate-adapter-metadata</id>
+ <id>mojo-descriptor</id>
<phase>process-classes</phase>
<goals>
- <goal>generate-adapter-metadata</goal>
+ <goal>descriptor</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>generated-helpmojo</id>
+ <goals>
+ <goal>helpmojo</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-component-metadata</artifactId>
+ <version>1.6</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-metadata</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
<configuration>
- <instructions>
- <Import-Package>
- javax.annotation;resolution:=optional,
- org.apache.sling.api.resource;provide:=true,
- org.apache.sling.commons.osgi;version="$(@)",
- *
- </Import-Package>
- </instructions>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-javadoc-plugin</artifactId>
- <configuration>
- <excludePackageNames>
- org.apache.sling.resourceresolver.impl
- </excludePackageNames>
+ <excludes>
+ <exclude>**/*.iml</exclude>
+ <exclude>**/target/**/*</exclude>
+ </excludes>
</configuration>
</plugin>
</plugins>
</build>
-
- <dependencies>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.scr.annotations</artifactId>
- </dependency>
- <dependency>
- <groupId>javax.jcr</groupId>
- <artifactId>jcr</artifactId>
- <version>2.0</version>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.api</artifactId>
- <version>2.11.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.serviceusermapper</artifactId>
- <version>1.0.0</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.commons.osgi</artifactId>
- <version>2.2.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>commons-collections</groupId>
- <artifactId>commons-collections</artifactId>
- <version>3.2.1</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.4</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>adapter-annotations</artifactId>
- <version>1.0.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
- <version>3.0.0</version>
- <scope>provided</scope>
- </dependency>
-
- <!-- For the Console Plugin of the ResourceResolverFactoryImpl -->
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- </dependency>
-
- <!-- Testing -->
- <dependency>
- <groupId>org.hamcrest</groupId>
- <artifactId>hamcrest-library</artifactId>
- <version>1.3</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
- </dependency>
- <dependency>
- <groupId>junit-addons</groupId>
- <artifactId>junit-addons</artifactId>
- <version>1.4</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.framework</artifactId>
- <version>3.0.8</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <version>1.9.5</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.testing.osgi-mock</artifactId>
- <version>1.4.0</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
</project>
diff --git a/src/main/java/org/apache/sling/maven/htl/ValidateMojo.java b/src/main/java/org/apache/sling/maven/htl/ValidateMojo.java
new file mode 100644
index 0000000..826b2a4
--- /dev/null
+++ b/src/main/java/org/apache/sling/maven/htl/ValidateMojo.java
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * 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.maven.htl;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apache.sling.scripting.sightly.compiler.CompilationResult;
+import org.apache.sling.scripting.sightly.compiler.CompilationUnit;
+import org.apache.sling.scripting.sightly.compiler.CompilerMessage;
+import org.apache.sling.scripting.sightly.compiler.SightlyCompiler;
+import org.codehaus.plexus.util.Scanner;
+import org.codehaus.plexus.util.StringUtils;
+import org.sonatype.plexus.build.incremental.BuildContext;
+
+/**
+ * This goal validates Sightly scripts syntax.
+ */
+@Mojo(
+ name = "validate",
+ defaultPhase = LifecyclePhase.COMPILE,
+ threadSafe = true
+)
+public class ValidateMojo extends AbstractMojo {
+
+ private static final String DEFAULT_INCLUDES = "**/*.html";
+ private static final String DEFAULT_EXCLUDES = "";
+
+ @Component
+ private BuildContext buildContext;
+
+ @Parameter(defaultValue = "${project}", readonly = true, required = true)
+ protected MavenProject project;
+
+ /**
+ * Defines the root folder where this Mojo expects to find Sightly scripts to validate.
+ */
+ @Parameter(property = "sourceDirectory", defaultValue = "${project.build.sourceDirectory}")
+ private File sourceDirectory;
+
+ /**
+ * List of files to include. Specified as fileset patterns which are relative to the input directory whose contents will be scanned
+ * (see the sourceDirectory configuration option).
+ */
+ @Parameter
+ private String[] includes;
+
+ /**
+ * List of files to exclude. Specified as fileset patterns which are relative to the input directory whose contents will be scanned
+ * (see the sourceDirectory configuration option).
+ */
+ @Parameter
+ private String[] excludes;
+
+ /**
+ * If set to "true" it will fail the build on compiler warnings.
+ */
+ @Parameter(property = "failOnWarnings", defaultValue = "false")
+ private boolean failOnWarnings;
+
+ private boolean hasWarnings = false;
+ private boolean hasErrors = false;
+ private String processedIncludes = null;
+ private String processedExcludes = null;
+ private List<File> processedFiles = Collections.emptyList();
+
+ private int sourceDirectoryLength = 0;
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+
+ long start = System.currentTimeMillis();
+
+ if (!sourceDirectory.isAbsolute()) {
+ sourceDirectory = new File(project.getBasedir(), sourceDirectory.getPath());
+ }
+ if (!sourceDirectory.exists()) {
+ throw new MojoExecutionException(
+ String.format("Configured sourceDirectory={%s} does not exist.", sourceDirectory.getAbsolutePath()));
+ }
+ if (!sourceDirectory.isDirectory()) {
+ throw new MojoExecutionException(
+ String.format("Configured sourceDirectory={%s} is not a directory.", sourceDirectory.getAbsolutePath()));
+ }
+
+ if ( !buildContext.hasDelta(sourceDirectory )) {
+ getLog().info("No files found to validate, skipping");
+ return;
+ }
+
+ // don't fail execution in Eclipse as it generates an error marker in the POM file, which is not desired
+ boolean mayFailExecution = !buildContext.getClass().getName().startsWith("org.eclipse.m2e");
+
+ sourceDirectoryLength = sourceDirectory.getAbsolutePath().length();
+ processedIncludes = processIncludes();
+ processedExcludes = processExcludes();
+ try {
+ SightlyCompiler compiler = new SightlyCompiler();
+
+ Scanner scanner = buildContext.newScanner(sourceDirectory);
+ scanner.setExcludes(new String[] { processedExcludes } );
+ scanner.setIncludes(new String[] { processedIncludes } );
+ scanner.scan();
+
+ String[] includedFiles = scanner.getIncludedFiles();
+
+ processedFiles = new ArrayList<>(includedFiles.length);
+ for ( String includedFile : includedFiles ) {
+ processedFiles.add(new File(sourceDirectory, includedFile));
+ }
+ Map<File, CompilationResult> compilationResults = new HashMap<>();
+ for (File script : processedFiles) {
+ compilationResults.put(script, compiler.compile(getCompilationUnit(script)));
+ }
+ for (Map.Entry<File, CompilationResult> entry : compilationResults.entrySet()) {
+ File script = entry.getKey();
+ CompilationResult result = entry.getValue();
+ buildContext.removeMessages(script);
+
+ if (result.getWarnings().size() > 0) {
+ for (CompilerMessage message : result.getWarnings()) {
+ buildContext.addMessage(script, message.getLine(), message.getColumn(), message.getMessage(), BuildContext.SEVERITY_WARNING, null);
+ }
+ hasWarnings = true;
+ }
+ if (result.getErrors().size() > 0) {
+ for (CompilerMessage message : result.getErrors()) {
+ String messageString = message.getMessage().replaceAll(System.lineSeparator(), "");
+ buildContext.addMessage(script, message.getLine(), message.getColumn(), messageString, BuildContext.SEVERITY_ERROR, null);
+ }
+ hasErrors = true;
+ }
+ }
+
+ getLog().info("Processed " + processedFiles.size() + " files in " + ( System.currentTimeMillis() - start ) + " milliseconds");
+
+ if (mayFailExecution && hasWarnings && failOnWarnings) {
+ throw new MojoFailureException("Compilation warnings were configured to fail the build.");
+ }
+ if (mayFailExecution && hasErrors) {
+ throw new MojoFailureException("Please check the reported syntax errors.");
+ }
+ } catch (IOException e) {
+ throw new MojoExecutionException(String.format("Cannot filter files from {%s} with includes {%s} and excludes {%s}.",
+ sourceDirectory.getAbsolutePath(), processedIncludes, processedExcludes), e);
+ }
+
+ }
+
+ public File getSourceDirectory() {
+ return sourceDirectory;
+ }
+
+ public boolean shouldFailOnWarnings() {
+ return failOnWarnings;
+ }
+
+ public boolean hasWarnings() {
+ return hasWarnings;
+ }
+
+ public boolean hasErrors() {
+ return hasErrors;
+ }
+
+ public String getIncludes() {
+ return processedIncludes;
+ }
+
+ public String getExcludes() {
+ return processedExcludes;
+ }
+
+ public List<File> getProcessedFiles() {
+ return processedFiles;
+ }
+
+ private String processIncludes() {
+ if (includes == null) {
+ return DEFAULT_INCLUDES;
+ }
+ return join(includes, ',');
+ }
+
+ private String processExcludes() {
+ if (excludes == null) {
+ return DEFAULT_EXCLUDES;
+ }
+ return join(excludes, ',');
+ }
+
+ private String join(String[] array, char joinChar) {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int index = 0; index < array.length; index++) {
+ stringBuilder.append(StringUtils.trim(array[index]));
+ if (index < array.length - 1) {
+ stringBuilder.append(joinChar);
+ }
+ }
+ return stringBuilder.toString();
+ }
+
+ private CompilationUnit getCompilationUnit(final File file) throws FileNotFoundException {
+ final Reader reader = new FileReader(file);
+ return new CompilationUnit() {
+ public String getScriptName() {
+ return file.getAbsolutePath().substring(sourceDirectoryLength);
+ }
+
+ public Reader getScriptReader() {
+ return reader;
+ }
+ };
+ }
+
+ // visible for testing only
+ void setBuildContext(BuildContext buildContext) {
+
+ this.buildContext = buildContext;
+ }
+}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java
deleted file mode 100644
index b15038a..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Stack;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.commons.collections.BidiMap;
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.resourceresolver.impl.console.ResourceResolverWebConsolePlugin;
-import org.apache.sling.resourceresolver.impl.helper.ResourceDecoratorTracker;
-import org.apache.sling.resourceresolver.impl.helper.ResourceResolverControl;
-import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider;
-import org.apache.sling.resourceresolver.impl.mapping.MapEntries;
-import org.apache.sling.resourceresolver.impl.mapping.Mapping;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The <code>CommonResourceResolverFactoryImpl</code> is a singleton
- * implementing the shared/common functionality of all resource
- * resolver factories.
- */
-public class CommonResourceResolverFactoryImpl implements ResourceResolverFactory, MapConfigurationProvider {
-
- /** Helper for the resource resolver. */
- private MapEntries mapEntries = MapEntries.EMPTY;
-
- /** The web console plugin. */
- private ResourceResolverWebConsolePlugin plugin;
-
- /** The activator */
- private final ResourceResolverFactoryActivator activator;
-
- /**
- * Thread local holding the resource resolver stack
- */
- private ThreadLocal<Stack<WeakReference<ResourceResolver>>> resolverStackHolder = new ThreadLocal<Stack<WeakReference<ResourceResolver>>>();
-
- /** Flag indicating whether this factory is still active. */
- private final AtomicBoolean isActive = new AtomicBoolean(true);
-
- /** The reference queue to handle disposing of resource resolver instances. */
- private final ReferenceQueue<ResourceResolver> resolverReferenceQueue = new ReferenceQueue<ResourceResolver>();
-
- /** All weak references for the resource resolver instances. */
- private final Map<Integer, ResolverWeakReference> refs = new ConcurrentHashMap<Integer, CommonResourceResolverFactoryImpl.ResolverWeakReference>();
-
- /** Background thread handling disposing of resource resolver instances. */
- private final Thread refQueueThread;
-
- private boolean logResourceResolverClosing = false;
-
- /**
- * Create a new common resource resolver factory.
- */
- public CommonResourceResolverFactoryImpl(final ResourceResolverFactoryActivator activator) {
- this.activator = activator;
- this.logResourceResolverClosing = activator.shouldLogResourceResolverClosing();
- this.refQueueThread = new Thread("Apache Sling Resource Resolver Finalizer Thread") {
-
- @Override
- public void run() {
- while ( isActive.get() ) {
- try {
- final ResolverWeakReference ref = (ResolverWeakReference) resolverReferenceQueue.remove();
- try {
- ref.close();
- } catch ( final Throwable t ) {
- // we ignore everything from there to not stop this thread
- }
- refs.remove(ref.control.hashCode());
- } catch ( final InterruptedException ie) {
- Thread.currentThread().interrupt();
- }
- }
- for(final ResolverWeakReference ref : refs.values()) {
- ref.close();
- }
- refs.clear();
- }
-
- };
- this.refQueueThread.setDaemon(true);
- this.refQueueThread.start();
- }
-
- // ---------- Resource Resolver Factory ------------------------------------
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolverFactory#getAdministrativeResourceResolver(java.util.Map)
- */
- @Override
- public ResourceResolver getAdministrativeResourceResolver(final Map<String, Object> passedAuthenticationInfo)
- throws LoginException {
- if ( !isActive.get() ) {
- throw new LoginException("ResourceResolverFactory is deactivated.");
- }
-
- // create a copy of the passed authentication info as we modify the map
- final Map<String, Object> authenticationInfo = new HashMap<String, Object>();
- authenticationInfo.put(ResourceProvider.AUTH_ADMIN, Boolean.TRUE);
- if ( passedAuthenticationInfo != null ) {
- authenticationInfo.putAll(passedAuthenticationInfo);
- // make sure there is no leaking of service bundle and info props
- authenticationInfo.remove(ResourceProvider.AUTH_SERVICE_BUNDLE);
- authenticationInfo.remove(SUBSERVICE);
- }
-
- return getResourceResolverInternal(authenticationInfo, true);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolverFactory#getResourceResolver(java.util.Map)
- */
- @Override
- public ResourceResolver getResourceResolver(final Map<String, Object> passedAuthenticationInfo)
- throws LoginException {
- if ( !isActive.get() ) {
- throw new LoginException("ResourceResolverFactory is deactivated.");
- }
-
- // create a copy of the passed authentication info as we modify the map
- final Map<String, Object> authenticationInfo = new HashMap<String, Object>();
- if ( passedAuthenticationInfo != null ) {
- authenticationInfo.putAll(passedAuthenticationInfo);
- // make sure there is no leaking of service bundle and info props
- authenticationInfo.remove(ResourceProvider.AUTH_SERVICE_BUNDLE);
- authenticationInfo.remove(SUBSERVICE);
- }
-
- final ResourceResolver result = getResourceResolverInternal(authenticationInfo, false);
- Stack<WeakReference<ResourceResolver>> resolverStack = resolverStackHolder.get();
- if ( resolverStack == null ) {
- resolverStack = new Stack<WeakReference<ResourceResolver>>();
- resolverStackHolder.set(resolverStack);
- }
- resolverStack.push(new WeakReference<ResourceResolver>(result));
- return result;
- }
-
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolverFactory#getThreadResourceResolver()
- */
- @Override
- public ResourceResolver getThreadResourceResolver() {
- if ( !isActive.get() ) {
- return null;
- }
-
- ResourceResolver result = null;
- final Stack<WeakReference<ResourceResolver>> resolverStack = resolverStackHolder.get();
- if ( resolverStack != null) {
- while ( result == null && !resolverStack.isEmpty() ) {
- result = resolverStack.peek().get();
- if ( result == null ) {
- resolverStack.pop();
- }
- }
- }
- return result;
- }
-
- // ---------- Implementation helpers --------------------------------------
-
- /**
- * Inform about a new resource resolver instance.
- * We create a weak reference to be able to close the resolver if close on the
- * resource resolver is never called.
- * @param resolver The resource resolver
- * @param ctrl The resource resolver control
- */
- public void register(final ResourceResolver resolver,
- final ResourceResolverControl ctrl) {
- // create new weak reference
- refs.put(ctrl.hashCode(), new ResolverWeakReference(resolver, this.resolverReferenceQueue, ctrl));
- }
-
- /**
- * Inform about a closed resource resolver.
- * Make sure to remove it from the current thread context.
- * @param resourceResolverImpl The resource resolver
- * @param ctrl The resource resolver control
- */
- public void unregister(final ResourceResolver resourceResolverImpl,
- final ResourceResolverControl ctrl) {
- // close the context
- ctrl.close();
- // remove it from the set of weak references.
- refs.remove(ctrl.hashCode());
-
- // on shutdown, the factory might already be closed before the resolvers close
- // therefore we have to check for null
- final ThreadLocal<Stack<WeakReference<ResourceResolver>>> tl = resolverStackHolder;
- if ( tl != null ) {
- final Stack<WeakReference<ResourceResolver>> resolverStack = tl.get();
- if ( resolverStack != null ) {
- final Iterator<WeakReference<ResourceResolver>> i = resolverStack.iterator();
- while ( i.hasNext() ) {
- final WeakReference<ResourceResolver> ref = i.next();
- if ( ref.get() == null || ref.get() == resourceResolverImpl ) {
- i.remove();
- }
- }
- if ( resolverStack.isEmpty() ) {
- tl.remove();
- }
- }
- }
- }
-
- /**
- * Create a new ResourceResolver
- * @param authenticationInfo The authentication map
- * @param isAdmin is an administrative resolver requested?
- * @return A resource resolver
- * @throws LoginException if login to any of the required resource providers fails.
- */
- public ResourceResolver getResourceResolverInternal(final Map<String, Object> authenticationInfo,
- final boolean isAdmin)
- throws LoginException {
- if ( !isActive.get() ) {
- throw new LoginException("ResourceResolverFactory is deactivated.");
- }
-
- return new ResourceResolverImpl(this, isAdmin, authenticationInfo);
- }
-
- public MapEntries getMapEntries() {
- return mapEntries;
- }
-
- /** Activates this component */
- protected void activate(final BundleContext bundleContext) {
- final Logger logger = LoggerFactory.getLogger(getClass());
- try {
- plugin = new ResourceResolverWebConsolePlugin(bundleContext, this, this.activator.getRuntimeService());
- } catch (final Throwable ignore) {
- // an exception here probably means the web console plugin is not
- // available
- logger.debug("activate: unable to setup web console plugin.", ignore);
- }
- // set up the map entries from configuration
- try {
- mapEntries = new MapEntries(this, bundleContext, this.activator.getEventAdmin());
- } catch (final Exception e) {
- logger.error("activate: Cannot access repository, failed setting up Mapping Support", e);
- }
- }
-
- /**
- * Deactivates this component
- */
- protected void deactivate() {
- isActive.set(false);
- this.refQueueThread.interrupt();
- if (plugin != null) {
- plugin.dispose();
- plugin = null;
- }
-
- if (mapEntries != null) {
- mapEntries.dispose();
- mapEntries = MapEntries.EMPTY;
- }
- resolverStackHolder = null;
- }
-
- public ResourceDecoratorTracker getResourceDecoratorTracker() {
- return this.activator.getResourceDecoratorTracker();
- }
-
- public String[] getSearchPath() {
- return this.activator.getSearchPath();
- }
-
- public boolean isMangleNamespacePrefixes() {
- return this.activator.isMangleNamespacePrefixes();
- }
-
- @Override
- public String getMapRoot() {
- return this.activator.getMapRoot();
- }
-
- @Override
- public Mapping[] getMappings() {
- return this.activator.getMappings();
- }
-
- @Override
- public BidiMap getVirtualURLMap() {
- return this.activator.getVirtualURLMap();
- }
-
- @Override
- public int getDefaultVanityPathRedirectStatus() {
- return this.activator.getDefaultVanityPathRedirectStatus();
- }
-
- /**
- * get's the ServiceTracker of the ResourceAccessSecurity service
- */
- public ResourceAccessSecurityTracker getResourceAccessSecurityTracker () {
- return this.activator.getResourceAccessSecurityTracker();
- }
-
- @Override
- public ResourceResolver getServiceResourceResolver(
- final Map<String, Object> authenticationInfo) throws LoginException {
- throw new IllegalStateException("This method is not implemented.");
- }
-
- @Override
- public boolean isVanityPathEnabled() {
- return this.activator.isVanityPathEnabled();
- }
-
- @Override
- public long getMaxCachedVanityPathEntries() {
- return this.activator.getMaxCachedVanityPathEntries();
- }
-
- @Override
- public boolean isMaxCachedVanityPathEntriesStartup() {
- return this.activator.isMaxCachedVanityPathEntriesStartup();
- }
-
- @Override
- public int getVanityBloomFilterMaxBytes() {
- return this.activator.getVanityBloomFilterMaxBytes();
- }
-
- @Override
- public boolean isOptimizeAliasResolutionEnabled() {
- return this.activator.isOptimizeAliasResolutionEnabled();
- }
-
- @Override
- public boolean hasVanityPathPrecedence() {
- return this.activator.hasVanityPathPrecedence();
- }
-
- @Override
- public List<VanityPathConfig> getVanityPathConfig() {
- final String[] includes = this.activator.getVanityPathWhiteList();
- final String[] excludes = this.activator.getVanityPathBlackList();
- if ( includes == null && excludes == null ) {
- return null;
- }
- final List<VanityPathConfig> configs = new ArrayList<VanityPathConfig>();
- if ( includes != null ) {
- for(final String val : includes) {
- configs.add(new VanityPathConfig(val, false));
- }
- }
- if ( excludes != null ) {
- for(final String val : excludes) {
- configs.add(new VanityPathConfig(val, true));
- }
- }
- Collections.sort(configs);
- return configs;
- }
-
- /**
- * Is this factory still alive?
- */
- public boolean isLive() {
- return this.isActive.get();
- }
-
- public boolean shouldLogResourceResolverClosing() {
- return logResourceResolverClosing;
- }
-
- public ResourceProviderTracker getResourceProviderTracker() {
- return activator.getResourceProviderTracker();
- }
-
- /**
- * Extension of a weak reference to be able to get the control object
- * that is used for cleaning up.
- */
- private static final class ResolverWeakReference extends WeakReference<ResourceResolver> {
-
- private final ResourceResolverControl control;
-
- public ResolverWeakReference(final ResourceResolver referent,
- final ReferenceQueue<? super ResourceResolver> q,
- final ResourceResolverControl ctrl) {
- super(referent, q);
- this.control = ctrl;
- }
-
- public void close() {
- this.control.close();
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/FactoryPreconditions.java b/src/main/java/org/apache/sling/resourceresolver/impl/FactoryPreconditions.java
deleted file mode 100644
index 24cad65..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/FactoryPreconditions.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.sling.resourceresolver.impl.legacy.LegacyResourceProviderWhiteboard;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Helper class which checks whether all conditions for registering
- * the resource resolver factory are fulfilled.
- */
-public class FactoryPreconditions {
-
- private static final class RequiredProvider {
- public String name;
- public String pid;
- public Filter filter;
- };
-
- private volatile ResourceProviderTracker tracker;
-
- private volatile List<RequiredProvider> requiredProviders;
-
- public void activate(final BundleContext bc,
- final String[] legycyConfiguration,
- final String[] namesConfiguration,
- final ResourceProviderTracker tracker) {
- synchronized ( this ) {
- this.tracker = tracker;
-
- final List<RequiredProvider> rps = new ArrayList<RequiredProvider>();
- if ( legycyConfiguration != null ) {
- final Logger logger = LoggerFactory.getLogger(getClass());
- for(final String r : legycyConfiguration) {
- if ( r != null && r.trim().length() > 0 ) {
- final String value = r.trim();
- RequiredProvider rp = new RequiredProvider();
- if ( value.startsWith("(") ) {
- try {
- rp.filter = bc.createFilter(value);
- } catch (final InvalidSyntaxException e) {
- logger.warn("Ignoring invalid filter syntax for required provider: " + value, e);
- rp = null;
- }
- } else {
- rp.pid = value;
- }
- if ( rp != null ) {
- rps.add(rp);
- }
- }
- }
- }
- if ( namesConfiguration != null ) {
- for(final String r : namesConfiguration) {
- final String value = r.trim();
- if ( !value.isEmpty() ) {
- final RequiredProvider rp = new RequiredProvider();
- rp.name = value;
- rps.add(rp);
- }
- }
- }
- this.requiredProviders = rps;
- }
- }
-
- public void deactivate() {
- synchronized ( this ) {
- this.requiredProviders = null;
- this.tracker = null;
- }
- }
-
- public boolean checkPreconditions(final String unavailableName, final String unavailableServicePid) {
- synchronized ( this ) {
- final List<RequiredProvider> localRequiredProviders = this.requiredProviders;
- final ResourceProviderTracker localTracker = this.tracker;
- boolean canRegister = localTracker != null;
- if (localRequiredProviders != null && localTracker != null ) {
- for (final RequiredProvider rp : localRequiredProviders) {
- canRegister = false;
- for (final ResourceProviderHandler h : localTracker.getResourceProviderStorage().getAllHandlers()) {
- final ServiceReference ref = h.getInfo().getServiceReference();
- final Object servicePid = ref.getProperty(Constants.SERVICE_PID);
- if ( unavailableServicePid != null && unavailableServicePid.equals(servicePid) ) {
- // ignore this service
- continue;
- }
- if ( unavailableName != null && unavailableName.equals(h.getInfo().getName()) ) {
- // ignore this service
- continue;
- }
- if ( rp.name != null && rp.name.equals(h.getInfo().getName()) ) {
- canRegister = true;
- break;
- } else if (rp.filter != null && rp.filter.match(ref)) {
- canRegister = true;
- break;
- } else if (rp.pid != null && rp.pid.equals(servicePid)){
- canRegister = true;
- break;
- } else if (rp.pid != null && rp.pid.equals(ref.getProperty(LegacyResourceProviderWhiteboard.ORIGINAL_SERVICE_PID))) {
- canRegister = true;
- break;
- }
- }
- if ( !canRegister ) {
- break;
- }
- }
- }
- return canRegister;
- }
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceAccessSecurityTracker.java b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceAccessSecurityTracker.java
deleted file mode 100644
index 0e12d42..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceAccessSecurityTracker.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.ReferencePolicyOption;
-import org.apache.felix.scr.annotations.Service;
-import org.apache.sling.api.security.ResourceAccessSecurity;
-
-/**
- * This internal helper class keeps track of the resource access security services
- * and always returns the one with the highest service ranking.
- */
-@Component
-@Service(value=ResourceAccessSecurityTracker.class)
-public class ResourceAccessSecurityTracker {
-
- @Reference(policyOption=ReferencePolicyOption.GREEDY,
- cardinality=ReferenceCardinality.OPTIONAL_UNARY,
- policy=ReferencePolicy.DYNAMIC,
- target="(" + ResourceAccessSecurity.CONTEXT + "=" + ResourceAccessSecurity.APPLICATION_CONTEXT + ")")
- private volatile ResourceAccessSecurity applicationResourceAccessSecurity;
-
- @Reference(policyOption=ReferencePolicyOption.GREEDY,
- cardinality=ReferenceCardinality.OPTIONAL_UNARY,
- policy=ReferencePolicy.DYNAMIC,
- target="(" + ResourceAccessSecurity.CONTEXT + "=" + ResourceAccessSecurity.PROVIDER_CONTEXT + ")")
- private volatile ResourceAccessSecurity providerResourceAccessSecurity;
-
- public ResourceAccessSecurity getApplicationResourceAccessSecurity() {
- return this.applicationResourceAccessSecurity;
- }
-
- public ResourceAccessSecurity getProviderResourceAccessSecurity() {
- return this.providerResourceAccessSecurity;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java
deleted file mode 100644
index abb7a56..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.collections.BidiMap;
-import org.apache.commons.collections.bidimap.TreeBidiMap;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Properties;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyUnbounded;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.References;
-import org.apache.sling.api.resource.ResourceDecorator;
-import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.api.resource.runtime.RuntimeService;
-import org.apache.sling.commons.osgi.PropertiesUtil;
-import org.apache.sling.resourceresolver.impl.helper.ResourceDecoratorTracker;
-import org.apache.sling.resourceresolver.impl.mapping.MapEntries;
-import org.apache.sling.resourceresolver.impl.mapping.Mapping;
-import org.apache.sling.resourceresolver.impl.observation.ResourceChangeListenerWhiteboard;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker.ChangeListener;
-import org.apache.sling.resourceresolver.impl.providers.RuntimeServiceImpl;
-import org.apache.sling.serviceusermapping.ServiceUserMapper;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.component.ComponentContext;
-import org.osgi.service.event.EventAdmin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The <code>ResourceResolverFactoryActivator/code> keeps track of required services for the
- * resource resolver factory.
- * One all required providers and provider factories are available a resource resolver factory
- * is registered.
- *
- */
-@Component(
- name = "org.apache.sling.jcr.resource.internal.JcrResourceResolverFactoryImpl",
- label = "Apache Sling Resource Resolver Factory",
- description = "Configures the Resource Resolver for request URL and resource path rewriting.",
- specVersion = "1.1",
- metatype = true)
-@Properties({
- @Property(name = Constants.SERVICE_DESCRIPTION, value = "Apache Sling Resource Resolver Factory"),
- @Property(name = Constants.SERVICE_VENDOR, value = "The Apache Software Foundation")
-})
-@References({
- @Reference(name = "ResourceDecorator", referenceInterface = ResourceDecorator.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC)
-})
-public class ResourceResolverFactoryActivator {
-
- private static final class FactoryRegistration {
- /** Registration .*/
- public volatile ServiceRegistration factoryRegistration;
-
- /** Runtime registration. */
- public volatile ServiceRegistration runtimeRegistration;
-
- public volatile CommonResourceResolverFactoryImpl commonFactory;
- }
-
- @Property(value = { "/apps", "/libs" },
- label = "Resource Search Path",
- description = "The list of absolute path prefixes " +
- "applied to find resources whose path is just specified with a relative path. " +
- "The default value is [ \"/apps\", \"/libs\" ]. If an empty path is specified a " +
- "single entry path of [ \"/\" ] is assumed.")
- public static final String PROP_PATH = "resource.resolver.searchpath";
-
- /**
- * Defines whether namespace prefixes of resource names inside the path
- * (e.g. <code>jcr:</code> in <code>/home/path/jcr:content</code>) are
- * mangled or not.
- * <p>
- * Mangling means that any namespace prefix contained in the path is replaced as per the generic
- * substitution pattern <code>/([^:]+):/_$1_/</code> when calling the <code>map</code> method of
- * the resource resolver. Likewise the <code>resolve</code> methods will unmangle such namespace
- * prefixes according to the substitution pattern <code>/_([^_]+)_/$1:/</code>.
- * <p>
- * This feature is provided since there may be systems out there in the wild which cannot cope
- * with URLs containing colons, even though they are perfectly valid characters in the path part
- * of URI references with a scheme.
- * <p>
- * The default value of this property if no configuration is provided is <code>true</code>.
- *
- */
- @Property(boolValue = true,
- label = "Namespace Mangling",
- description = "Defines whether namespace " +
- "prefixes of resource names inside the path (e.g. \"jcr:\" in \"/home/path/jcr:content\") " +
- "are mangled or not. Mangling means that any namespace prefix contained in the " +
- "path is replaced as per the generic substitution pattern \"/([^:]+):/_$1_/\" " +
- "when calling the \"map\" method of the resource resolver. Likewise the " +
- "\"resolve\" methods will unmangle such namespace prefixes according to the " +
- "substituation pattern \"/_([^_]+)_/$1:/\". This feature is provided since " +
- "there may be systems out there in the wild which cannot cope with URLs " +
- "containing colons, even though they are perfectly valid characters in the " +
- "path part of URI references with a scheme. The default value of this property " +
- "if no configuration is provided is \"true\".")
- private static final String PROP_MANGLE_NAMESPACES = "resource.resolver.manglenamespaces";
-
- @Property(boolValue = true,
- label = "Allow Direct Mapping",
- description = "Whether to add a direct URL mapping to the front of the mapping list.")
- private static final String PROP_ALLOW_DIRECT = "resource.resolver.allowDirect";
-
- @Property(unbounded=PropertyUnbounded.ARRAY,
- label = "Required Providers (Deprecated)",
- description = "A resource resolver factory is only " +
- "available (registered) if all resource providers mentioned in this configuration " +
- "are available. Each entry is either a service PID or a filter expression. " +
- "Invalid filters are ignored.")
- private static final String PROP_REQUIRED_PROVIDERS_LEGACY = "resource.resolver.required.providers";
-
- @Property(unbounded=PropertyUnbounded.ARRAY,
- value = "JCR",
- label = "Required Providers ",
- description = "A resource resolver factory is only " +
- "available (registered) if all resource providers mentioned in this configuration " +
- "are available. Each entry is refers to the name of a registered provider.")
- private static final String PROP_REQUIRED_PROVIDERS = "resource.resolver.required.providernames";
-
- /**
- * The resolver.virtual property has no default configuration. But the Sling
- * maven plugin and the sling management console cannot handle empty
- * multivalue properties at the moment. So we just add a dummy direct
- * mapping.
- */
- @Property(value = "/:/", unbounded = PropertyUnbounded.ARRAY,
- label = "Virtual URLs",
- description = "List of virtual URLs and there mappings to real URLs. " +
- "Format is <externalURL>:<internalURL>. Mappings are " +
- "applied on the complete request URL only.")
- private static final String PROP_VIRTUAL = "resource.resolver.virtual";
-
- @Property(value = { "/:/", "/content/:/", "/system/docroot/:/" },
- label = "URL Mappings",
- description = "List of mappings to apply to paths. Incoming mappings are " +
- "applied to request paths to map to resource paths, " +
- "outgoing mappings are applied to map resource paths to paths used on subsequent " +
- "requests. Form is <internalPathPrefix><op><externalPathPrefix> where <op> is " +
- "\">\" for incoming mappings, \"<\" for outgoing mappings and \":\" for mappings " +
- "applied in both directions. Mappings are applied in configuration order by " +
- "comparing and replacing URL prefixes. Note: The use of \"-\" as the <op> value " +
- "indicating a mapping in both directions is deprecated.")
- private static final String PROP_MAPPING = "resource.resolver.mapping";
-
- @Property(value = MapEntries.DEFAULT_MAP_ROOT,
- label = "Mapping Location",
- description = "The path to the root of the configuration to setup and configure " +
- "the ResourceResolver mapping. The default value is /etc/map.")
- private static final String PROP_MAP_LOCATION = "resource.resolver.map.location";
-
- @Property(intValue = MapEntries.DEFAULT_DEFAULT_VANITY_PATH_REDIRECT_STATUS,
- label = "Default Vanity Path Redirect Status",
- description = "The default status code used when a sling:vanityPath is configured to redirect " +
- "and does not have a specific status code associated with it " +
- "(via a sling:redirectStatus property)")
- private static final String PROP_DEFAULT_VANITY_PATH_REDIRECT_STATUS = "resource.resolver.default.vanity.redirect.status";
-
- private static final boolean DEFAULT_ENABLE_VANITY_PATH = true;
- @Property(boolValue = DEFAULT_ENABLE_VANITY_PATH,
- label = "Enable Vanity Paths",
- description = "This flag controls whether all resources with a sling:vanityPath property " +
- "are processed and added to the mappoing table.")
- private static final String PROP_ENABLE_VANITY_PATH = "resource.resolver.enable.vanitypath";
-
- private static final long DEFAULT_MAX_CACHED_VANITY_PATHS = -1;
- @Property(longValue = DEFAULT_MAX_CACHED_VANITY_PATHS,
- label = "Maximum number of cached vanity path entries",
- description = "The maximum number of cached vanity path entries. " +
- "Default is -1 (no limit)")
- private static final String PROP_MAX_CACHED_VANITY_PATHS = "resource.resolver.vanitypath.maxEntries";
-
- private static final boolean DEFAULT_MAX_CACHED_VANITY_PATHS_STARTUP = true;
- @Property(boolValue = DEFAULT_MAX_CACHED_VANITY_PATHS_STARTUP,
- label = "Limit the maximum number of cached vanity path entries only at startup",
- description = "Limit the maximum number of cached vanity path entries only at startup. " +
- "Default is true")
- private static final String PROP_MAX_CACHED_VANITY_PATHS_STARTUP = "resource.resolver.vanitypath.maxEntries.startup";
-
- private static final int DEFAULT_VANITY_BLOOM_FILTER_MAX_BYTES = 1024000;
- @Property(longValue = DEFAULT_VANITY_BLOOM_FILTER_MAX_BYTES,
- label = "Maximum number of vanity bloom filter bytes",
- description = "The maximum number of vanity bloom filter bytes. " +
- "Changing this value is subject to vanity bloom filter rebuild")
- private static final String PROP_VANITY_BLOOM_FILTER_MAX_BYTES = " resource.resolver.vanitypath.bloomfilter.maxBytes";
-
- private static final boolean DEFAULT_ENABLE_OPTIMIZE_ALIAS_RESOLUTION = true;
- @Property(boolValue = DEFAULT_ENABLE_OPTIMIZE_ALIAS_RESOLUTION ,
- label = "Optimize alias resolution",
- description ="This flag controls whether to optimize" +
- " the alias resolution by creating an internal cache of aliases. This might have an impact on the startup time"+
- " and on the alias update time if the number of aliases is huge (over 10000).")
- private static final String PROP_ENABLE_OPTIMIZE_ALIAS_RESOLUTION = "resource.resolver.optimize.alias.resolution";
-
- @Property(unbounded=PropertyUnbounded.ARRAY,
- label = "Allowed Vanity Path Location",
- description ="This setting can contain a list of path prefixes, e.g. /libs/, /content/. If " +
- "such a list is configured, only vanity paths from resources starting with this prefix " +
- " are considered. If the list is empty, all vanity paths are used.")
- private static final String PROP_ALLOWED_VANITY_PATH_PREFIX = "resource.resolver.vanitypath.whitelist";
-
- @Property(unbounded=PropertyUnbounded.ARRAY,
- label = "Denied Vanity Path Location",
- description ="This setting can contain a list of path prefixes, e.g. /misc/. If " +
- "such a list is configured,vanity paths from resources starting with this prefix " +
- " are not considered. If the list is empty, all vanity paths are used.")
- private static final String PROP_DENIED_VANITY_PATH_PREFIX = "resource.resolver.vanitypath.blacklist";
-
- private static final boolean DEFAULT_VANITY_PATH_PRECEDENCE = false;
- @Property(boolValue = DEFAULT_VANITY_PATH_PRECEDENCE ,
- label = "Vanity Path Precedence",
- description ="This flag controls whether vanity paths" +
- " will have precedence over existing /etc/map mapping")
- private static final String PROP_VANITY_PATH_PRECEDENCE = "resource.resolver.vanity.precedence";
-
- private static final boolean DEFAULT_PARANOID_PROVIDER_HANDLING = false;
- @Property(boolValue = DEFAULT_PARANOID_PROVIDER_HANDLING,
- label = "Paranoid Provider Handling",
- description = "If this flag is enabled, an unregistration of a resource provider (not factory), "
- + "is causing the resource resolver factory to restart, potentially cleaning up "
- + "for memory leaks caused by objects hold from that resource provider.")
- private static final String PROP_PARANOID_PROVIDER_HANDLING = "resource.resolver.providerhandling.paranoid";
-
- private static final boolean DEFAULT_LOG_RESOURCE_RESOLVER_CLOSING = false;
- @Property(boolValue = DEFAULT_LOG_RESOURCE_RESOLVER_CLOSING,
- label = "Log resource resolver closing",
- description = "When enabled CRUD operations with a closed resource resolver will log a stack trace " +
- "with the point where the used resolver was closed. It's advisable to not enable this feature on " +
- "production systems.")
- private static final String PROP_LOG_RESOURCE_RESOLVER_CLOSING = "resource.resolver.log.closing";
-
- /** Logger. */
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- /** Tracker for the resource decorators. */
- private final ResourceDecoratorTracker resourceDecoratorTracker = new ResourceDecoratorTracker();
-
- /** all mappings */
- private volatile Mapping[] mappings;
-
- /** The fake URLs */
- private volatile BidiMap virtualURLMap;
-
- /** <code>true</code>, if direct mappings from URI to handle are allowed */
- private volatile boolean allowDirect = false;
-
- /** the search path for ResourceResolver.getResource(String) */
- private volatile String[] searchPath;
-
- /** the root location of the /etc/map entries */
- private volatile String mapRoot;
-
- /** whether to mangle paths with namespaces or not */
- private volatile boolean mangleNamespacePrefixes;
-
- /** paranoid provider handling. */
- private volatile boolean paranoidProviderHandling;
-
- /** Event admin. */
- @Reference
- EventAdmin eventAdmin;
-
- /** Service User Mapper */
- @Reference
- private ServiceUserMapper serviceUserMapper;
-
- @Reference
- ResourceAccessSecurityTracker resourceAccessSecurityTracker;
-
- volatile ResourceProviderTracker resourceProviderTracker;
-
- volatile ResourceChangeListenerWhiteboard changeListenerWhiteboard;
-
- /** ComponentContext */
- private volatile ComponentContext componentContext;
-
- private volatile int defaultVanityPathRedirectStatus;
-
- /** vanityPath enabled? */
- private volatile boolean enableVanityPath = DEFAULT_ENABLE_VANITY_PATH;
-
- /** alias resource resolution optimization enabled? */
- private volatile boolean enableOptimizeAliasResolution = DEFAULT_ENABLE_OPTIMIZE_ALIAS_RESOLUTION;
-
- /** max number of cache vanity path entries */
- private volatile long maxCachedVanityPathEntries = DEFAULT_MAX_CACHED_VANITY_PATHS;
-
- /** limit max number of cache vanity path entries only at startup*/
- private volatile boolean maxCachedVanityPathEntriesStartup = DEFAULT_MAX_CACHED_VANITY_PATHS_STARTUP;
-
- /** Maximum number of vanity bloom filter bytes */
- private volatile int vanityBloomFilterMaxBytes = DEFAULT_VANITY_BLOOM_FILTER_MAX_BYTES;
-
- /** vanity paths will have precedence over existing /etc/map mapping? */
- private volatile boolean vanityPathPrecedence = DEFAULT_VANITY_PATH_PRECEDENCE;
-
- /** log the place where a resource resolver is closed */
- private volatile boolean logResourceResolverClosing = DEFAULT_LOG_RESOURCE_RESOLVER_CLOSING;
-
- /** Vanity path whitelist */
- private volatile String[] vanityPathWhiteList;
-
- /** Vanity path blacklist */
- private volatile String[] vanityPathBlackList;
-
- private final FactoryPreconditions preconds = new FactoryPreconditions();
-
- /** Factory registration. */
- private volatile FactoryRegistration factoryRegistration;
-
- /**
- * Get the resource decorator tracker.
- */
- public ResourceDecoratorTracker getResourceDecoratorTracker() {
- return this.resourceDecoratorTracker;
- }
-
- public ResourceAccessSecurityTracker getResourceAccessSecurityTracker() {
- return this.resourceAccessSecurityTracker;
- }
-
- public EventAdmin getEventAdmin() {
- return this.eventAdmin;
- }
-
- /**
- * This method is called from {@link MapEntries}
- */
- public BidiMap getVirtualURLMap() {
- return virtualURLMap;
- }
-
- /**
- * This method is called from {@link MapEntries}
- */
- public Mapping[] getMappings() {
- return mappings;
- }
-
- public String[] getSearchPath() {
- return searchPath;
- }
-
- public boolean isMangleNamespacePrefixes() {
- return mangleNamespacePrefixes;
-
- }
-
- public String getMapRoot() {
- return mapRoot;
- }
-
- public int getDefaultVanityPathRedirectStatus() {
- return defaultVanityPathRedirectStatus;
- }
-
- public boolean isVanityPathEnabled() {
- return this.enableVanityPath;
- }
-
- public boolean isOptimizeAliasResolutionEnabled() {
- return this.enableOptimizeAliasResolution;
- }
-
- public String[] getVanityPathWhiteList() {
- return this.vanityPathWhiteList;
- }
-
- public String[] getVanityPathBlackList() {
- return this.vanityPathBlackList;
- }
-
- public boolean hasVanityPathPrecedence() {
- return this.vanityPathPrecedence;
- }
-
- public long getMaxCachedVanityPathEntries() {
- return this.maxCachedVanityPathEntries;
- }
-
- public boolean isMaxCachedVanityPathEntriesStartup() {
- return this.maxCachedVanityPathEntriesStartup;
- }
-
- public int getVanityBloomFilterMaxBytes() {
- return this.vanityBloomFilterMaxBytes;
- }
-
- public boolean shouldLogResourceResolverClosing() {
- return logResourceResolverClosing;
- }
-
- // ---------- SCR Integration ---------------------------------------------
-
- /**
- * Activates this component, called by SCR before registering as a service
- */
- @Activate
- protected void activate(final ComponentContext componentContext) {
- this.componentContext = componentContext;
- final Dictionary<?, ?> properties = componentContext.getProperties();
-
- final BidiMap virtuals = new TreeBidiMap();
- final String[] virtualList = PropertiesUtil.toStringArray(properties.get(PROP_VIRTUAL));
- for (int i = 0; virtualList != null && i < virtualList.length; i++) {
- final String[] parts = Mapping.split(virtualList[i]);
- virtuals.put(parts[0], parts[2]);
- }
- virtualURLMap = virtuals;
-
- final List<Mapping> maps = new ArrayList<Mapping>();
- final String[] mappingList = (String[]) properties.get(PROP_MAPPING);
- for (int i = 0; mappingList != null && i < mappingList.length; i++) {
- maps.add(new Mapping(mappingList[i]));
- }
- final Mapping[] tmp = maps.toArray(new Mapping[maps.size()]);
-
- // check whether direct mappings are allowed
- final Boolean directProp = (Boolean) properties.get(PROP_ALLOW_DIRECT);
- allowDirect = (directProp != null) ? directProp.booleanValue() : true;
- if (allowDirect) {
- final Mapping[] tmp2 = new Mapping[tmp.length + 1];
- tmp2[0] = Mapping.DIRECT;
- System.arraycopy(tmp, 0, tmp2, 1, tmp.length);
- mappings = tmp2;
- } else {
- mappings = tmp;
- }
-
- // from configuration if available
- searchPath = PropertiesUtil.toStringArray(properties.get(PROP_PATH));
- if (searchPath != null && searchPath.length > 0) {
- for (int i = 0; i < searchPath.length; i++) {
- // ensure leading slash
- if (!searchPath[i].startsWith("/")) {
- searchPath[i] = "/" + searchPath[i];
- }
- // ensure trailing slash
- if (!searchPath[i].endsWith("/")) {
- searchPath[i] += "/";
- }
- }
- }
- if (searchPath == null) {
- searchPath = new String[] { "/" };
- }
- // namespace mangling
- mangleNamespacePrefixes = PropertiesUtil.toBoolean(properties.get(PROP_MANGLE_NAMESPACES), false);
-
- // the root of the resolver mappings
- mapRoot = PropertiesUtil.toString(properties.get(PROP_MAP_LOCATION), MapEntries.DEFAULT_MAP_ROOT);
-
- defaultVanityPathRedirectStatus = PropertiesUtil.toInteger(properties.get(PROP_DEFAULT_VANITY_PATH_REDIRECT_STATUS),
- MapEntries.DEFAULT_DEFAULT_VANITY_PATH_REDIRECT_STATUS);
- this.enableVanityPath = PropertiesUtil.toBoolean(properties.get(PROP_ENABLE_VANITY_PATH), DEFAULT_ENABLE_VANITY_PATH);
- // vanity path white list
- this.vanityPathWhiteList = null;
- String[] vanityPathPrefixes = PropertiesUtil.toStringArray(properties.get(PROP_ALLOWED_VANITY_PATH_PREFIX));
- if ( vanityPathPrefixes != null ) {
- final List<String> prefixList = new ArrayList<String>();
- for(final String value : vanityPathPrefixes) {
- if ( value.trim().length() > 0 ) {
- if ( value.trim().endsWith("/") ) {
- prefixList.add(value.trim());
- } else {
- prefixList.add(value.trim() + "/");
- }
- }
- }
- if ( prefixList.size() > 0 ) {
- this.vanityPathWhiteList = prefixList.toArray(new String[prefixList.size()]);
- }
- }
- // vanity path black list
- this.vanityPathBlackList = null;
- vanityPathPrefixes = PropertiesUtil.toStringArray(properties.get(PROP_DENIED_VANITY_PATH_PREFIX));
- if ( vanityPathPrefixes != null ) {
- final List<String> prefixList = new ArrayList<String>();
- for(final String value : vanityPathPrefixes) {
- if ( value.trim().length() > 0 ) {
- if ( value.trim().endsWith("/") ) {
- prefixList.add(value.trim());
- } else {
- prefixList.add(value.trim() + "/");
- }
- }
- }
- if ( prefixList.size() > 0 ) {
- this.vanityPathBlackList = prefixList.toArray(new String[prefixList.size()]);
- }
- }
-
- this.enableOptimizeAliasResolution = PropertiesUtil.toBoolean(properties.get(PROP_ENABLE_OPTIMIZE_ALIAS_RESOLUTION), DEFAULT_ENABLE_OPTIMIZE_ALIAS_RESOLUTION);
- this.maxCachedVanityPathEntries = PropertiesUtil.toLong(properties.get(PROP_MAX_CACHED_VANITY_PATHS), DEFAULT_MAX_CACHED_VANITY_PATHS);
- this.maxCachedVanityPathEntriesStartup = PropertiesUtil.toBoolean(properties.get(PROP_MAX_CACHED_VANITY_PATHS_STARTUP), DEFAULT_MAX_CACHED_VANITY_PATHS_STARTUP);
- this.vanityBloomFilterMaxBytes = PropertiesUtil.toInteger(properties.get(PROP_VANITY_BLOOM_FILTER_MAX_BYTES), DEFAULT_VANITY_BLOOM_FILTER_MAX_BYTES);
-
- this.vanityPathPrecedence = PropertiesUtil.toBoolean(properties.get(PROP_VANITY_PATH_PRECEDENCE), DEFAULT_VANITY_PATH_PRECEDENCE);
- this.logResourceResolverClosing = PropertiesUtil.toBoolean(properties.get(PROP_LOG_RESOURCE_RESOLVER_CLOSING),
- DEFAULT_LOG_RESOURCE_RESOLVER_CLOSING);
- this.paranoidProviderHandling = PropertiesUtil.toBoolean(properties.get(PROP_PARANOID_PROVIDER_HANDLING), DEFAULT_PARANOID_PROVIDER_HANDLING);
-
- final BundleContext bc = componentContext.getBundleContext();
-
- // check for required property
- final String[] requiredResourceProvidersLegacy = PropertiesUtil.toStringArray(properties.get(PROP_REQUIRED_PROVIDERS_LEGACY));
- final String[] requiredResourceProviderNames = PropertiesUtil.toStringArray(properties.get(PROP_REQUIRED_PROVIDERS));
-
- if ( requiredResourceProvidersLegacy != null && requiredResourceProvidersLegacy.length > 0 ) {
- logger.error("ResourceResolverFactory is using deprecated required providers configuration (" + PROP_REQUIRED_PROVIDERS_LEGACY +
- "). Please change to use the property " + PROP_REQUIRED_PROVIDERS + " for values: " + Arrays.toString(requiredResourceProvidersLegacy));
- }
- // for testing: if we run unit test, both trackers are set from the outside
- if ( this.resourceProviderTracker == null ) {
- this.resourceProviderTracker = new ResourceProviderTracker();
- this.changeListenerWhiteboard = new ResourceChangeListenerWhiteboard();
- this.preconds.activate(bc, requiredResourceProvidersLegacy, requiredResourceProviderNames, resourceProviderTracker);
- this.changeListenerWhiteboard.activate(this.componentContext.getBundleContext(),
- this.resourceProviderTracker, searchPath);
- this.resourceProviderTracker.activate(this.componentContext.getBundleContext(),
- this.eventAdmin,
- new ChangeListener() {
-
- @Override
- public void providerAdded() {
- if ( factoryRegistration == null ) {
- checkFactoryPreconditions(null, null);
- }
-
- }
-
- @Override
- public void providerRemoved(final String name, final String pid, final boolean stateful, final boolean isUsed) {
- if ( factoryRegistration != null ) {
- if ( isUsed && (stateful || paranoidProviderHandling) ) {
- unregisterFactory();
- }
- checkFactoryPreconditions(name, pid);
- }
- }
- });
- } else {
- this.preconds.activate(bc, requiredResourceProvidersLegacy, requiredResourceProviderNames, resourceProviderTracker);
- this.checkFactoryPreconditions(null, null);
- }
- }
-
- /**
- * Deactivates this component (called by SCR to take out of service)
- */
- @Deactivate
- protected void deactivate() {
- this.unregisterFactory();
-
- this.componentContext = null;
-
- this.changeListenerWhiteboard.deactivate();
- this.resourceProviderTracker.deactivate();
- this.preconds.deactivate();
- this.resourceDecoratorTracker.close();
- }
-
- /**
- * Unregister the factory (if registered)
- * This method might be called concurrently from deactivate and the
- * background thread, therefore we need to synchronize.
- */
- private void unregisterFactory() {
- FactoryRegistration local = null;
- synchronized ( this ) {
- if ( this.factoryRegistration != null ) {
- local = this.factoryRegistration;
- this.factoryRegistration = null;
- }
- }
- this.unregisterFactory(local);
- }
-
- /**
- * Unregister the provided factory
- */
- private void unregisterFactory(final FactoryRegistration local) {
- if ( local != null ) {
- if ( local.factoryRegistration != null ) {
- local.factoryRegistration.unregister();
- }
- if ( local.runtimeRegistration != null ) {
- local.runtimeRegistration.unregister();
- }
- if ( local.commonFactory != null ) {
- local.commonFactory.deactivate();
- }
- }
- }
-
- /**
- * Try to register the factory.
- */
- private void registerFactory(final ComponentContext localContext) {
- final FactoryRegistration local = new FactoryRegistration();
-
- if ( localContext != null ) {
- // activate and register factory
- final Dictionary<String, Object> serviceProps = new Hashtable<String, Object>();
- serviceProps.put(Constants.SERVICE_VENDOR, localContext.getProperties().get(Constants.SERVICE_VENDOR));
- serviceProps.put(Constants.SERVICE_DESCRIPTION, localContext.getProperties().get(Constants.SERVICE_DESCRIPTION));
-
- local.commonFactory = new CommonResourceResolverFactoryImpl(this);
- local.commonFactory.activate(localContext.getBundleContext());
- local.factoryRegistration = localContext.getBundleContext().registerService(
- ResourceResolverFactory.class.getName(), new ServiceFactory() {
-
- @Override
- public Object getService(final Bundle bundle, final ServiceRegistration registration) {
- if ( ResourceResolverFactoryActivator.this.componentContext == null ) {
- return null;
- }
- final ResourceResolverFactoryImpl r = new ResourceResolverFactoryImpl(
- local.commonFactory, bundle,
- ResourceResolverFactoryActivator.this.serviceUserMapper);
- return r;
- }
-
- @Override
- public void ungetService(final Bundle bundle, final ServiceRegistration registration, final Object service) {
- // nothing to do
- }
- }, serviceProps);
-
- local.runtimeRegistration = localContext.getBundleContext().registerService(RuntimeService.class.getName(),
- this.getRuntimeService(), null);
-
- this.factoryRegistration = local;
- }
- }
-
- public RuntimeService getRuntimeService() {
- return new RuntimeServiceImpl(this.resourceProviderTracker);
- }
-
- /**
- * Check the preconditions and if it changed, either register factory or unregister
- */
- private void checkFactoryPreconditions(final String unavailableName, final String unavailableServicePid) {
- final ComponentContext localContext = this.componentContext;
- if ( localContext != null ) {
- final boolean result = this.preconds.checkPreconditions(unavailableName, unavailableServicePid);
- if ( result && this.factoryRegistration == null ) {
- boolean create = true;
- synchronized ( this ) {
- if ( this.factoryRegistration == null ) {
- this.factoryRegistration = new FactoryRegistration();
- } else {
- create = false;
- }
- }
- if ( create ) {
- this.registerFactory(localContext);
- }
- } else if ( !result && this.factoryRegistration != null ) {
- this.unregisterFactory();
- }
- }
- }
-
- /**
- * Bind a resource decorator.
- */
- protected void bindResourceDecorator(final ResourceDecorator decorator, final Map<String, Object> props) {
- this.resourceDecoratorTracker.bindResourceDecorator(decorator, props);
- }
-
- /**
- * Unbind a resource decorator.
- */
- protected void unbindResourceDecorator(final ResourceDecorator decorator, final Map<String, Object> props) {
- this.resourceDecoratorTracker.unbindResourceDecorator(decorator, props);
- }
-
- public ResourceProviderTracker getResourceProviderTracker() {
- return resourceProviderTracker;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java
deleted file mode 100644
index e0e882b..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.serviceusermapping.ServiceUserMapper;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.osgi.framework.Bundle;
-
-/**
- * The <code>ResourceResolverFactoryImpl</code> is the {@link ResourceResolverFactory} service
- * providing the following
- * functionality:
- * <ul>
- * <li><code>ResourceResolverFactory</code> service
- * <li>Fires OSGi EventAdmin events on behalf of internal helper objects
- * </ul>
- *
- */
-public class ResourceResolverFactoryImpl implements ResourceResolverFactory {
-
- private final CommonResourceResolverFactoryImpl commonFactory;
-
- private final ServiceUserMapper serviceUserMapper;
-
- private final Bundle usingBundle;
-
- public ResourceResolverFactoryImpl(
- final CommonResourceResolverFactoryImpl commonFactory,
- final Bundle usingBundle,
- final ServiceUserMapper serviceUserMapper) {
- this.commonFactory = commonFactory;
- this.serviceUserMapper = serviceUserMapper;
- this.usingBundle = usingBundle;
- }
-
- // ---------- Resource Resolver Factory ------------------------------------
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolverFactory#getServiceResourceResolver(java.util.Map)
- */
- public ResourceResolver getServiceResourceResolver(final Map<String, Object> passedAuthenticationInfo) throws LoginException {
- // create a copy of the passed authentication info as we modify the map
- final Map<String, Object> authenticationInfo = new HashMap<String, Object>();
- final String subServiceName;
- if ( passedAuthenticationInfo != null ) {
- authenticationInfo.putAll(passedAuthenticationInfo);
- authenticationInfo.remove(PASSWORD);
- final Object info = passedAuthenticationInfo.get(SUBSERVICE);
- subServiceName = (info instanceof String) ? (String) info : null;
- } else {
- subServiceName = null;
- }
-
- // Ensure a mapped user name: If no user is defined for a bundle
- // acting as a service, the user may be null. We can decide whether
- // this should yield guest access or no access at all. For now
- // no access is granted if there is no service user defined for
- // the bundle.
- final String userName = this.serviceUserMapper.getServiceUserID(this.usingBundle, subServiceName);
- if (userName == null) {
- throw new LoginException("Cannot derive user name for bundle "
- + this.usingBundle + " and sub service " + subServiceName);
- }
-
- // ensure proper user name and service bundle
- authenticationInfo.put(ResourceResolverFactory.USER, userName);
- authenticationInfo.put(ResourceProvider.AUTH_SERVICE_BUNDLE, this.usingBundle);
-
- return commonFactory.getResourceResolverInternal(authenticationInfo, false);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolverFactory#getResourceResolver(java.util.Map)
- */
- public ResourceResolver getResourceResolver(
- final Map<String, Object> authenticationInfo) throws LoginException {
- return commonFactory.getResourceResolver(authenticationInfo);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolverFactory#getAdministrativeResourceResolver(java.util.Map)
- */
- public ResourceResolver getAdministrativeResourceResolver(
- final Map<String, Object> authenticationInfo) throws LoginException {
- return commonFactory.getAdministrativeResourceResolver(authenticationInfo);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolverFactory#getThreadResourceResolver()
- */
- public ResourceResolver getThreadResourceResolver() {
- return commonFactory.getThreadResourceResolver();
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
deleted file mode 100644
index 3210a45..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java
+++ /dev/null
@@ -1,1382 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import static org.apache.commons.lang.StringUtils.defaultString;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.annotation.CheckForNull;
-import javax.jcr.NamespaceException;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.sling.adapter.annotations.Adaptable;
-import org.apache.sling.adapter.annotations.Adapter;
-import org.apache.sling.api.SlingException;
-import org.apache.sling.api.adapter.SlingAdaptable;
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.NonExistingResource;
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceNotFoundException;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.resource.ResourceWrapper;
-import org.apache.sling.resourceresolver.impl.helper.RedirectResource;
-import org.apache.sling.resourceresolver.impl.helper.ResourceIteratorDecorator;
-import org.apache.sling.resourceresolver.impl.helper.ResourcePathIterator;
-import org.apache.sling.resourceresolver.impl.helper.ResourceResolverContext;
-import org.apache.sling.resourceresolver.impl.helper.ResourceResolverControl;
-import org.apache.sling.resourceresolver.impl.helper.StarResource;
-import org.apache.sling.resourceresolver.impl.helper.URI;
-import org.apache.sling.resourceresolver.impl.helper.URIException;
-import org.apache.sling.resourceresolver.impl.mapping.MapEntry;
-import org.apache.sling.resourceresolver.impl.params.ParsedParameters;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorageProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Adaptable(adaptableClass = ResourceResolver.class, adapters = { @Adapter(Session.class) })
-public class ResourceResolverImpl extends SlingAdaptable implements ResourceResolver {
-
- /** Default logger */
- private static final Logger logger = LoggerFactory.getLogger(ResourceResolverImpl.class);
-
- private static final Map<String, String> EMPTY_PARAMETERS = Collections.emptyMap();
-
- private static final String MANGLE_NAMESPACE_IN_SUFFIX = "_";
-
- private static final String MANGLE_NAMESPACE_IN_PREFIX = "/_";
-
- private static final Pattern MANGLE_NAMESPACE_IN_PATTERN = Pattern.compile("/_([^_/]+)_");
-
- private static final String MANGLE_NAMESPACE_OUT_SUFFIX = ":";
-
- private static final String MANGLE_NAMESPACE_OUT_PREFIX = "/";
-
- private static final Pattern MANLE_NAMESPACE_OUT_PATTERN = Pattern.compile("/([^:/]+):");
-
- public static final String PROP_REDIRECT_INTERNAL = "sling:internalRedirect";
-
- public static final String PROP_ALIAS = "sling:alias";
-
- // The suffix of a resource being a content node of some parent
- // such as nt:file. The slash is included to prevent false
- // positives for the String.endsWith check for names like
- // "xyzjcr:content"
- private static final String JCR_CONTENT_LEAF = "/jcr:content";
-
- /** The factory which created this resource resolver. */
- private final CommonResourceResolverFactoryImpl factory;
-
- /** Resource resolver control. */
- private final ResourceResolverControl control;
-
- /** Resource resolver context. */
- private final ResourceResolverContext context;
-
- private volatile Exception closedResolverException;
-
- public ResourceResolverImpl(final CommonResourceResolverFactoryImpl factory, final boolean isAdmin, final Map<String, Object> authenticationInfo) throws LoginException {
- this(factory, isAdmin, authenticationInfo, factory.getResourceProviderTracker());
- }
-
- ResourceResolverImpl(final CommonResourceResolverFactoryImpl factory, final boolean isAdmin, final Map<String, Object> authenticationInfo, final ResourceProviderStorageProvider resourceProviderTracker) throws LoginException {
- this.factory = factory;
- this.context = new ResourceResolverContext(this, factory.getResourceAccessSecurityTracker());
- this.control = createControl(resourceProviderTracker, authenticationInfo, isAdmin);
- this.factory.register(this, control);
- }
-
- /**
- * Constructor for cloning the resource resolver
- * @param resolver The resolver to clone
- * @param authenticationInfo The auth info
- * @throws LoginException if auth to a required provider fails
- */
- private ResourceResolverImpl(final ResourceResolverImpl resolver, final Map<String, Object> authenticationInfo) throws LoginException {
- this.factory = resolver.factory;
- Map<String, Object> authInfo = new HashMap<String, Object>();
- if (resolver.control.getAuthenticationInfo() != null) {
- authInfo.putAll(resolver.control.getAuthenticationInfo());
- }
- if (authenticationInfo != null) {
- authInfo.putAll(authenticationInfo);
- }
- this.context = new ResourceResolverContext(this, factory.getResourceAccessSecurityTracker());
- this.control = createControl(factory.getResourceProviderTracker(), authInfo, resolver.control.isAdmin());
- this.factory.register(this, control);
- }
-
- /**
- * Create the resource resolver control
- * @param storage The provider storage
- * @param authenticationInfo Current auth info
- * @param isAdmin Is this admin?
- * @return A control
- * @throws LoginException If auth to the required providers fails.
- */
- private ResourceResolverControl createControl(final ResourceProviderStorageProvider resourceProviderTracker,
- final Map<String, Object> authenticationInfo,
- final boolean isAdmin)
- throws LoginException {
- final ResourceResolverControl control = new ResourceResolverControl(isAdmin, authenticationInfo, resourceProviderTracker);
-
- this.context.getProviderManager().authenticateAll(resourceProviderTracker.getResourceProviderStorage().getAuthRequiredHandlers(), control);
-
- return control;
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#clone(Map)
- */
- @Override
- public ResourceResolver clone(final Map<String, Object> authenticationInfo)
- throws LoginException {
- // ensure resolver is still live
- checkClosed();
-
- // create a regular resource resolver
- return new ResourceResolverImpl(this, authenticationInfo);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#isLive()
- */
- @Override
- public boolean isLive() {
- return !this.control.isClosed() && this.control.isLive(this.context) && this.factory.isLive();
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#close()
- */
- @Override
- public void close() {
- if (factory.shouldLogResourceResolverClosing()) {
- closedResolverException = new Exception("Stack Trace");
- }
- this.factory.unregister(this, this.control);
- }
-
- /**
- * Check if the resource resolver is already closed or the factory which created this resolver is no longer live.
- *
- * @throws IllegalStateException
- * If the resolver is already closed or the factory is no longer live.
- */
- private void checkClosed() {
- if (this.control.isClosed()) {
- if (closedResolverException != null) {
- logger.error("The ResourceResolver has already been closed.", closedResolverException);
- }
- throw new IllegalStateException("Resource resolver is already closed.");
- }
- if (!this.factory.isLive()) {
- throw new IllegalStateException("Resource resolver factory which created this resolver is no longer active.");
- }
- }
-
- // ---------- attributes
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#getAttributeNames()
- */
- @Override
- public Iterator<String> getAttributeNames() {
- checkClosed();
- return this.control.getAttributeNames(this.context).iterator();
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#getAttribute(String)
- */
- @Override
- public Object getAttribute(final String name) {
- checkClosed();
- if (name == null) {
- throw new NullPointerException("name");
- }
-
- return this.control.getAttribute(this.context, name);
- }
-
- // ---------- resolving resources
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#resolve(java.lang.String)
- */
- @Override
- public Resource resolve(final String path) {
- checkClosed();
-
- final Resource rsrc = this.resolveInternal(null, path);
- return rsrc;
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#resolve(javax.servlet.http.HttpServletRequest)
- */
- @SuppressWarnings("deprecation")
- @Override
- public Resource resolve(final HttpServletRequest request) {
- checkClosed();
-
- // throws NPE if request is null as required
- final Resource rsrc = this.resolveInternal(request, request.getPathInfo());
- return rsrc;
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#resolve(javax.servlet.http.HttpServletRequest,
- * java.lang.String)
- */
- @Override
- public Resource resolve(final HttpServletRequest request, String path) {
- checkClosed();
-
- final Resource rsrc = this.resolveInternal(request, path);
- return rsrc;
- }
-
- private Resource resolveInternal(final HttpServletRequest request, String absPath) {
- // make sure abspath is not null and is absolute
- if (absPath == null) {
- absPath = "/";
- } else if (!absPath.startsWith("/")) {
- absPath = "/" + absPath;
- }
-
- // check for special namespace prefix treatment
- absPath = unmangleNamespaces(absPath);
-
- // Assume http://localhost:80 if request is null
- String[] realPathList = { absPath };
- String requestPath;
- if (request != null) {
- requestPath = getMapPath(request.getScheme(), request.getServerName(), request.getServerPort(), absPath);
- } else {
- requestPath = getMapPath("http", "localhost", 80, absPath);
- }
-
- logger.debug("resolve: Resolving request path {}", requestPath);
-
- // loop while finding internal or external redirect into the
- // content out of the virtual host mapping tree
- // the counter is to ensure we are not caught in an endless loop here
- // TODO: might do better to be able to log the loop and help the user
- for (int i = 0; i < 100; i++) {
-
- String[] mappedPath = null;
-
- final Iterator<MapEntry> mapEntriesIterator = this.factory.getMapEntries().getResolveMapsIterator(requestPath);
- while (mapEntriesIterator.hasNext()) {
- final MapEntry mapEntry = mapEntriesIterator.next();
- mappedPath = mapEntry.replace(requestPath);
- if (mappedPath != null) {
- if (logger.isDebugEnabled()) {
- logger.debug("resolve: MapEntry {} matches, mapped path is {}", mapEntry, Arrays.toString(mappedPath));
- }
- if (mapEntry.isInternal()) {
- // internal redirect
- logger.debug("resolve: Redirecting internally");
- break;
- }
-
- // external redirect
- logger.debug("resolve: Returning external redirect");
- return this.factory.getResourceDecoratorTracker().decorate(
- new RedirectResource(this, absPath, mappedPath[0], mapEntry.getStatus()));
- }
- }
-
- // if there is no virtual host based path mapping, abort
- // and use the original realPath
- if (mappedPath == null) {
- logger.debug("resolve: Request path {} does not match any MapEntry", requestPath);
- break;
- }
-
- // if the mapped path is not an URL, use this path to continue
- if (!mappedPath[0].contains("://")) {
- logger.debug("resolve: Mapped path is for resource tree");
- realPathList = mappedPath;
- break;
- }
-
- // otherwise the mapped path is an URI and we have to try to
- // resolve that URI now, using the URI's path as the real path
- try {
- final URI uri = new URI(mappedPath[0], false);
- requestPath = getMapPath(uri.getScheme(), uri.getHost(), uri.getPort(), uri.getPath());
- realPathList = new String[] { uri.getPath() };
-
- logger.debug("resolve: Mapped path is an URL, using new request path {}", requestPath);
- } catch (final URIException use) {
- // TODO: log and fail
- throw new ResourceNotFoundException(absPath);
- }
- }
-
- // now we have the real path resolved from virtual host mapping
- // this path may be absolute or relative, in which case we try
- // to resolve it against the search path
-
- Resource res = null;
- for (int i = 0; res == null && i < realPathList.length; i++) {
- final ParsedParameters parsedPath = new ParsedParameters(realPathList[i]);
- final String realPath = parsedPath.getRawPath();
-
-
- // first check whether the requested resource is a StarResource
- if (StarResource.appliesTo(realPath)) {
- logger.debug("resolve: Mapped path {} is a Star Resource", realPath);
- res = new StarResource(this, ensureAbsPath(realPath));
-
- } else {
-
- if (realPath.startsWith("/")) {
-
- // let's check it with a direct access first
- logger.debug("resolve: Try absolute mapped path {}", realPath);
- res = resolveInternal(realPath, parsedPath.getParameters());
-
- } else {
-
- final String[] searchPath = getSearchPath();
- for (int spi = 0; res == null && spi < searchPath.length; spi++) {
- logger.debug("resolve: Try relative mapped path with search path entry {}", searchPath[spi]);
- res = resolveInternal(searchPath[spi] + realPath, parsedPath.getParameters());
- }
-
- }
- }
- }
-
- // if no resource has been found, use a NonExistingResource
- if (res == null) {
- final ParsedParameters parsedPath = new ParsedParameters(realPathList[0]);
- final String resourcePath = ensureAbsPath(parsedPath.getRawPath());
- logger.debug("resolve: Path {} does not resolve, returning NonExistingResource at {}", absPath, resourcePath);
-
- res = new NonExistingResource(this, resourcePath);
- // SLING-864: if the path contains a dot we assume this to be
- // the start for any selectors, extension, suffix, which may be
- // used for further request processing.
- // the resolution path must be the full path and is already set within
- // the non existing resource
- final int index = resourcePath.indexOf('.');
- if (index != -1) {
- res.getResourceMetadata().setResolutionPathInfo(resourcePath.substring(index));
- }
- res.getResourceMetadata().setParameterMap(parsedPath.getParameters());
- } else {
- logger.debug("resolve: Path {} resolves to Resource {}", absPath, res);
- }
-
- return this.factory.getResourceDecoratorTracker().decorate(res);
- }
-
- /**
- * calls map(HttpServletRequest, String) as map(null, resourcePath)
- *
- * @see org.apache.sling.api.resource.ResourceResolver#map(java.lang.String)
- */
- @Override
- public String map(final String resourcePath) {
- checkClosed();
- return map(null, resourcePath);
- }
-
- /**
- * full implementation - apply sling:alias from the resource path - apply
- * /etc/map mappings (inkl. config backwards compat) - return absolute uri
- * if possible
- *
- * @see org.apache.sling.api.resource.ResourceResolver#map(javax.servlet.http.HttpServletRequest,
- * java.lang.String)
- */
- @Override
- public String map(final HttpServletRequest request, final String resourcePath) {
- checkClosed();
-
- // find a fragment or query
- int fragmentQueryMark = resourcePath.indexOf('#');
- if (fragmentQueryMark < 0) {
- fragmentQueryMark = resourcePath.indexOf('?');
- }
-
- // cut fragment or query off the resource path
- String mappedPath;
- final String fragmentQuery;
- if (fragmentQueryMark >= 0) {
- fragmentQuery = resourcePath.substring(fragmentQueryMark);
- mappedPath = resourcePath.substring(0, fragmentQueryMark);
- logger.debug("map: Splitting resource path '{}' into '{}' and '{}'", new Object[] { resourcePath, mappedPath,
- fragmentQuery });
- } else {
- fragmentQuery = null;
- mappedPath = resourcePath;
- }
-
- // cut off scheme and host, if the same as requested
- final String schemehostport;
- final String schemePrefix;
- if (request != null) {
- schemehostport = MapEntry.getURI(request.getScheme(), request.getServerName(), request.getServerPort(), "/");
- schemePrefix = request.getScheme().concat("://");
- logger.debug("map: Mapping path {} for {} (at least with scheme prefix {})", new Object[] { resourcePath,
- schemehostport, schemePrefix });
-
- } else {
-
- schemehostport = null;
- schemePrefix = null;
- logger.debug("map: Mapping path {} for default", resourcePath);
-
- }
-
- ParsedParameters parsed = new ParsedParameters(mappedPath);
- final Resource res = resolveInternal(parsed.getRawPath(), parsed.getParameters());
-
- if (res != null) {
-
- // keep, what we might have cut off in internal resolution
- final String resolutionPathInfo = res.getResourceMetadata().getResolutionPathInfo();
-
- logger.debug("map: Path maps to resource {} with path info {}", res, resolutionPathInfo);
-
- // find aliases for segments. we can't walk the parent chain
- // since the request session might not have permissions to
- // read all parents SLING-2093
- final LinkedList<String> names = new LinkedList<String>();
-
- Resource current = res;
- String path = res.getPath();
- while (path != null) {
- String alias = null;
- if (current != null && !path.endsWith(JCR_CONTENT_LEAF)) {
- if (factory.getMapEntries().isOptimizeAliasResolutionEnabled()) {
- logger.debug("map: Optimize Alias Resolution is Enabled");
- String parentPath = ResourceUtil.getParent(path);
- if (parentPath != null) {
- final Map<String, String> aliases = factory.getMapEntries().getAliasMap(parentPath);
- if (aliases!= null && aliases.containsValue(current.getName())) {
- for (String key:aliases.keySet()) {
- if (current.getName().equals(aliases.get(key))) {
- alias = key;
- break;
- }
- }
- }
- }
- } else {
- logger.debug("map: Optimize Alias Resolution is Disabled");
- alias = ResourceResolverControl.getProperty(current, PROP_ALIAS);
- }
- }
- if (alias == null || alias.length() == 0) {
- alias = ResourceUtil.getName(path);
- }
- names.add(alias);
- path = ResourceUtil.getParent(path);
- if ("/".equals(path)) {
- path = null;
- } else if (path != null) {
- current = res.getResourceResolver().resolve(path);
- }
- }
-
- // build path from segment names
- final StringBuilder buf = new StringBuilder();
-
- // construct the path from the segments (or root if none)
- if (names.isEmpty()) {
- buf.append('/');
- } else {
- while (!names.isEmpty()) {
- buf.append('/');
- buf.append(names.removeLast());
- }
- }
-
- // reappend the resolutionPathInfo
- if (resolutionPathInfo != null) {
- buf.append(resolutionPathInfo);
- }
-
- // and then we have the mapped path to work on
- mappedPath = buf.toString();
-
- logger.debug("map: Alias mapping resolves to path {}", mappedPath);
-
- }
-
- boolean mappedPathIsUrl = false;
- for (final MapEntry mapEntry : this.factory.getMapEntries().getMapMaps()) {
- final String[] mappedPaths = mapEntry.replace(mappedPath);
- if (mappedPaths != null) {
-
- logger.debug("map: Match for Entry {}", mapEntry);
-
- mappedPathIsUrl = !mapEntry.isInternal();
-
- if (mappedPathIsUrl && schemehostport != null) {
-
- mappedPath = null;
-
- for (final String candidate : mappedPaths) {
- if (candidate.startsWith(schemehostport)) {
- mappedPath = candidate.substring(schemehostport.length() - 1);
- mappedPathIsUrl = false;
- logger.debug("map: Found host specific mapping {} resolving to {}", candidate, mappedPath);
- break;
- } else if (candidate.startsWith(schemePrefix) && mappedPath == null) {
- mappedPath = candidate;
- }
- }
-
- if (mappedPath == null) {
- mappedPath = mappedPaths[0];
- }
-
- } else {
-
- // we can only go with assumptions selecting the first entry
- mappedPath = mappedPaths[0];
-
- }
-
- logger.debug("resolve: MapEntry {} matches, mapped path is {}", mapEntry, mappedPath);
-
- break;
- }
- }
-
- // this should not be the case, since mappedPath is primed
- if (mappedPath == null) {
- mappedPath = resourcePath;
- }
-
- // [scheme:][//authority][path][?query][#fragment]
- try {
- // use commons-httpclient's URI instead of java.net.URI, as it can
- // actually accept *unescaped* URIs, such as the "mappedPath" and
- // return them in proper escaped form, including the path, via
- // toString()
- final URI uri = new URI(mappedPath, false);
-
- // 1. mangle the namespaces in the path
- String path = mangleNamespaces(uri.getPath());
-
- // 2. prepend servlet context path if we have a request
- if (request != null && request.getContextPath() != null && request.getContextPath().length() > 0) {
- path = request.getContextPath().concat(path);
- }
- // update the path part of the URI
- uri.setPath(path);
-
- mappedPath = uri.toString();
- } catch (final URIException e) {
- logger.warn("map: Unable to mangle namespaces for " + mappedPath + " returning unmangled", e);
- }
-
- logger.debug("map: Returning URL {} as mapping for path {}", mappedPath, resourcePath);
-
- // reappend fragment and/or query
- if (fragmentQuery != null) {
- mappedPath = mappedPath.concat(fragmentQuery);
- }
-
- return mappedPath;
- }
-
- // ---------- search path for relative resoures
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#getSearchPath()
- */
- @Override
- public String[] getSearchPath() {
- checkClosed();
- return factory.getSearchPath().clone();
- }
-
- // ---------- direct resource access without resolution
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#getResource(java.lang.String)
- */
- @Override
- public Resource getResource(String path) {
- checkClosed();
- final Resource result = this.getResourceInternal(null, path);
- return result;
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#getResource(org.apache.sling.api.resource.Resource,
- * java.lang.String)
- */
- @Override
- public Resource getResource(final Resource base, final String path) {
- checkClosed();
-
- String absolutePath = path;
- if (absolutePath != null && !absolutePath.startsWith("/") && base != null && base.getPath() != null ) {
- absolutePath = appendToPath(base.getPath(), absolutePath);
- }
-
- final Resource result = getResourceInternal(base, absolutePath);
- return result;
- }
-
- /**
- * Methods concatenates two paths. If the first path contains parameters separated semicolon, they are
- * moved at the end of the result.
- *
- * @param pathWithParameters
- * @param segmentToAppend
- * @return
- */
- private static String appendToPath(final String pathWithParameters, final String segmentToAppend) {
- final ParsedParameters parsed = new ParsedParameters(pathWithParameters);
- if (parsed.getParametersString() == null) {
- return new StringBuilder(parsed.getRawPath()).append('/').append(segmentToAppend).toString();
- } else {
- return new StringBuilder(parsed.getRawPath()).append('/').append(segmentToAppend).append(parsed.getParametersString()).toString();
- }
- }
-
- private Resource getResourceInternal(Resource parent, String path) {
-
- Resource result = null;
- if ( path != null ) {
- // if the path is absolute, normalize . and .. segments and get res
- if (path.startsWith("/")) {
- ParsedParameters parsedPath = new ParsedParameters(path);
- path = ResourceUtil.normalize(parsedPath.getRawPath());
- result = (path != null) ? getAbsoluteResourceInternal(parent, path, parsedPath.getParameters(), false) : null;
- if (result != null) {
- result = this.factory.getResourceDecoratorTracker().decorate(result);
- }
- } else {
-
- // otherwise we have to apply the search path
- // (don't use this.getSearchPath() to save a few cycle for not cloning)
- final String[] paths = factory.getSearchPath();
- if (paths != null) {
- for (final String prefix : factory.getSearchPath()) {
- result = getResource(prefix + path);
- if (result != null) {
- break;
- }
- }
- }
- }
- }
-
- return result;
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#listChildren(org.apache.sling.api.resource.Resource)
- */
- @Override
- public Iterator<Resource> listChildren(final Resource parent) {
- checkClosed();
-
- if (parent instanceof ResourceWrapper) {
- return listChildren(((ResourceWrapper) parent).getResource());
- }
- return new ResourceIteratorDecorator(this.factory.getResourceDecoratorTracker(), this.control.listChildren(this.context, parent));
- }
-
- /**
- * @see org.apache.sling.api.resource.Resource#getChildren()
- */
- @Override
- public Iterable<Resource> getChildren(final Resource parent) {
- return new Iterable<Resource>() {
-
- @Override
- public Iterator<Resource> iterator() {
- return listChildren(parent);
- }
- };
- }
-
- // ---------- Querying resources
-
- private static final String DEFAULT_QUERY_LANGUAGE = "xpath";
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#findResources(java.lang.String,
- * java.lang.String)
- */
- @Override
- public Iterator<Resource> findResources(final String query, final String language) throws SlingException {
- checkClosed();
-
- return new ResourceIteratorDecorator(this.factory.getResourceDecoratorTracker(),
- control.findResources(this.context, query, defaultString(language, DEFAULT_QUERY_LANGUAGE)));
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#queryResources(java.lang.String,
- * java.lang.String)
- */
- @Override
- public Iterator<Map<String, Object>> queryResources(final String query, final String language)
- throws SlingException {
- checkClosed();
-
- return control.queryResources(this.context, query, defaultString(language, DEFAULT_QUERY_LANGUAGE));
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#getUserID()
- */
- @Override
- public String getUserID() {
- checkClosed();
-
- // Try auth info first
- if ( this.control.getAuthenticationInfo() != null ) {
- final Object impUser = this.control.getAuthenticationInfo().get(ResourceResolverFactory.USER_IMPERSONATION);
- if ( impUser != null ) {
- return impUser.toString();
- }
- final Object user = this.control.getAuthenticationInfo().get(ResourceResolverFactory.USER);
- if ( user != null ) {
- return user.toString();
- }
- }
- // Try session
- final Session session = this.getSession();
- if ( session != null ) {
- return session.getUserID();
- }
- // Try attributes
- final Object impUser = this.getAttribute(ResourceResolverFactory.USER_IMPERSONATION);
- if ( impUser != null ) {
- return impUser.toString();
- }
- final Object user = this.getAttribute(ResourceResolverFactory.USER);
- if ( user != null ) {
- return user.toString();
- }
-
- return null;
- }
-
- /** Cached session object, fetched on demand. */
- private Session cachedSession;
- /** Flag indicating if a searching has already been searched. */
- private boolean searchedSession = false;
-
- /**
- * Try to get a session from one of the resource providers.
- */
- private Session getSession() {
- if ( !this.searchedSession ) {
- this.searchedSession = true;
- this.cachedSession = this.control.adaptTo(this.context, Session.class);
- }
- return this.cachedSession;
- }
-
- // ---------- Adaptable interface
-
- /**
- * @see org.apache.sling.api.adapter.SlingAdaptable#adaptTo(java.lang.Class)
- */
- @Override
- @SuppressWarnings("unchecked")
- public <AdapterType> AdapterType adaptTo(final Class<AdapterType> type) {
- checkClosed();
-
- if (type == Session.class) {
- return (AdapterType) getSession();
- }
- final AdapterType result = this.control.adaptTo(this.context, type);
- if ( result != null ) {
- return result;
- }
-
- // fall back to default behaviour
- return super.adaptTo(type);
- }
-
- // ---------- internal
-
- /**
- * Returns a string used for matching map entries against the given request
- * or URI parts.
- *
- * @param scheme
- * The URI scheme
- * @param host
- * The host name
- * @param port
- * The port number. If this is negative, the default value used
- * is 80 unless the scheme is "https" in which case the default
- * value is 443.
- * @param path
- * The (absolute) path
- * @return The request path string {scheme}/{host}.{port}{path}.
- */
- private static String getMapPath(final String scheme, final String host, int port, final String path) {
- if (port < 0) {
- port = ("https".equals(scheme)) ? 443 : 80;
- }
-
- return scheme + "/" + host + "." + port + path;
- }
-
- /**
- * Internally resolves the absolute path. The will almost always contain
- * request selectors and an extension. Therefore this method uses the
- * {@link ResourcePathIterator} to cut off parts of the path to find the
- * actual resource.
- * <p>
- * This method operates in two steps:
- * <ol>
- * <li>Check the path directly
- * <li>Drill down the resource tree from the root down to the resource trying to get the child
- * as per the respective path segment or finding a child whose <code>sling:alias</code> property
- * is set to the respective name.
- * </ol>
- * <p>
- * If neither mechanism (direct access and drill down) resolves to a resource this method
- * returns <code>null</code>.
- *
- * @param absPath
- * The absolute path of the resource to return.
- * @return The resource found or <code>null</code> if the resource could not
- * be found. The
- * {@link org.apache.sling.api.resource.ResourceMetadata#getResolutionPathInfo()
- * resolution path info} field of the resource returned is set to
- * the part of the <code>absPath</code> which has been cut off by
- * the {@link ResourcePathIterator} to resolve the resource.
- */
- private Resource resolveInternal(final String absPath, final Map<String, String> parameters) {
- Resource resource = null;
- String curPath = absPath;
- try {
- final ResourcePathIterator it = new ResourcePathIterator(absPath);
- while (it.hasNext() && resource == null) {
- curPath = it.next();
- resource = getAbsoluteResourceInternal(null, curPath, parameters, true);
- }
- } catch (final Exception ex) {
- throw new SlingException("Problem trying " + curPath + " for request path " + absPath, ex);
- }
-
- // SLING-627: set the part cut off from the uriPath as
- // sling.resolutionPathInfo property such that
- // uriPath = curPath + sling.resolutionPathInfo
- if (resource != null) {
-
- final String rpi = absPath.substring(curPath.length());
- resource.getResourceMetadata().setResolutionPath(absPath.substring(0, curPath.length()));
- resource.getResourceMetadata().setResolutionPathInfo(rpi);
- resource.getResourceMetadata().setParameterMap(parameters);
-
- logger.debug("resolveInternal: Found resource {} with path info {} for {}", new Object[] { resource, rpi, absPath });
-
- } else {
-
- String tokenizedPath = absPath;
-
- // no direct resource found, so we have to drill down into the
- // resource tree to find a match
- resource = getAbsoluteResourceInternal(null, "/", parameters, true);
-
- //no read access on / drilling further down
- //SLING-5638
- if (resource == null) {
- resource = getAbsoluteResourceInternal(absPath, parameters, true);
- if (resource != null) {
- tokenizedPath = tokenizedPath.substring(resource.getPath().length());
- }
- }
-
- final StringBuilder resolutionPath = new StringBuilder();
- final StringTokenizer tokener = new StringTokenizer(tokenizedPath, "/");
- while (resource != null && tokener.hasMoreTokens()) {
- final String childNameRaw = tokener.nextToken();
-
- Resource nextResource = getChildInternal(resource, childNameRaw);
- if (nextResource != null) {
-
- resource = nextResource;
- resolutionPath.append("/").append(childNameRaw);
-
- } else {
-
- String childName = null;
- final ResourcePathIterator rpi = new ResourcePathIterator(childNameRaw);
- while (rpi.hasNext() && nextResource == null) {
- childName = rpi.next();
- nextResource = getChildInternal(resource, childName);
- }
-
- // switch the currentResource to the nextResource (may be
- // null)
- resource = nextResource;
- resolutionPath.append("/").append(childName);
-
- // terminate the search if a resource has been found
- // with the extension cut off
- if (nextResource != null) {
- break;
- }
- }
- }
-
- // SLING-627: set the part cut off from the uriPath as
- // sling.resolutionPathInfo property such that
- // uriPath = curPath + sling.resolutionPathInfo
- if (resource != null) {
- final String path = resolutionPath.toString();
- final String pathInfo = absPath.substring(path.length());
-
- resource.getResourceMetadata().setResolutionPath(path);
- resource.getResourceMetadata().setResolutionPathInfo(pathInfo);
- resource.getResourceMetadata().setParameterMap(parameters);
-
- logger.debug("resolveInternal: Found resource {} with path info {} for {}", new Object[] { resource, pathInfo,
- absPath });
- }
- }
-
- return resource;
- }
-
- private Resource getChildInternal(final Resource parent, final String childName) {
- final String path;
- if ( childName.startsWith("/") ) {
- path = childName;
- } else {
- path = parent.getPath() + '/' + childName;
- }
- Resource child = getAbsoluteResourceInternal(parent, ResourceUtil.normalize(path), EMPTY_PARAMETERS, true );
- if (child != null) {
- final String alias = ResourceResolverControl.getProperty(child, PROP_REDIRECT_INTERNAL);
- if (alias != null) {
- // TODO: might be a redirect ??
- logger.warn("getChildInternal: Internal redirect to {} for Resource {} is not supported yet, ignoring", alias,
- child);
- }
-
- // we have the resource name, continue with the next level
- return child;
- }
-
- // we do not have a child with the exact name, so we look for
- // a child, whose alias matches the childName
- if (factory.getMapEntries().isOptimizeAliasResolutionEnabled()){
- logger.debug("getChildInternal: Optimize Alias Resolution is Enabled");
- //optimization made in SLING-2521
- final Map<String, String> aliases = factory.getMapEntries().getAliasMap(parent.getPath());
- if (aliases != null) {
- final String aliasName = aliases.get(childName);
- if (aliasName != null ) {
- final String aliasPath;
- if ( aliasName.startsWith("/") ) {
- aliasPath = aliasName;
- } else {
- aliasPath = parent.getPath() + '/' + aliasName;
- }
- final Resource aliasedChild = getAbsoluteResourceInternal(parent, ResourceUtil.normalize(aliasPath), EMPTY_PARAMETERS, true );
- logger.debug("getChildInternal: Found Resource {} with alias {} to use", aliasedChild, childName);
- return aliasedChild;
- }
- }
- } else {
- logger.debug("getChildInternal: Optimize Alias Resolution is Disabled");
- final Iterator<Resource> children = listChildren(parent);
- while (children.hasNext()) {
- child = children.next();
- if (!child.getPath().endsWith(JCR_CONTENT_LEAF)) {
- final String[] aliases = ResourceResolverControl.getProperty(child, PROP_ALIAS, String[].class);
- if (aliases != null) {
- for (final String alias : aliases) {
- if (childName.equals(alias)) {
- logger.debug("getChildInternal: Found Resource {} with alias {} to use", child, childName);
- final Resource aliasedChild = getAbsoluteResourceInternal(parent, ResourceUtil.normalize(child.getPath()) , EMPTY_PARAMETERS, true);
- return aliasedChild;
- }
- }
- }
- }
- }
- }
-
- // no match for the childName found
- logger.debug("getChildInternal: Resource {} has no child {}", parent, childName);
- return null;
- }
-
- /**
- * Creates a resource with the given path if existing
- */
- private Resource getAbsoluteResourceInternal(@CheckForNull final Resource parent, @CheckForNull final String path, final Map<String, String> parameters, final boolean isResolve) {
- if (path == null || path.length() == 0 || path.charAt(0) != '/') {
- logger.debug("getResourceInternal: Path must be absolute {}", path);
- return null; // path must be absolute
- }
-
- final Resource parentToUse;
- if (parent != null && path.startsWith(parent.getPath())) {
- parentToUse = parent;
- } else {
- parentToUse = null;
- }
-
- final Resource resource = this.control.getResource(this.context, path, parentToUse, parameters, isResolve);
- if (resource != null) {
- resource.getResourceMetadata().setResolutionPath(path);
- resource.getResourceMetadata().setParameterMap(parameters);
- return resource;
- }
-
- logger.debug("getResourceInternal: Cannot resolve path '{}' to a resource", path);
- return null;
- }
-
- /**
- * Creates a resource, traversing bottom up, to the highest readable resource.
- *
- */
- private Resource getAbsoluteResourceInternal(String absPath, final Map<String, String> parameters, final boolean isResolved) {
-
- if (!absPath.contains("/") || "/".equals(absPath)) {
- return null;
- }
-
- absPath = absPath.substring(absPath.indexOf("/"));
- Resource resource = getAbsoluteResourceInternal(null, absPath, parameters, isResolved);
-
- absPath = absPath.substring(0, absPath.lastIndexOf("/"));
-
- while (!absPath.equals("")) {
- Resource r = getAbsoluteResourceInternal(null, absPath, parameters, true);
-
- if (r != null) {
- resource = r;
- }
- absPath = absPath.substring(0, absPath.lastIndexOf("/"));
- }
- return resource;
- }
-
- /**
- * Returns the <code>path</code> as an absolute path. If the path is already
- * absolute it is returned unmodified (the same instance actually). If the
- * path is relative it is made absolute by prepending the first entry of the
- * {@link #getSearchPath() search path}.
- *
- * @param path
- * The path to ensure absolute
- * @return The absolute path as explained above
- */
- private String ensureAbsPath(String path) {
- if (!path.startsWith("/")) {
- path = getSearchPath()[0] + path;
- }
- return path;
- }
-
- private String mangleNamespaces(String absPath) {
- if (factory.isMangleNamespacePrefixes() && absPath != null && absPath.contains(MANGLE_NAMESPACE_OUT_SUFFIX)) {
- final Matcher m = MANLE_NAMESPACE_OUT_PATTERN.matcher(absPath);
-
- final StringBuffer buf = new StringBuffer();
- while (m.find()) {
- final String namespace = m.group(1);
- try {
-
- // throws if "namespace" is not a registered
- // namespace prefix
- final Session session = getSession();
- if ( session != null ) {
- session.getNamespaceURI(namespace);
- final String replacement = MANGLE_NAMESPACE_IN_PREFIX + namespace + MANGLE_NAMESPACE_IN_SUFFIX;
- m.appendReplacement(buf, replacement);
- } else {
- logger.debug("mangleNamespaces: '{}' is not a prefix, not mangling", namespace);
- }
-
-
- } catch (final NamespaceException ne) {
-
- // not a valid prefix
- logger.debug("mangleNamespaces: '{}' is not a prefix, not mangling", namespace);
-
- } catch (final RepositoryException re) {
-
- logger.warn("mangleNamespaces: Problem checking namespace '{}'", namespace, re);
-
- }
- }
-
- m.appendTail(buf);
-
- absPath = buf.toString();
- }
-
- return absPath;
- }
-
- private String unmangleNamespaces(String absPath) {
- if (factory.isMangleNamespacePrefixes() && absPath.contains(MANGLE_NAMESPACE_IN_PREFIX)) {
- final Matcher m = MANGLE_NAMESPACE_IN_PATTERN.matcher(absPath);
- final StringBuffer buf = new StringBuffer();
- while (m.find()) {
- final String namespace = m.group(1);
- try {
-
- // throws if "namespace" is not a registered
- // namespace prefix
- final Session session = getSession();
- if ( session != null ) {
- session.getNamespaceURI(namespace);
- final String replacement = MANGLE_NAMESPACE_OUT_PREFIX + namespace + MANGLE_NAMESPACE_OUT_SUFFIX;
- m.appendReplacement(buf, replacement);
- } else {
- logger.debug("unmangleNamespaces: '{}' is not a prefix, not unmangling", namespace);
- }
-
-
- } catch (final NamespaceException ne) {
-
- // not a valid prefix
- logger.debug("unmangleNamespaces: '{}' is not a prefix, not unmangling", namespace);
-
- } catch (final RepositoryException re) {
-
- logger.warn("unmangleNamespaces: Problem checking namespace '{}'", namespace, re);
-
- }
- }
- m.appendTail(buf);
- absPath = buf.toString();
- }
-
- return absPath;
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#delete(org.apache.sling.api.resource.Resource)
- */
- @Override
- public void delete(final Resource resource)
- throws PersistenceException {
- // check if the resource is non existing - throws NPE if resource is null as stated in the API
- if ( ResourceUtil.isNonExistingResource(resource) ) {
- // nothing to do
- return;
- }
- // if resource is null, we get an NPE as stated in the API
- this.control.delete(this.context, resource);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#create(org.apache.sling.api.resource.Resource, java.lang.String, Map)
- */
- @Override
- public Resource create(final Resource parent, final String name, final Map<String, Object> properties)
- throws PersistenceException {
- // if parent or name is null, we get an NPE as stated in the API
- if ( name == null ) {
- throw new NullPointerException("name");
- }
- // name should be a name not a path
- if ( name.indexOf("/") != -1 ) {
- throw new IllegalArgumentException("Name should not contain a slash: " + name);
- }
- final String path;
- if ( parent.getPath().equals("/") ) {
- path = parent.getPath() + name;
- } else {
- path = parent.getPath() + "/" + name;
- }
- // experimental code for handling synthetic resources
- if ( ResourceUtil.isSyntheticResource(parent) ) {
- Resource grandParent = parent.getParent();
- if (grandParent != null) {
- this.create(grandParent, parent.getName(), null);
- } else {
- throw new IllegalArgumentException("Can't create child on a synthetic root");
- }
- }
- final Resource rsrc = this.control.create(this.context, path, properties);
- rsrc.getResourceMetadata().setResolutionPath(rsrc.getPath());
- return this.factory.getResourceDecoratorTracker().decorate(rsrc);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#revert()
- */
- @Override
- public void revert() {
- this.control.revert(this.context);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#commit()
- */
- @Override
- public void commit() throws PersistenceException {
- this.control.commit(this.context);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#hasChanges()
- */
- @Override
- public boolean hasChanges() {
- return this.control.hasChanges(this.context);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#hasChildren()
- */
- @Override
- public boolean hasChildren(Resource resource) {
- return listChildren(resource).hasNext();
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#getParentResourceType(org.apache.sling.api.resource.Resource)
- */
- @Override
- public String getParentResourceType(final Resource resource) {
- String resourceSuperType = null;
- if ( resource != null ) {
- resourceSuperType = resource.getResourceSuperType();
- if (resourceSuperType == null) {
- resourceSuperType = this.getParentResourceType(resource.getResourceType());
- }
- }
- return resourceSuperType;
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#getParentResourceType(java.lang.String)
- */
- @Override
- public String getParentResourceType(final String resourceType) {
- return this.control.getParentResourceType(this.factory, this, resourceType);
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#isResourceType(org.apache.sling.api.resource.Resource, java.lang.String)
- */
- @Override
- public boolean isResourceType(final Resource resource, final String resourceType) {
- boolean result = false;
- if ( resource != null && resourceType != null ) {
- // Check if the resource is of the given type. This method first checks the
- // resource type of the resource, then its super resource type and continues
- // to go up the resource super type hierarchy.
- if (resourceType.equals(resource.getResourceType())) {
- result = true;
- } else {
- Set<String> superTypesChecked = new HashSet<String>();
- String superType = this.getParentResourceType(resource);
- while (!result && superType != null) {
- if (resourceType.equals(superType)) {
- result = true;
- } else {
- superTypesChecked.add(superType);
- superType = this.getParentResourceType(superType);
- if (superType != null && superTypesChecked.contains(superType)) {
- throw new SlingException("Cyclic dependency for resourceSuperType hierarchy detected on resource " + resource.getPath(), null);
- }
- }
- }
- }
-
- }
- return result;
- }
-
- /**
- * @see org.apache.sling.api.resource.ResourceResolver#refresh()
- */
- @Override
- public void refresh() {
- this.control.refresh(this.context);
- }
-
- @Override
- public Resource getParent(final Resource child) {
- Resource rsrc = null;
- final String parentPath = ResourceUtil.getParent(child.getPath());
- if ( parentPath != null ) {
- // if the parent path is relative, resolve using search paths.
- if ( !parentPath.startsWith("/") ) {
- rsrc = context.getResourceResolver().getResource(parentPath);
- } else {
- rsrc = this.control.getParent(this.context, parentPath, child);
- if (rsrc != null ) {
- rsrc.getResourceMetadata().setResolutionPath(rsrc.getPath());
- rsrc = this.factory.getResourceDecoratorTracker().decorate(rsrc);
- }
- }
- }
- return rsrc;
- }
-
- @Override
- public Resource copy(final String srcAbsPath, final String destAbsPath) throws PersistenceException {
- Resource rsrc = this.control.copy(this.context, srcAbsPath, destAbsPath);
- if (rsrc != null ) {
- rsrc.getResourceMetadata().setResolutionPath(rsrc.getPath());
- rsrc = this.factory.getResourceDecoratorTracker().decorate(rsrc);
- }
- return rsrc;
- }
-
- @Override
- public Resource move(final String srcAbsPath, final String destAbsPath) throws PersistenceException {
- Resource rsrc = this.control.move(this.context, srcAbsPath, destAbsPath);
- if (rsrc != null ) {
- rsrc.getResourceMetadata().setResolutionPath(rsrc.getPath());
- rsrc = this.factory.getResourceDecoratorTracker().decorate(rsrc);
- }
- return rsrc;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/console/ResourceResolverWebConsolePlugin.java b/src/main/java/org/apache/sling/resourceresolver/impl/console/ResourceResolverWebConsolePlugin.java
deleted file mode 100644
index 5d6beaa..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/console/ResourceResolverWebConsolePlugin.java
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * 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.resourceresolver.impl.console;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Set;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.sling.api.request.ResponseUtil;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.runtime.RuntimeService;
-import org.apache.sling.api.resource.runtime.dto.ResourceProviderDTO;
-import org.apache.sling.api.resource.runtime.dto.ResourceProviderFailureDTO;
-import org.apache.sling.api.resource.runtime.dto.RuntimeDTO;
-import org.apache.sling.resourceresolver.impl.CommonResourceResolverFactoryImpl;
-import org.apache.sling.resourceresolver.impl.helper.URI;
-import org.apache.sling.resourceresolver.impl.helper.URIException;
-import org.apache.sling.resourceresolver.impl.mapping.MapEntries;
-import org.apache.sling.resourceresolver.impl.mapping.MapEntry;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-public class ResourceResolverWebConsolePlugin extends HttpServlet {
-
- private static final long serialVersionUID = 0;
-
- private static final String ATTR_TEST = "plugin.test";
-
- private static final String ATTR_SUBMIT = "plugin.submit";
-
- private static final String PAR_MSG = "msg";
- private static final String PAR_TEST = "test";
-
- private final transient CommonResourceResolverFactoryImpl resolverFactory;
-
- private transient ServiceRegistration service;
-
- private final transient RuntimeService runtimeService;
-
- private final transient BundleContext bundleContext;
-
- public ResourceResolverWebConsolePlugin(final BundleContext context,
- final CommonResourceResolverFactoryImpl resolverFactory,
- final RuntimeService runtimeService) {
- this.resolverFactory = resolverFactory;
- this.runtimeService = runtimeService;
- this.bundleContext = context;
-
- Dictionary<String, Object> props = new Hashtable<String, Object>();
- props.put(Constants.SERVICE_DESCRIPTION,
- "Apache Sling Resource Resolver Web Console Plugin");
- props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
- props.put(Constants.SERVICE_PID, getClass().getName());
- props.put("felix.webconsole.label", "jcrresolver");
- props.put("felix.webconsole.title", "Resource Resolver");
- props.put("felix.webconsole.css", "/jcrresolver/res/ui/resourceresolver.css");
- props.put("felix.webconsole.category", "Sling");
- props.put("felix.webconsole.configprinter.modes", "always");
-
- service = context.registerService(
- new String[] { "javax.servlet.Servlet" }, this, props);
- }
-
- public void dispose() {
- if (service != null) {
- service.unregister();
- service = null;
- }
- }
-
- @Override
- protected void doGet(final HttpServletRequest request,
- final HttpServletResponse response) throws ServletException,
- IOException {
- final String msg = request.getParameter(PAR_MSG);
- final String test;
- if (msg != null) {
- test = request.getParameter(PAR_TEST);
- } else {
- test = null;
- }
-
- final PrintWriter pw = response.getWriter();
-
- pw.println("<table class='content' cellpadding='0' cellspacing='0' width='100%'>");
-
- final MapEntries mapEntries = resolverFactory.getMapEntries();
-
- titleHtml(pw, "Configuration", null);
- pw.println("<tr class='content'>");
- pw.println("<td class='content'>Resource Search Path</td>");
- pw.print("<td class='content' colspan='2'>");
- pw.print(Arrays.asList(resolverFactory.getSearchPath()).toString());
- pw.print("</td>");
- pw.println("</tr>");
- pw.println("<tr class='content'>");
- pw.println("<td class='content'>Namespace Mangling</td>");
- pw.print("<td class='content' colspan='2'>");
- pw.print(resolverFactory.isMangleNamespacePrefixes() ? "Enabled"
- : "Disabled");
- pw.print("</td>");
- pw.println("</tr>");
- pw.println("<tr class='content'>");
- pw.println("<td class='content'>Mapping Location</td>");
- pw.print("<td class='content' colspan='2'>");
- pw.print(resolverFactory.getMapRoot());
- pw.print("</td>");
- pw.println("</tr>");
-
- separatorHtml(pw);
-
- titleHtml(
- pw,
- "Configuration Test",
- "To test the configuration, enter an URL or a resource path into "
- + "the field and click 'Resolve' to resolve the URL or click 'Map' "
- + "to map the resource path. To simulate a map call that takes the "
- + "current request into account, provide a full URL whose "
- + "scheme/host/port prefix will then be used as the request "
- + "information. The path passed to map will always be the path part "
- + "of the URL.");
-
- pw.println("<tr class='content'>");
- pw.println("<td class='content'>Test</td>");
- pw.print("<td class='content' colspan='2'>");
- pw.print("<form method='post'>");
- pw.print("<input type='text' name='" + ATTR_TEST + "' value='");
- if (test != null) {
- pw.print(ResponseUtil.escapeXml(test));
- }
- pw.println("' class='input' size='50'>");
- pw.println(" <input type='submit' name='" + ATTR_SUBMIT
- + "' value='Resolve' class='submit'>");
- pw.println(" <input type='submit' name='" + ATTR_SUBMIT
- + "' value='Map' class='submit'>");
- pw.print("</form>");
- pw.print("</td>");
- pw.println("</tr>");
-
- if (msg != null) {
- pw.println("<tr class='content'>");
- pw.println("<td class='content'> </td>");
- pw.print("<td class='content' colspan='2'>");
- pw.print(ResponseUtil.escapeXml(msg));
- pw.println("</td>");
- pw.println("</tr>");
- }
-
- separatorHtml(pw);
-
- dumpDTOsHtml(pw);
-
- separatorHtml(pw);
- dumpMapHtml(
- pw,
- "Resolver Map Entries",
- "Lists the entries used by the ResourceResolver.resolve methods to map URLs to Resources",
- mapEntries.getResolveMaps());
-
- separatorHtml(pw);
-
- dumpMapHtml(
- pw,
- "Mapping Map Entries",
- "Lists the entries used by the ResourceResolver.map methods to map Resource Paths to URLs",
- mapEntries.getMapMaps());
-
- pw.println("</table>");
-
- }
-
- @Override
- protected void doPost(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
-
- final String test = request.getParameter(ATTR_TEST);
- String msg = null;
- if (test != null && test.length() > 0) {
-
- ResourceResolver resolver = null;
- try {
- // prepare the request for the resource resolver
- HttpServletRequest helper = new ResolverRequest(request, test);
-
- // get an administrative resource resolver
- resolver = resolverFactory
- .getAdministrativeResourceResolver(null);
-
- // map or resolve as instructed
- Object result;
- if ("Map".equals(request.getParameter(ATTR_SUBMIT))) {
- if (helper.getServerName() == null) {
- result = resolver.map(helper.getPathInfo());
- } else {
- result = resolver.map(helper, helper.getPathInfo());
- }
- } else {
- result = resolver.resolve(helper, helper.getPathInfo());
- }
-
- // set the result to render the result
- msg = result.toString();
-
- } catch (final Throwable t) {
-
- // some error occurred, report it as a result
- msg = "Test Failure: " + t;
-
- } finally {
- if (resolver != null) {
- resolver.close();
- }
- }
-
- }
-
- // finally redirect
- final String path = request.getContextPath() + request.getServletPath()
- + request.getPathInfo();
- final String redirectTo;
- if (msg == null) {
- redirectTo = path;
- } else {
- redirectTo = path + '?' + PAR_MSG + '=' + encodeParam(msg) + '&'
- + PAR_TEST + '=' + encodeParam(test);
- }
- response.sendRedirect(redirectTo);
- }
-
- private String encodeParam(final String value) {
- try {
- return URLEncoder.encode(value, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- // should never happen
- return value;
- }
- }
-
- // ---------- ConfigurationPrinter
-
- public void printConfiguration(final PrintWriter pw) {
- dumpDTOsText(pw);
-
- separatorText(pw);
-
- final MapEntries mapEntries = resolverFactory.getMapEntries();
-
- dumpMapText(pw, "Resolver Map Entries", mapEntries.getResolveMaps());
-
- separatorText(pw);
-
- dumpMapText(pw, "Mapping Map Entries", mapEntries.getMapMaps());
- }
-
- // ---------- internal
-
- private void dumpMapHtml(PrintWriter pw, String title, String description,
- Collection<MapEntry> list) {
-
- titleHtml(pw, title, description);
-
- pw.println("<tr class='content'>");
- pw.println("<th class='content'>Pattern</th>");
- pw.println("<th class='content'>Replacement</th>");
- pw.println("<th class='content'>Redirect</th>");
- pw.println("</tr>");
-
- final Set<String> usedPatterns = new HashSet<String>();
-
- for (final MapEntry entry : list) {
- final String pattern = entry.getPattern();
- pw.print("<tr class='content");
- if (!usedPatterns.add(pattern)) {
- pw.print(" duplicate");
- }
- pw.println("'>");
- pw.println("<td class='content' style='vertical-align: top'>");
- pw.print(ResponseUtil.escapeXml(pattern));
- pw.print("</td>");
-
- pw.print("<td class='content' style='vertical-align: top'>");
- final String[] repls = entry.getRedirect();
- for (final String repl : repls) {
- pw.print(ResponseUtil.escapeXml(repl));
- pw.print("<br/>");
- }
- pw.print("</td>");
-
- pw.print("<td class='content' style='vertical-align: top'>");
- if (entry.isInternal()) {
- pw.print("internal");
- } else {
- pw.print("external: ");
- pw.print(String.valueOf(entry.getStatus()));
- }
- pw.println("</td></tr>");
-
- }
- }
-
- private void titleHtml(PrintWriter pw, String title, String description) {
- pw.print("<tr class='content'>");
- pw.print("<th colspan='3'class='content container'>");
- pw.print(ResponseUtil.escapeXml(title));
- pw.println("</th></tr>");
-
- if (description != null) {
- pw.print("<tr class='content'>");
- pw.print("<td colspan='3'class='content'>");
- pw.print(ResponseUtil.escapeXml(description));
- pw.println("</th></tr>");
- }
- }
-
- private void separatorHtml(PrintWriter pw) {
- pw.print("<tr class='content'>");
- pw.println("<td class='content' colspan='3'> </td>");
- pw.println("</tr>");
- }
-
- private void dumpMapText(PrintWriter pw, String title,
- Collection<MapEntry> list) {
-
- pw.println(title);
-
- final String format = "%25s%25s%15s\r\n";
- pw.printf(format, "Pattern", "Replacement", "Redirect");
-
- for (MapEntry entry : list) {
- final List<String> redir = Arrays.asList(entry.getRedirect());
- final String status = entry.isInternal() ? "internal"
- : "external: " + entry.getStatus();
- pw.printf(format, entry.getPattern(), redir, status);
- }
- }
-
- private ServiceReference getServiceReference(final long id) {
- try {
- final ServiceReference[] refs = this.bundleContext.getServiceReferences(ResourceProvider.class.getName(),
- "(" + Constants.SERVICE_ID + "=" + String.valueOf(id) + ")");
- if ( refs != null && refs.length > 0 ) {
- return refs[0];
- }
- } catch ( final InvalidSyntaxException ise) {
- // ignore
- }
- return null;
- }
-
- private void dumpDTOsHtml(final PrintWriter pw) {
-
- titleHtml(pw, "Resource Providers", "Lists all available and activate resource prodivers.");
-
- pw.println("<tr class='content'>");
- pw.println("<th class='content'>Provider</th>");
- pw.println("<th class='content'>Path</th>");
- pw.println("<th class='content'>Configuration</th>");
- pw.println("</tr>");
-
- final RuntimeDTO runtimeDTO = this.runtimeService.getRuntimeDTO();
- for(final ResourceProviderDTO dto : runtimeDTO.providers) {
- // get service reference
- final ServiceReference ref = this.getServiceReference(dto.serviceId);
- final StringBuilder sb = new StringBuilder();
- if ( dto.name != null ) {
- sb.append(dto.name);
- sb.append(' ');
- } else {
- sb.append("<unnamed> ");
- }
- if ( ref != null ) {
- sb.append("(serviceId = ");
- sb.append(dto.serviceId);
- sb.append(", bundleId = ");
- sb.append(ref.getBundle().getBundleId());
- sb.append(")");
- }
- pw.print("<tr class='content'>");
- pw.print("<td class='content' style='vertical-align: top'>");
- pw.print(ResponseUtil.escapeXml(sb.toString()));
- pw.print("</td>");
-
- pw.print("<td class='content' style='vertical-align: top'>");
- pw.print(ResponseUtil.escapeXml(dto.path));
- pw.print("</td>");
-
- pw.print("<td class='content' style='vertical-align: top'>");
- pw.print("auth=");
- pw.print(dto.authType.name());
- pw.print("<br/>");
- pw.print("adaptable=");
- pw.print(dto.adaptable);
- pw.print("<br/>");
- pw.print("attributable=");
- pw.print(dto.attributable);
- pw.print("<br/>");
- pw.print("modifiable=");
- pw.print(dto.modifiable);
- pw.print("<br/>");
- pw.print("refreshable=");
- pw.print(dto.refreshable);
- pw.print("<br/>");
- pw.print("supportsQueryLanguage=");
- pw.print(dto.supportsQueryLanguage);
- pw.print("<br/>");
- pw.print("useResourceAccessSecurity=");
- pw.print(dto.useResourceAccessSecurity);
- pw.println("</td></tr>");
- }
-
- if ( runtimeDTO.failedProviders.length > 0 ) {
- titleHtml(pw, "Failed Resource Providers", "Lists all failed providers.");
-
- pw.println("<tr class='content'>");
- pw.println("<th class='content'>Provider</th>");
- pw.println("<th class='content'>Path</th>");
- pw.println("<th class='content'>Reason</th>");
- pw.println("</tr>");
-
- for(final ResourceProviderFailureDTO dto : runtimeDTO.failedProviders) {
- // get service reference
- final ServiceReference ref = this.getServiceReference(dto.serviceId);
- final StringBuilder sb = new StringBuilder();
- if ( dto.name != null ) {
- sb.append(dto.name);
- sb.append(' ');
- } else {
- sb.append("<unnamed> ");
- }
- if ( ref != null ) {
- sb.append("(serviceId = ");
- sb.append(dto.serviceId);
- sb.append(", bundleId = ");
- sb.append(ref.getBundle().getBundleId());
- sb.append(")");
- }
- pw.print("<tr class='content'>");
- pw.print("<td class='content' style='vertical-align: top'>");
- pw.print(ResponseUtil.escapeXml(sb.toString()));
- pw.print("</td>");
-
- pw.print("<td class='content' style='vertical-align: top'>");
- pw.print(ResponseUtil.escapeXml(dto.path));
- pw.print("</td>");
-
- pw.print("<td class='content' style='vertical-align: top'>");
- pw.print(dto.reason.name());
- pw.println("</td></tr>");
- }
- }
- }
-
- private void dumpDTOsText(final PrintWriter pw) {
-
- pw.println("Resource Providers");
-
- final String format = "%35s %25s %15s\r\n";
- pw.printf(format, "Provider", "Path", "Configuration");
-
- final RuntimeDTO runtimeDTO = this.runtimeService.getRuntimeDTO();
- for(final ResourceProviderDTO dto : runtimeDTO.providers) {
- // get service reference
- final ServiceReference ref = this.getServiceReference(dto.serviceId);
- final StringBuilder sb = new StringBuilder();
- if ( dto.name != null ) {
- sb.append(dto.name);
- sb.append(' ');
- } else {
- sb.append("<unnamed> ");
- }
- if ( ref != null ) {
- sb.append("(serviceId = ");
- sb.append(dto.serviceId);
- sb.append(", bundleId = ");
- sb.append(ref.getBundle().getBundleId());
- sb.append(")");
- }
- final StringBuilder config = new StringBuilder();
- config.append("auth=");
- config.append(dto.authType.name());
- config.append(", adaptable=");
- config.append(dto.adaptable);
- config.append(", attributable=");
- config.append(dto.attributable);
- config.append(", modifiable=");
- config.append(dto.modifiable);
- config.append(", refreshable=");
- config.append(dto.refreshable);
- config.append(", supportsQueryLanguage=");
- config.append(dto.supportsQueryLanguage);
- config.append(", useResourceAccessSecurity=");
- config.append(dto.useResourceAccessSecurity);
- pw.printf(format, sb.toString(), dto.path, config.toString());
- }
- pw.println();
- if ( runtimeDTO.failedProviders.length > 0 ) {
- pw.println("Failed Resource Providers");
- pw.printf(format, "Provider", "Path", "Reason");
-
- for(final ResourceProviderFailureDTO dto : runtimeDTO.failedProviders) {
- // get service reference
- final ServiceReference ref = this.getServiceReference(dto.serviceId);
- final StringBuilder sb = new StringBuilder();
- if ( dto.name != null ) {
- sb.append(dto.name);
- sb.append(' ');
- } else {
- sb.append("<unnamed> ");
- }
- if ( ref != null ) {
- sb.append("(serviceId = ");
- sb.append(dto.serviceId);
- sb.append(", bundleId = ");
- sb.append(ref.getBundle().getBundleId());
- sb.append(")");
- }
- pw.printf(format, sb.toString(), dto.path, dto.reason.name());
- }
- pw.println();
- }
- }
-
- private void separatorText(PrintWriter pw) {
- pw.println();
- }
-
- /**
- * Method to retrieve static resources from this bundle.
- */
- @SuppressWarnings("unused")
- private URL getResource(final String path) {
- if (path.startsWith("/jcrresolver/res/ui/")) {
- return this.getClass().getResource(path.substring(12));
- }
- return null;
- }
-
- private static class ResolverRequest extends HttpServletRequestWrapper {
-
- private final URI uri;
-
- public ResolverRequest(HttpServletRequest request, String uriString)
- throws URIException {
- super(request);
- uri = new URI(uriString, false);
- }
-
- @Override
- public String getScheme() {
- return uri.getScheme();
- }
-
- @Override
- public String getServerName() {
- try {
- return uri.getHost();
- } catch (URIException ue) {
- return null;
- }
- }
-
- @Override
- public int getServerPort() {
- return uri.getPort();
- }
-
- @Override
- public String getPathInfo() {
- try {
- return uri.getPath();
- } catch (URIException ue) {
- return "";
- }
- }
- }
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/AbstractIterator.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/AbstractIterator.java
deleted file mode 100644
index 86253a9..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/AbstractIterator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-public abstract class AbstractIterator<T> implements Iterator<T> {
-
- private T nextElement;
-
- protected abstract T seek();
-
- @Override
- public boolean hasNext() {
- if (nextElement == null) {
- nextElement = seek();
- }
- return nextElement != null;
- }
-
- @Override
- public T next() {
- if (nextElement == null && !hasNext()) {
- throw new NoSuchElementException();
- }
- final T result = nextElement;
- nextElement = null;
- return result;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ChainedIterator.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/ChainedIterator.java
deleted file mode 100644
index 5dfda1f..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ChainedIterator.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import java.util.Iterator;
-
-public class ChainedIterator<T> extends AbstractIterator<T> {
-
- private final Iterator<Iterator<T>> iterators;
-
- private Iterator<T> currentIterator;
-
- public ChainedIterator(Iterator<Iterator<T>> iterators) {
- this.iterators = iterators;
- }
-
- @Override
- protected T seek() {
- while (true) {
- if (currentIterator == null) {
- if (!iterators.hasNext()) {
- return null;
- }
- currentIterator = iterators.next();
- continue;
- }
- if (currentIterator.hasNext()) {
- return currentIterator.next();
- } else {
- currentIterator = null;
- }
- }
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/RedirectResource.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/RedirectResource.java
deleted file mode 100644
index 43c241b..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/RedirectResource.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.sling.adapter.annotations.Adaptable;
-import org.apache.sling.adapter.annotations.Adapter;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.SyntheticResource;
-import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.api.wrappers.ValueMapDecorator;
-
-@Adaptable(adaptableClass = Resource.class, adapters = @Adapter(value = { Map.class, ValueMap.class }))
-public final class RedirectResource extends SyntheticResource {
-
- static final String RT_SLING_REDIRECT = "sling:redirect";
-
- static final String PROP_SLING_TARGET = "sling:target";
-
- static final String PROP_SLING_STATUS = "sling:status";
-
- private final Map<String, Object> values;
-
- public RedirectResource(final ResourceResolver resolver, final String path,
- final String target, final int status) {
- super(resolver, path, RT_SLING_REDIRECT);
-
- final Map<String, Object> props = new HashMap<String, Object>();
- props.put(PROP_SLING_TARGET, target);
- props.put(PROP_SLING_STATUS, status);
- this.values = Collections.unmodifiableMap(props);
- }
-
- /**
- * @see org.apache.sling.api.adapter.Adaptable#adaptTo(java.lang.Class)
- */
- @SuppressWarnings("unchecked")
- public <AdapterType> AdapterType adaptTo(final Class<AdapterType> type) {
- if (type == ValueMap.class) {
- return (AdapterType) new ValueMapDecorator(values);
- } else if (type == Map.class) {
- return (AdapterType) values;
- }
-
- return super.adaptTo(type);
- }
-
- @Override
- public String toString() {
- return super.toString() + ", values=" + values;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceDecoratorTracker.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceDecoratorTracker.java
deleted file mode 100644
index 460f912..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceDecoratorTracker.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceDecorator;
-import org.apache.sling.commons.osgi.ServiceUtil;
-
-/**
- * Helper class to track the resource decorators and keep them sorted by their
- * service ranking.
- */
-public class ResourceDecoratorTracker {
-
- private static final ResourceDecorator[] EMPTY_ARRAY = new ResourceDecorator[0];
-
- /**
- * The (optional) resource decorators, working copy.
- */
- protected final List<ResourceDecoratorEntry> resourceDecorators = new ArrayList<ResourceDecoratorEntry>();
-
- /**
- * An array of the above, updates when changes are created.
- */
- private volatile ResourceDecorator[] resourceDecoratorsArray = EMPTY_ARRAY;
-
- public void close() {
- synchronized (this.resourceDecorators) {
- this.resourceDecorators.clear();
- this.resourceDecoratorsArray = EMPTY_ARRAY;
- }
- }
-
- /**
- * Decorate a resource.
- */
- public Resource decorate(final Resource resource) {
- Resource result = resource;
- final ResourceDecorator[] decorators = this.resourceDecoratorsArray;
- for (final ResourceDecorator decorator : decorators) {
- final Resource original = result;
- result = decorator.decorate(original);
- if (result == null) {
- result = original;
- }
- }
-
- // make resource metadata read-only
- result.getResourceMetadata().lock();
-
- return result;
- }
-
- /**
- * Bind a resource decorator.
- */
- public void bindResourceDecorator(final ResourceDecorator decorator,
- final Map<String, Object> props) {
- synchronized (this.resourceDecorators) {
- this.resourceDecorators.add(new ResourceDecoratorEntry(decorator,
- ServiceUtil.getComparableForServiceRanking(props)));
- Collections.sort(this.resourceDecorators);
- updateResourceDecoratorsArray();
- }
- }
-
- /**
- * Unbind a resouce decorator.
- */
- public void unbindResourceDecorator(final ResourceDecorator decorator,
- final Map<String, Object> props) {
- synchronized (this.resourceDecorators) {
- final Iterator<ResourceDecoratorEntry> i = this.resourceDecorators
- .iterator();
- while (i.hasNext()) {
- final ResourceDecoratorEntry current = i.next();
- if (current.decorator == decorator) {
- i.remove();
- break;
- }
- }
- updateResourceDecoratorsArray();
- }
- }
-
- /**
- * Updates the ResourceDecorators array, this method is not thread safe and
- * should only be called from a synchronized block.
- */
- private void updateResourceDecoratorsArray() {
- final ResourceDecorator[] decorators;
- if (this.resourceDecorators.size() > 0) {
- decorators = new ResourceDecorator[this.resourceDecorators.size()];
- int index = 0;
- final Iterator<ResourceDecoratorEntry> i = this.resourceDecorators
- .iterator();
- while (i.hasNext()) {
- decorators[index] = i.next().decorator;
- index++;
- }
- } else {
- decorators = EMPTY_ARRAY;
- }
- this.resourceDecoratorsArray = decorators;
- }
-
- /**
- * Internal class to keep track of the resource decorators.
- */
- private static final class ResourceDecoratorEntry implements
- Comparable<ResourceDecoratorEntry> {
-
- final Comparable<Object> comparable;
-
- final ResourceDecorator decorator;
-
- public ResourceDecoratorEntry(final ResourceDecorator d,
- final Comparable<Object> comparable) {
- this.comparable = comparable;
- this.decorator = d;
- }
-
- public int compareTo(final ResourceDecoratorEntry o) {
- return comparable.compareTo(o.comparable);
- }
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceIteratorDecorator.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceIteratorDecorator.java
deleted file mode 100644
index 2611c94..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceIteratorDecorator.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import java.util.Iterator;
-
-import org.apache.sling.api.resource.Resource;
-
-/**
- * Resource iterator handling the decoration of resources.
- */
-public class ResourceIteratorDecorator implements Iterator<Resource> {
-
- private final ResourceDecoratorTracker tracker;
-
- private final Iterator<Resource> iterator;
-
- public ResourceIteratorDecorator(final ResourceDecoratorTracker tracker,
- final Iterator<Resource> iterator) {
- this.tracker = tracker;
- this.iterator = iterator;
- }
-
- /**
- * @see java.util.Iterator#hasNext()
- */
- @Override
- public boolean hasNext() {
- return this.iterator.hasNext();
- }
-
- /**
- * @see java.util.Iterator#next()
- */
- @Override
- public Resource next() {
- final Resource rsrc = this.iterator.next();
- rsrc.getResourceMetadata().setResolutionPath(rsrc.getPath());
-
- return this.tracker.decorate(rsrc);
- }
-
- /**
- * @see java.util.Iterator#remove()
- */
- @Override
- public void remove() {
- this.iterator.remove();
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourcePathIterator.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourcePathIterator.java
deleted file mode 100644
index 17482eb..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourcePathIterator.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * Iterate over the the HTTP request path by creating shorter segments of that
- * path using "." as a separator.
- * <p>
- * For example, if path = /some/stuff.a4.html/xyz.ext the sequence is:
- * <ol>
- * <li> /some/stuff.a4.html/xyz.ext </li>
- * <li> /some/stuff.a4.html/xyz </li>
- * <li> /some/stuff.a4</li>
- * <li> /some/stuff </li>
- * </ol>
- * <p>
- * The root path (/) is never returned.
- */
-public class ResourcePathIterator implements Iterator<String> {
-
- // the next path to return, null if nothing more to return
- private String nextPath;
-
- /**
- * Creates a new instance iterating over the given path
- *
- * @param path The path to iterate over. If this is empty or
- * <code>null</code> this iterator will not return anything.
- */
- public ResourcePathIterator(String path) {
-
- if (path == null || path.length() == 0) {
-
- // null or empty path, there is nothing to return
- nextPath = null;
-
- } else {
-
- // find last non-slash character
- int i = path.length() - 1;
- while (i >= 0 && path.charAt(i) == '/') {
- i--;
- }
-
- if (i < 0) {
- // only slashes, assume root node
- nextPath = "/";
-
- } else if (i < path.length() - 1) {
- // cut off slash
- nextPath = path.substring(0, i + 1);
-
- } else {
- // no trailing slash
- nextPath = path;
- }
- }
- }
-
- public boolean hasNext() {
- return nextPath != null;
- }
-
- public String next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
-
- final String result = nextPath;
-
- // find next path
- int lastDot = nextPath.lastIndexOf('.');
- nextPath = (lastDot > 0) ? nextPath.substring(0, lastDot) : null;
-
- return result;
- }
-
- public void remove() {
- throw new UnsupportedOperationException("remove");
- }
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverContext.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverContext.java
deleted file mode 100644
index e9a004b..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverContext.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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 SF 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.resourceresolver.impl.helper;
-
-import javax.annotation.Nonnull;
-
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.resourceresolver.impl.ResourceAccessSecurityTracker;
-import org.apache.sling.resourceresolver.impl.providers.stateful.ProviderManager;
-
-/**
- * The resource resolver context.
- *
- * This class is not thread safe (same as the resource resolver).
- */
-public class ResourceResolverContext {
-
- private final ResourceResolver resolver;
-
- private final ProviderManager providerManager;
-
- public ResourceResolverContext(@Nonnull final ResourceResolver resolver, @Nonnull final ResourceAccessSecurityTracker tracker) {
- this.resolver = resolver;
- this.providerManager = new ProviderManager(resolver, tracker);
- }
-
- public ResourceResolver getResourceResolver() {
- return this.resolver;
- }
-
- public ProviderManager getProviderManager() {
- return this.providerManager;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java
deleted file mode 100644
index 1e6f046..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControl.java
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * 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 SF 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.resourceresolver.impl.helper;
-
-import java.io.Closeable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-
-import org.apache.commons.collections.iterators.IteratorChain;
-import org.apache.commons.lang.ArrayUtils;
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.resource.SyntheticResource;
-import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.api.resource.path.PathBuilder;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderInfo;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorageProvider;
-import org.apache.sling.resourceresolver.impl.providers.stateful.AuthenticatedResourceProvider;
-import org.apache.sling.resourceresolver.impl.providers.tree.Node;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This class takes a number of {@link AuthenticatedResourceProvider} objects and
- * exposes it as one such object. Provider appropriate for the given operation
- * is chosen basing on its {@link ResourceProviderInfo#getPath()} (more specific
- * first) and service ranking.
- *
- * Like a resource resolver itself, this class is not thread safe.
- */
-public class ResourceResolverControl {
-
- private static final Logger logger = LoggerFactory.getLogger(ResourceResolverControl.class);
-
- private static final String FORBIDDEN_ATTRIBUTE = ResourceResolverFactory.PASSWORD;
-
- /** Is this a resource resolver for an admin? */
- private final boolean isAdmin;
-
- /** The authentication info. */
- private final Map<String, Object> authenticationInfo;
-
- /** Resource type resource resolver (admin resolver) */
- private volatile ResourceResolver resourceTypeResourceResolver;
-
- /** Flag for handling multiple calls to close. */
- private final AtomicBoolean isClosed = new AtomicBoolean(false);
-
- private final ResourceProviderStorageProvider resourceProviderTracker;
-
- private final Map<ResourceProviderHandler, Object> authenticatedProviders;
-
- /**
- * Create a new resource resolver context.
- */
- public ResourceResolverControl(final boolean isAdmin,
- final Map<String, Object> authenticationInfo,
- final ResourceProviderStorageProvider resourceProviderTracker) {
- this.authenticatedProviders = new IdentityHashMap<ResourceProviderHandler, Object>();
- this.authenticationInfo = authenticationInfo;
- this.isAdmin = isAdmin;
- this.resourceProviderTracker = resourceProviderTracker;
- }
-
- /**
- * Is this an admin resource resolver?
- * @return{@code true} if it is an admin resource resolver
- */
- public boolean isAdmin() {
- return isAdmin;
- }
-
- /**
- * The authentication info
- * @return The map with the auth info
- */
- public Map<String, Object> getAuthenticationInfo() {
- return this.authenticationInfo;
- }
-
- /**
- * Is this already closed?
- * @return {@code true} if it is closed.
- */
- public boolean isClosed() {
- return this.isClosed.get();
- }
-
- /**
- * Logs out from all providers.
- */
- private void logout() {
- for(final Map.Entry<ResourceProviderHandler, Object> entry : this.authenticatedProviders.entrySet()) {
- try {
- final ResourceProvider<Object> rp = entry.getKey().getResourceProvider();
- if ( rp != null ) {
- rp.logout(entry.getValue());
- } else if ( entry.getValue() instanceof Closeable ) {
- ((Closeable)entry.getValue()).close();
- }
- } catch ( final Throwable t ) {
- // we ignore everything from there to not stop this thread
- }
- }
- this.authenticatedProviders.clear();
- }
-
- /**
- * Refreshes all refreshable providers.
- */
- public void refresh(@Nonnull final ResourceResolverContext context) {
- for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllUsedRefreshable()) {
- p.refresh();
- }
- }
-
- /**
- * Returns {@code true} if all providers are live.
- */
- public boolean isLive(@Nonnull final ResourceResolverContext context) {
- for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllAuthenticated()) {
- if (!p.isLive()) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Returns parent from the most appropriate resource provider accepting the
- * given children.
- *
- * In some cases the {@link SyntheticResource} can be returned if no
- * resource provider returns parent for this child. See
- * {@link #getResource(String, Resource, Map, boolean)} for more details
- */
- public Resource getParent(@Nonnull final ResourceResolverContext context, @Nonnull final String parentPath, @Nonnull final Resource child) {
- final AuthenticatedResourceProvider childProvider = getBestMatchingProvider(context, child.getPath());
- final AuthenticatedResourceProvider parentProvider = getBestMatchingProvider(context, parentPath);
- if ( parentProvider != null ) {
- final Resource parentCandidate;
- if ( childProvider == parentProvider ) {
- parentCandidate = parentProvider.getParent(child);
- } else {
- parentCandidate = parentProvider.getResource(parentPath, null, null);
- }
- if (parentCandidate != null) {
- return parentCandidate;
- }
- }
-
- if (isIntermediatePath(parentPath)) {
- return new SyntheticResource(context.getResourceResolver(), parentPath, ResourceProvider.RESOURCE_TYPE_SYNTHETIC);
- }
- return null;
- }
-
- /**
- * Returns resource from the most appropriate resource provider.
- * <br/><br/>
- * If there's no such provider and the path is a part of some resource
- * provider path, then the {@link SyntheticResource} will be returned. For
- * instance, if we have resource provider under
- * {@code /libs/sling/servlet/default/GET.servlet} and no resource provider
- * returns a resource for {@code /libs/sling/servlet/default}, then the
- * {@link SyntheticResource} will be returned to provide a consistent
- * resource tree.
- * <br/><br/>
- * The same behaviour occurs in {@link #getParent(Resource)} and
- * {@link #listChildren(Resource)}.
- */
- public Resource getResource(final ResourceResolverContext context,
- String path, Resource parent, Map<String, String> parameters,
- boolean isResolve) {
- if (path == null || path.length() == 0 || path.charAt(0) != '/') {
- logger.debug("Not absolute {}", path);
- return null; // path must be absolute
- }
-
- final AuthenticatedResourceProvider provider = this.getBestMatchingProvider(context, path);
- if ( provider != null ) {
- final Resource resourceCandidate = provider.getResource(path, parent, parameters);
- if (resourceCandidate != null) {
- return resourceCandidate;
- }
- }
-
- // query: /libs/sling/servlet/default
- // resource Provider: libs/sling/servlet/default/GET.servlet
- // list will match libs, sling, servlet, default
- // and there will be no resource provider at the end
- // SLING-3482 : this is only done for getResource but not resolve
- // as it is important e.g. for servlet resolution
- // to get the parent resource for resource traversal.
- if (!isResolve && isIntermediatePath(path)) {
- logger.debug("Resolved Synthetic {}", path);
- return new SyntheticResource(context.getResourceResolver(), path, ResourceProvider.RESOURCE_TYPE_SYNTHETIC);
- }
- logger.debug("Resource null {} ", path);
- return null;
- }
-
- private boolean isIntermediatePath(final String fullPath) {
- return getResourceProviderStorage().getTree().getNode(fullPath) != null;
- }
-
- /**
- * This method asks all matching resource providers for the children iterators,
- * merges them, adds {@link SyntheticResource}s (see
- * {@link #getResource(String, Resource, Map, boolean)} for more details),
- * filters out the duplicates and returns the resulting iterator. All
- * transformations are done lazily, during the {@link Iterator#hasNext()}
- * invocation on the result.
- */
- @SuppressWarnings("unchecked")
- public Iterator<Resource> listChildren(final ResourceResolverContext context, final Resource parent) {
- final String parentPath = parent.getPath();
-
- // 3 sources are combined: children of the provider which owns 'parent',
- // providers which are directly mounted at a child path,
- // synthetic resources for providers mounted at a lower level
-
- // children of the 'parent' provider
- Iterator<Resource> realChildren = null;
- final AuthenticatedResourceProvider provider = this.getBestMatchingProvider(context, parentPath);
- if ( provider != null ) {
- realChildren = provider.listChildren(parent);
- }
-
- final Set<String> visitedNames = new HashSet<String>();
-
- IteratorChain chain = new IteratorChain();
- if ( realChildren != null ) {
- chain.addIterator(realChildren);
- }
-
- // synthetic and providers are done in one loop
- final Node<ResourceProviderHandler> node = getResourceProviderStorage().getTree().getNode(parent.getPath());
- if (node != null) {
- final List<Resource> syntheticList = new ArrayList<Resource>();
- final List<Resource> providerList = new ArrayList<Resource>();
-
- for (final Entry<String, Node<ResourceProviderHandler>> entry : node.getChildren().entrySet()) {
- final String name = entry.getKey();
- final ResourceProviderHandler handler = entry.getValue().getValue();
- PathBuilder pathBuilder = new PathBuilder(parent.getPath());
- pathBuilder.append(name);
- final String childPath = pathBuilder.toString();
- if (handler == null) {
- syntheticList.add(new SyntheticResource(context.getResourceResolver(), childPath, ResourceProvider.RESOURCE_TYPE_SYNTHETIC));
- } else {
- Resource rsrc = null;
- try {
- final AuthenticatedResourceProvider rp = context.getProviderManager().getOrCreateProvider(handler, this);
- rsrc = rp == null ? null : rp.getResource(childPath, parent, null);
- } catch ( final LoginException ignore) {
- // ignore
- }
- if ( rsrc != null ) {
- providerList.add(rsrc);
- } else {
- // if there is a child provider underneath, we need to create a synthetic resource
- // otherwise we need to make sure that no one else is providing this child
- if ( entry.getValue().getChildren().isEmpty() ) {
- syntheticList.add(new SyntheticResource(context.getResourceResolver(), childPath, ResourceProvider.RESOURCE_TYPE_SYNTHETIC));
- } else {
- visitedNames.add(name);
- }
- }
- }
- }
- if ( !providerList.isEmpty() ) {
- chain.addIterator(providerList.iterator());
- }
- if ( !syntheticList.isEmpty() ) {
- chain.addIterator(syntheticList.iterator());
- }
- }
- if ( chain.size() == 0 ) {
- return Collections.EMPTY_LIST.iterator();
- }
- return new UniqueResourceIterator(visitedNames, chain);
- }
-
- /**
- * Returns the union of all attribute names.
- */
- public Collection<String> getAttributeNames(final ResourceResolverContext context) {
- final Set<String> names = new LinkedHashSet<String>();
- for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllBestEffort(getResourceProviderStorage().getAttributableHandlers(), this)) {
- p.getAttributeNames(names);
- }
- if ( this.authenticationInfo != null ) {
- names.addAll(authenticationInfo.keySet());
- }
- names.remove(FORBIDDEN_ATTRIBUTE);
- return names;
- }
-
- /**
- * Returns the first non-null result of the
- * {@link AuthenticatedResourceProvider#getAttribute(String)} invocation on
- * the providers.
- */
- public Object getAttribute(final ResourceResolverContext context, final String name) {
- if (FORBIDDEN_ATTRIBUTE.equals(name)) {
- return null;
- }
- for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllBestEffort(getResourceProviderStorage().getAttributableHandlers(), this)) {
- final Object attribute = p.getAttribute(name);
- if (attribute != null) {
- return attribute;
- }
- }
- return this.authenticationInfo != null ? this.authenticationInfo.get(name) :null;
- }
-
- /**
- * Create a resource.
- *
- * @throws UnsupportedOperationException
- * If creation is not allowed/possible
- * @throws PersistenceException
- * If creation fails
- * @return The new resource
- */
- public Resource create(final ResourceResolverContext context,
- final String path, final Map<String, Object> properties)
- throws PersistenceException {
- final AuthenticatedResourceProvider provider = getBestMatchingModifiableProvider(context, path);
- if ( provider != null ) {
- final Resource creationResultResource = provider.create(context.getResourceResolver(), path, properties);
- if (creationResultResource != null) {
- return creationResultResource;
- }
- }
- throw new UnsupportedOperationException("create '" + ResourceUtil.getName(path) + "' at " + ResourceUtil.getParent(path));
- }
-
- /**
- * Delete the resource. Iterate over all modifiable ResourceProviders
- * giving each an opportunity to delete the resource if they are able.
- *
- * @throws NullPointerException
- * if resource is null
- * @throws UnsupportedOperationException
- * If deletion is not allowed/possible
- * @throws PersistenceException
- * If deletion fails
- */
- public void delete(final ResourceResolverContext context, final Resource resource) throws PersistenceException {
- final String path = resource.getPath();
- final AuthenticatedResourceProvider provider = getBestMatchingModifiableProvider(context, path);
- if ( provider != null ) {
- provider.delete(resource);
- return;
- }
- throw new UnsupportedOperationException("delete at '" + path + "'");
- }
-
- /**
- * Revert changes on all modifiable ResourceProviders.
- */
- public void revert(final ResourceResolverContext context) {
- for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllUsedModifiable()) {
- p.revert();
- }
- }
-
- /**
- * Commit changes on all modifiable ResourceProviders.
- */
- public void commit(final ResourceResolverContext context) throws PersistenceException {
- for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllUsedModifiable()) {
- p.commit();
- }
- }
-
- /**
- * Check if any modifiable ResourceProvider has uncommited changes.
- */
- public boolean hasChanges(final ResourceResolverContext context) {
- for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllUsedModifiable()) {
- if (p.hasChanges()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Return the union of query languages supported by the providers.
- */
- public String[] getSupportedLanguages(final ResourceResolverContext context) {
- final Set<String> supportedLanguages = new LinkedHashSet<String>();
- for (AuthenticatedResourceProvider p : context.getProviderManager().getAllBestEffort(getResourceProviderStorage().getLanguageQueryableHandlers(), this)) {
- supportedLanguages.addAll(Arrays.asList(p.getSupportedLanguages()));
- }
- return supportedLanguages.toArray(new String[supportedLanguages.size()]);
- }
-
- /**
- * Queries all resource providers and combines the results.
- */
- public Iterator<Resource> findResources(final ResourceResolverContext context,
- final String query, final String language) {
- final List<AuthenticatedResourceProvider> queryableRP = getQueryableProviders(context, language);
- final List<Iterator<Resource>> iterators = new ArrayList<Iterator<Resource>>(queryableRP.size());
- for (AuthenticatedResourceProvider p : queryableRP) {
- iterators.add(p.findResources(query, language));
- }
- return new ChainedIterator<Resource>(iterators.iterator());
- }
-
- private List<AuthenticatedResourceProvider> getQueryableProviders(
- final ResourceResolverContext context,
- final String language) {
- final List<AuthenticatedResourceProvider> queryableProviders = new ArrayList<AuthenticatedResourceProvider>();
- for (final AuthenticatedResourceProvider p : context.getProviderManager().getAllBestEffort(getResourceProviderStorage().getLanguageQueryableHandlers(), this)) {
- if (ArrayUtils.contains(p.getSupportedLanguages(), language)) {
- queryableProviders.add(p);
- }
- }
- return queryableProviders;
- }
-
- /**
- * Queries all resource providers and combines the results.
- */
- public Iterator<Map<String, Object>> queryResources(final ResourceResolverContext context,
- final String query, final String language) {
- final List<AuthenticatedResourceProvider> queryableRP = getQueryableProviders(context, language);
- final List<Iterator<Map<String, Object>>> iterators = new ArrayList<Iterator<Map<String, Object>>>(queryableRP.size());
- for (AuthenticatedResourceProvider p : queryableRP) {
- iterators.add(p.queryResources(query, language));
- }
- return new ChainedIterator<Map<String, Object>>(iterators.iterator());
- }
-
- /**
- * Returns the first non-null result of the adaptTo() method invoked on the
- * providers.
- */
- @SuppressWarnings("unchecked")
- public <AdapterType> AdapterType adaptTo(final ResourceResolverContext context, Class<AdapterType> type) {
- for (AuthenticatedResourceProvider p : context.getProviderManager().getAllBestEffort(getResourceProviderStorage().getAdaptableHandlers(), this)) {
- final Object adaptee = p.adaptTo(type);
- if (adaptee != null) {
- return (AdapterType) adaptee;
- }
- }
- return null;
- }
-
- private AuthenticatedResourceProvider checkSourceAndDest(final ResourceResolverContext context,
- final String srcAbsPath, final String destAbsPath) throws PersistenceException {
- // check source
- final Node<ResourceProviderHandler> srcNode = getResourceProviderStorage().getTree().getBestMatchingNode(srcAbsPath);
- if ( srcNode == null ) {
- throw new PersistenceException("Source resource does not exist.", null, srcAbsPath, null);
- }
- AuthenticatedResourceProvider srcProvider = null;
- try {
- srcProvider = context.getProviderManager().getOrCreateProvider(srcNode.getValue(), this);
- } catch (LoginException e) {
- // ignore
- }
- if ( srcProvider == null ) {
- throw new PersistenceException("Source resource does not exist.", null, srcAbsPath, null);
- }
- final Resource srcResource = srcProvider.getResource(srcAbsPath, null, null);
- if ( srcResource == null ) {
- throw new PersistenceException("Source resource does not exist.", null, srcAbsPath, null);
- }
-
- // check destination
- final Node<ResourceProviderHandler> destNode = getResourceProviderStorage().getTree().getBestMatchingNode(destAbsPath);
- if ( destNode == null ) {
- throw new PersistenceException("Destination resource does not exist.", null, destAbsPath, null);
- }
- AuthenticatedResourceProvider destProvider = null;
- try {
- destProvider = context.getProviderManager().getOrCreateProvider(destNode.getValue(), this);
- } catch (LoginException e) {
- // ignore
- }
- if ( destProvider == null ) {
- throw new PersistenceException("Destination resource does not exist.", null, destAbsPath, null);
- }
- final Resource destResource = destProvider.getResource(destAbsPath, null, null);
- if ( destResource == null ) {
- throw new PersistenceException("Destination resource does not exist.", null, destAbsPath, null);
- }
-
- // check for sub providers of src and dest
- if ( srcProvider == destProvider && !collectProviders(context, srcNode) && !collectProviders(context, destNode) ) {
- return srcProvider;
- }
- return null;
- }
-
- private boolean collectProviders(final ResourceResolverContext context,
- final Node<ResourceProviderHandler> parent) {
- boolean hasMoreProviders = false;
- for (final Entry<String, Node<ResourceProviderHandler>> entry : parent.getChildren().entrySet()) {
- if ( entry.getValue().getValue() != null ) {
- try {
- context.getProviderManager().getOrCreateProvider(entry.getValue().getValue(), this);
- hasMoreProviders = true;
- } catch ( final LoginException ignore) {
- // ignore
- }
- }
- if ( collectProviders(context, entry.getValue())) {
- hasMoreProviders = true;
- }
- }
-
- return hasMoreProviders;
- }
-
- private void copy(final ResourceResolverContext context, final Resource src, final String dstPath, final List<Resource> newNodes) throws PersistenceException {
- final ValueMap vm = src.getValueMap();
- final String createPath = new PathBuilder(dstPath).append(src.getName()).toString();
- newNodes.add(this.create(context, createPath, vm));
- for(final Resource c : src.getChildren()) {
- copy(context, c, createPath, newNodes);
- }
- }
-
- /**
- * Tries to find a resource provider accepting both paths and invokes
- * {@link AuthenticatedResourceProvider#copy(String, String)} method on it.
- * Returns false if there's no such provider.
- */
- public Resource copy(final ResourceResolverContext context,
- final String srcAbsPath, final String destAbsPath) throws PersistenceException {
- final AuthenticatedResourceProvider optimizedSourceProvider = checkSourceAndDest(context, srcAbsPath, destAbsPath);
- if ( optimizedSourceProvider != null && optimizedSourceProvider.copy(srcAbsPath, destAbsPath) ) {
- return this.getResource(context, destAbsPath + '/' + ResourceUtil.getName(srcAbsPath), null, null, false);
- }
-
- final Resource srcResource = this.getResource(context, srcAbsPath, null, null, false);
- final List<Resource> newResources = new ArrayList<Resource>();
- boolean rollback = true;
- try {
- this.copy(context, srcResource, destAbsPath, newResources);
- rollback = false;
- return newResources.get(0);
- } finally {
- if ( rollback ) {
- for(final Resource rsrc : newResources) {
- this.delete(context, rsrc);
- }
- }
- }
- }
-
- /**
- * Tries to find a resource provider accepting both paths and invokes
- * {@link AuthenticatedResourceProvider#move(String, String)} method on it.
- * Returns false if there's no such provider.
- */
- public Resource move(final ResourceResolverContext context,
- String srcAbsPath, String destAbsPath) throws PersistenceException {
- final AuthenticatedResourceProvider optimizedSourceProvider = checkSourceAndDest(context, srcAbsPath, destAbsPath);
- if ( optimizedSourceProvider != null && optimizedSourceProvider.move(srcAbsPath, destAbsPath) ) {
- return this.getResource(context, destAbsPath + '/' + ResourceUtil.getName(srcAbsPath), null, null, false);
- }
- final Resource srcResource = this.getResource(context, srcAbsPath, null, null, false);
- final List<Resource> newResources = new ArrayList<Resource>();
- boolean rollback = true;
- try {
- this.copy(context, srcResource, destAbsPath, newResources);
- this.delete(context, srcResource);
- rollback = false;
- return newResources.get(0);
- } finally {
- if ( rollback ) {
- for(final Resource rsrc : newResources) {
- this.delete(context, rsrc);
- }
- }
- }
- }
-
- public ResourceProviderStorage getResourceProviderStorage() {
- return this.resourceProviderTracker.getResourceProviderStorage();
- }
-
- /**
- * @param path
- * @return
- */
- private @CheckForNull AuthenticatedResourceProvider getBestMatchingProvider(final ResourceResolverContext context,
- final String path) {
- try {
- final Node<ResourceProviderHandler> node = resourceProviderTracker.getResourceProviderStorage().getTree().getBestMatchingNode(path);
- return node == null ? null : context.getProviderManager().getOrCreateProvider(node.getValue(), this);
- } catch ( final LoginException le ) {
- // ignore
- return null;
- }
- }
-
- /**
- * @param path
- * @return The modifiable provider or {@code null}
- */
- private @CheckForNull AuthenticatedResourceProvider getBestMatchingModifiableProvider(
- final ResourceResolverContext context,
- final String path) {
- final Node<ResourceProviderHandler> node = resourceProviderTracker.getResourceProviderStorage().getTree().getBestMatchingNode(path);
- if ( node != null && node.getValue().getInfo().isModifiable() ) {
- try {
- return context.getProviderManager().getOrCreateProvider(node.getValue(), this);
- } catch ( final LoginException le ) {
- // ignore
- return null;
- }
- }
- return null;
- }
-
-
- /**
- * Close all dynamic resource providers.
- */
- public void close() {
- if (this.isClosed.compareAndSet(false, true)) {
- this.logout();
- if ( this.resourceTypeResourceResolver != null ) {
- try {
- this.resourceTypeResourceResolver.close();
- } catch ( final Throwable t) {
- // the resolver (or the underlying provider) might already be terminated (bundle stopped etc.)
- // so we ignore anything from here
- }
- this.resourceTypeResourceResolver = null;
- }
- }
- }
-
- @SuppressWarnings("deprecation")
- private ResourceResolver getResourceTypeResourceResolver(
- final ResourceResolverFactory factory,
- final ResourceResolver resolver) {
- if ( this.isAdmin ) {
- return resolver;
- } else {
- if ( this.resourceTypeResourceResolver == null ) {
- try {
- this.resourceTypeResourceResolver = factory.getAdministrativeResourceResolver(null);
- } catch (final LoginException e) {
- // we simply ignore this and return null
- }
- }
- return this.resourceTypeResourceResolver;
- }
- }
-
- /**
- * Get the parent resource type
- *
- * @see org.apache.sling.api.resource.ResourceResolver#getParentResourceType(java.lang.String)
- */
- public String getParentResourceType(
- final ResourceResolverFactory factory,
- final ResourceResolver resolver,
- final String resourceType) {
- // normalize resource type to a path string
- final String rtPath = (resourceType == null ? null : ResourceUtil.resourceTypeToPath(resourceType));
- // get the resource type resource and check its super type
- String resourceSuperType = null;
-
- if ( rtPath != null ) {
- ResourceResolver adminResolver = this.getResourceTypeResourceResolver(factory, resolver);
- if ( adminResolver != null ) {
- final Resource rtResource = adminResolver.getResource(rtPath);
- if (rtResource != null) {
- resourceSuperType = rtResource.getResourceSuperType();
- }
- }
- }
- return resourceSuperType;
- }
-
- /**
- * Returns {@link #getProperty(Resource, String, Class) getProperty(res,
- * propName, String.class)}
- *
- * @param res The resource to access the property from
- * @param propName The name of the property to access
- * @return The property as a {@code String} or {@code null} if the property
- * does not exist or cannot be converted into a {@code String}
- */
- public static String getProperty(final Resource res, final String propName) {
- return getProperty(res, propName, String.class);
- }
-
- /**
- * Returns the value of the name property of the resource converted to the
- * requested {@code type}.
- * <p>
- * If the resource itself does not have the property, the property is looked
- * up in the {@code jcr:content} child node. This access is done through the
- * same {@code ValueMap} as is used to access the property directly. This
- * generally only works for JCR based {@code ValueMap} instances which
- * provide access to relative path property names. This may not work in non
- * JCR {@code ValueMap}, however in non JCR envs there is usually no
- * "jcr:content" child node anyway
- *
- * @param res The resource to access the property from
- * @param propName The name of the property to access
- * @param type The type into which to convert the property
- * @return The property converted to the requested {@code type} or
- * {@code null} if the property does not exist or cannot be
- * converted into the requested {@code type}
- */
- public static <Type> Type getProperty(final Resource res, final String propName, final Class<Type> type) {
-
- // check the property in the resource itself
- final ValueMap props = res.adaptTo(ValueMap.class);
- if (props != null) {
- Type prop = props.get(propName, type);
- if (prop != null) {
- return prop;
- }
- // otherwise, check it in the jcr:content child resource
- // This is a special case checking for JCR based resources
- // we directly use the deep resolution of properties of the
- // JCR value map implementation - this does not work
- // in non JCR environments, however in non JCR envs there
- // is usually no "jcr:content" child node anyway
- prop = props.get("jcr:content/" + propName, type);
- return prop;
- }
-
- return null;
- }
-
- public void registerAuthenticatedProvider(@Nonnull ResourceProviderHandler handler,
- @CheckForNull Object providerState) {
- this.authenticatedProviders.put(handler, providerState);
- }
-
- public void clearAuthenticatedProviders() {
- this.authenticatedProviders.clear();
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/StarResource.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/StarResource.java
deleted file mode 100644
index 74f148d..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/StarResource.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import org.apache.sling.adapter.annotations.Adaptable;
-import org.apache.sling.adapter.annotations.Adapter;
-import org.apache.sling.api.SlingException;
-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.SyntheticResource;
-
-/**
- * Used to provide the equivalent of an empty Node for GET requests to
- * *.something (SLING-344)
- */
-@Adaptable(adaptableClass = Resource.class, adapters = @Adapter(value = { String.class }))
-public class StarResource extends SyntheticResource {
-
- final static String SLASH_STAR = "/*";
- public final static String DEFAULT_RESOURCE_TYPE = "sling:syntheticStarResource";
-
- private static final String UNSET_RESOURCE_SUPER_TYPE = "<unset>";
-
- private String resourceSuperType;
-
- @SuppressWarnings("serial")
- static class SyntheticStarResourceException extends SlingException {
- SyntheticStarResourceException(String reason, Throwable cause) {
- super(reason, cause);
- }
- }
-
- /**
- * True if a StarResource should be used for the given request, if a real
- * Resource was not found
- */
- public static boolean appliesTo(String path) {
- return path.contains(SLASH_STAR) || path.endsWith(SLASH_STAR);
- }
-
- /**
- * Returns true if the path of the resource ends with the
- * {@link #SLASH_STAR} and therefore should be considered a star resource.
- */
- public static boolean isStarResource(Resource res) {
- return res.getPath().endsWith(SLASH_STAR);
- }
-
- public StarResource(ResourceResolver resourceResolver, String path) {
- super(resourceResolver, getResourceMetadata(path),
- DEFAULT_RESOURCE_TYPE);
- resourceSuperType = UNSET_RESOURCE_SUPER_TYPE;
- }
-
- /**
- * Calls {@link ResourceUtil#getResourceSuperType(ResourceResolver, String)}
- * method to dynamically resolve the resource super type of this star
- * resource.
- */
- @Override
- public String getResourceSuperType() {
- // Yes, this isn't how you're supposed to compare Strings, but this is
- // intentional.
- if (resourceSuperType == UNSET_RESOURCE_SUPER_TYPE) {
- resourceSuperType = this.getResourceResolver().getParentResourceType(this.getResourceType());
- }
- return resourceSuperType;
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public <Type> Type adaptTo(Class<Type> type) {
- if (type == String.class) {
- return (Type) "";
- }
- return super.adaptTo(type);
- }
-
- /** Get our ResourceMetadata for given path */
- static ResourceMetadata getResourceMetadata(String path) {
- ResourceMetadata result = new ResourceMetadata();
-
- // The path is up to /*, what follows is pathInfo
- final int index = path.indexOf(SLASH_STAR);
- if (index >= 0) {
- result.setResolutionPath(path.substring(0, index) + SLASH_STAR);
- result.setResolutionPathInfo(path.substring(index
- + SLASH_STAR.length()));
- } else {
- result.setResolutionPath(path);
- }
- return result;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/URI.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/URI.java
deleted file mode 100644
index 231c65c..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/URI.java
+++ /dev/null
@@ -1,4200 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.Locale;
-
-import org.apache.sling.api.SlingException;
-
-/**
- * The interface for the URI(Uniform Resource Identifiers) version of RFC 2396.
- * This class has the purpose of supportting of parsing a URI reference to
- * extend any specific protocols, the character encoding of the protocol to be
- * transported and the charset of the document.
- *
- * A URI is always in an "escaped" form, since escaping or unescaping a
- * completed URI might change its semantics.
- *
- * Implementers should be careful not to escape or unescape the same string more
- * than once, since unescaping an already unescaped string might lead to
- * misinterpreting a percent data character as another escaped character, or
- * vice versa in the case of escaping an already escaped string.
- *
- * In order to avoid these problems, data types used as follows:
- *
- * <blockquote>
- *
- * <pre>
- * URI character sequence: char
- * octet sequence: byte
- * original character sequence: String
- * </pre>
- *
- * </blockquote>
- *
- * So, a URI is a sequence of characters as an array of a char type, which is
- * not always represented as a sequence of octets as an array of byte.
- *
- * URI Syntactic Components
- *
- * <blockquote>
- *
- * <pre>
- * - In general, written as follows:
- * Absolute URI = <scheme>:<scheme-specific-part>
- * Generic URI = <scheme>://<authority><path>?<query>
- * - Syntax
- * absoluteURI = scheme ":" ( hier_part | opaque_part )
- * hier_part = ( net_path | abs_path ) [ "?" query ]
- * net_path = "//" authority [ abs_path ]
- * abs_path = "/" path_segments
- * </pre>
- *
- * </blockquote>
- *
- * The following examples illustrate URI that are in common use.
- *
- * <pre>
- * ftp://ftp.is.co.za/rfc/rfc1808.txt
- * -- ftp scheme for File Transfer Protocol services
- * gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles
- * -- gopher scheme for Gopher and Gopher+ Protocol services
- * http://www.math.uio.no/faq/compression-faq/part1.html
- * -- http scheme for Hypertext Transfer Protocol services
- * mailto:mduerst@ifi.unizh.ch
- * -- mailto scheme for electronic mail addresses
- * news:comp.infosystems.www.servers.unix
- * -- news scheme for USENET news groups and articles
- * telnet://melvyl.ucop.edu/
- * -- telnet scheme for interactive services via the TELNET Protocol
- * </pre>
- *
- * Please, notice that there are many modifications from URL(RFC 1738) and
- * relative URL(RFC 1808).
- *
- * <b>The expressions for a URI</b>
- *
- *
- * <pre>
- * For escaped URI forms
- * - URI(char[]) // constructor
- * - char[] getRawXxx() // method
- * - String getEscapedXxx() // method
- * - String toString() // method
- *
- * For unescaped URI forms
- * - URI(String) // constructor
- * - String getXXX() // method
- * </pre>
- *
- * This class is a slightly modified version of the URI class distributed with
- * Http Client 3.1. The changes involve removing dependencies to other Http
- * Client classes and the Commons Codec library. To this avail the following
- * methods have been added to this class:
- * <ul>
- * <li>getBytes, getAsciiString, getString, getAsciiBytes has been copied from
- * the Http Client 3.1 EncodingUtils class.</li>
- * <li>encodeUrl and decodeUrl have been copied from the Commons Codec URLCodec
- * class.</li>
- * </ul>
- * The signatures have been simplified and adapted to the use in this class.
- * Also the exception thrown has been changed to be {@link URIException}.
- */
-public class URI implements Cloneable, Comparable<URI>, Serializable {
-
- // ----------------------------------------------------------- Constructors
-
- /** Create an instance as an internal use */
- protected URI() {
- }
-
- /**
- * Construct a URI from a string with the given charset. The input string
- * can be either in escaped or unescaped form.
- *
- * @param s URI character sequence
- * @param escaped <tt>true</tt> if URI character sequence is in escaped
- * form. <tt>false</tt> otherwise.
- * @param charset the charset string to do escape encoding, if required
- * @throws URIException If the URI cannot be created.
- * @throws NullPointerException if input string is <code>null</code>
- * @see #getProtocolCharset
- * @since 3.0
- */
- public URI(String s, boolean escaped, String charset) throws URIException,
- NullPointerException {
- protocolCharset = charset;
- parseUriReference(s, escaped);
- }
-
- /**
- * Construct a URI from a string with the given charset. The input string
- * can be either in escaped or unescaped form.
- *
- * @param s URI character sequence
- * @param escaped <tt>true</tt> if URI character sequence is in escaped
- * form. <tt>false</tt> otherwise.
- * @throws URIException If the URI cannot be created.
- * @throws NullPointerException if input string is <code>null</code>
- * @see #getProtocolCharset
- * @since 3.0
- */
- public URI(String s, boolean escaped) throws URIException,
- NullPointerException {
- parseUriReference(s, escaped);
- }
-
- /**
- * Construct a general URI from the given components.
- *
- * <blockquote>
- *
- * <pre>
- * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
- * absoluteURI = scheme ":" ( hier_part | opaque_part )
- * opaque_part = uric_no_slash *uric
- * </pre>
- *
- * </blockquote>
- *
- * It's for absolute URI = <scheme>:<scheme-specific-part>#
- * <fragment>.
- *
- * @param scheme the scheme string
- * @param schemeSpecificPart scheme_specific_part
- * @param fragment the fragment string
- * @throws URIException If the URI cannot be created.
- * @see #getDefaultProtocolCharset
- */
- public URI(String scheme, String schemeSpecificPart, String fragment)
- throws URIException {
-
- // validate and contruct the URI character sequence
- if (scheme == null) {
- throw new URIException(URIException.PARSING, "scheme required");
- }
- char[] s = scheme.toLowerCase().toCharArray();
- if (validate(s, URI.scheme)) {
- _scheme = s; // is_absoluteURI
- } else {
- throw new URIException(URIException.PARSING, "incorrect scheme");
- }
- _opaque = encode(schemeSpecificPart, allowed_opaque_part,
- getProtocolCharset());
- // Set flag
- _is_opaque_part = true;
- _fragment = fragment == null ? null : fragment.toCharArray();
- setURI();
- }
-
- /**
- * Construct a general URI from the given components.
- *
- * <blockquote>
- *
- * <pre>
- * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
- * absoluteURI = scheme ":" ( hier_part | opaque_part )
- * relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
- * hier_part = ( net_path | abs_path ) [ "?" query ]
- * </pre>
- *
- * </blockquote>
- *
- * It's for absolute URI = <scheme>:<path>?<query>#<
- * fragment> and relative URI = <path>?<query>#<fragment
- * >.
- *
- * @param scheme the scheme string
- * @param authority the authority string
- * @param path the path string
- * @param query the query string
- * @param fragment the fragment string
- * @throws URIException If the new URI cannot be created.
- * @see #getDefaultProtocolCharset
- */
- public URI(String scheme, String authority, String path, String query,
- String fragment) throws URIException {
-
- // validate and contruct the URI character sequence
- StringBuilder buff = new StringBuilder();
- if (scheme != null) {
- buff.append(scheme);
- buff.append(':');
- }
- if (authority != null) {
- buff.append("//");
- buff.append(authority);
- }
- if (path != null) { // accept empty path
- if ((scheme != null || authority != null) && !path.startsWith("/")) {
- throw new URIException(URIException.PARSING,
- "abs_path requested");
- }
- buff.append(path);
- }
- if (query != null) {
- buff.append('?');
- buff.append(query);
- }
- if (fragment != null) {
- buff.append('#');
- buff.append(fragment);
- }
- parseUriReference(buff.toString(), false);
- }
-
- /**
- * Construct a general URI from the given components.
- *
- * @param scheme the scheme string
- * @param userinfo the userinfo string
- * @param host the host string
- * @param port the port number
- * @throws URIException If the new URI cannot be created.
- * @see #getDefaultProtocolCharset
- */
- public URI(String scheme, String userinfo, String host, int port)
- throws URIException {
-
- this(scheme, userinfo, host, port, null, null, null);
- }
-
- /**
- * Construct a general URI from the given components.
- *
- * @param scheme the scheme string
- * @param userinfo the userinfo string
- * @param host the host string
- * @param port the port number
- * @param path the path string
- * @throws URIException If the new URI cannot be created.
- * @see #getDefaultProtocolCharset
- */
- public URI(String scheme, String userinfo, String host, int port,
- String path) throws URIException {
-
- this(scheme, userinfo, host, port, path, null, null);
- }
-
- /**
- * Construct a general URI from the given components.
- *
- * @param scheme the scheme string
- * @param userinfo the userinfo string
- * @param host the host string
- * @param port the port number
- * @param path the path string
- * @param query the query string
- * @throws URIException If the new URI cannot be created.
- * @see #getDefaultProtocolCharset
- */
- public URI(String scheme, String userinfo, String host, int port,
- String path, String query) throws URIException {
-
- this(scheme, userinfo, host, port, path, query, null);
- }
-
- /**
- * Construct a general URI from the given components.
- *
- * @param scheme the scheme string
- * @param userinfo the userinfo string
- * @param host the host string
- * @param port the port number
- * @param path the path string
- * @param query the query string
- * @param fragment the fragment string
- * @throws URIException If the new URI cannot be created.
- * @see #getDefaultProtocolCharset
- */
- public URI(String scheme, String userinfo, String host, int port,
- String path, String query, String fragment) throws URIException {
-
- this(scheme, (host == null) ? null : ((userinfo != null)
- ? userinfo + '@'
- : "")
- + host + ((port != -1) ? ":" + port : ""), path, query, fragment);
- }
-
- /**
- * Construct a general URI from the given components.
- *
- * @param scheme the scheme string
- * @param host the host string
- * @param path the path string
- * @param fragment the fragment string
- * @throws URIException If the new URI cannot be created.
- * @see #getDefaultProtocolCharset
- */
- public URI(String scheme, String host, String path, String fragment)
- throws URIException {
-
- this(scheme, host, path, null, fragment);
- }
-
- /**
- * Construct a general URI with the given relative URI string.
- *
- * @param base the base URI
- * @param relative the relative URI string
- * @param escaped <tt>true</tt> if URI character sequence is in escaped
- * form. <tt>false</tt> otherwise.
- * @throws URIException If the new URI cannot be created.
- * @since 3.0
- */
- public URI(URI base, String relative, boolean escaped) throws URIException {
- this(base, new URI(relative, escaped));
- }
-
- /**
- * Construct a general URI with the given relative URI.
- *
- * <blockquote>
- *
- * <pre>
- * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
- * relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
- * </pre>
- *
- * </blockquote>
- *
- * Resolving Relative References to Absolute Form. <strong>Examples of
- * Resolving Relative URI References</strong> Within an object with a
- * well-defined base URI of
- *
- * <blockquote>
- *
- * <pre>
- * http://a/b/c/d;p?q
- * </pre>
- *
- * </blockquote>
- *
- * the relative URI would be resolved as follows: Normal Examples
- *
- * <blockquote>
- *
- * <pre>
- * g:h = g:h
- * g = http://a/b/c/g
- * ./g = http://a/b/c/g
- * g/ = http://a/b/c/g/
- * /g = http://a/g
- * //g = http://g
- * ?y = http://a/b/c/?y
- * g?y = http://a/b/c/g?y
- * #s = (current document)#s
- * g#s = http://a/b/c/g#s
- * g?y#s = http://a/b/c/g?y#s
- * ;x = http://a/b/c/;x
- * g;x = http://a/b/c/g;x
- * g;x?y#s = http://a/b/c/g;x?y#s
- * . = http://a/b/c/
- * ./ = http://a/b/c/
- * .. = http://a/b/
- * ../ = http://a/b/
- * ../g = http://a/b/g
- * ../.. = http://a/
- * ../../ = http://a/
- * ../../g = http://a/g
- * </pre>
- *
- * </blockquote>
- *
- * Some URI schemes do not allow a hierarchical syntax matching the
- * <hier_part> syntax, and thus cannot use relative references.
- *
- * @param base the base URI
- * @param relative the relative URI
- * @throws URIException If the new URI cannot be created.
- */
- public URI(URI base, URI relative) throws URIException {
-
- if (base._scheme == null) {
- throw new URIException(URIException.PARSING, "base URI required");
- }
- if (base._scheme != null) {
- this._scheme = base._scheme;
- this._authority = base._authority;
- this._is_net_path = base._is_net_path;
- }
- if (base._is_opaque_part || relative._is_opaque_part) {
- this._scheme = base._scheme;
- this._is_opaque_part = base._is_opaque_part
- || relative._is_opaque_part;
- this._opaque = relative._opaque;
- this._fragment = relative._fragment;
- this.setURI();
- return;
- }
- boolean schemesEqual = Arrays.equals(base._scheme, relative._scheme);
- if (relative._scheme != null
- && (!schemesEqual || relative._authority != null)) {
- this._scheme = relative._scheme;
- this._is_net_path = relative._is_net_path;
- this._authority = relative._authority;
- if (relative._is_server) {
- this._is_server = relative._is_server;
- this._userinfo = relative._userinfo;
- this._host = relative._host;
- this._port = relative._port;
- } else if (relative._is_reg_name) {
- this._is_reg_name = relative._is_reg_name;
- }
- this._is_abs_path = relative._is_abs_path;
- this._is_rel_path = relative._is_rel_path;
- this._path = relative._path;
- } else if (base._authority != null && relative._scheme == null) {
- this._is_net_path = base._is_net_path;
- this._authority = base._authority;
- if (base._is_server) {
- this._is_server = base._is_server;
- this._userinfo = base._userinfo;
- this._host = base._host;
- this._port = base._port;
- } else if (base._is_reg_name) {
- this._is_reg_name = base._is_reg_name;
- }
- }
- if (relative._authority != null) {
- this._is_net_path = relative._is_net_path;
- this._authority = relative._authority;
- if (relative._is_server) {
- this._is_server = relative._is_server;
- this._userinfo = relative._userinfo;
- this._host = relative._host;
- this._port = relative._port;
- } else if (relative._is_reg_name) {
- this._is_reg_name = relative._is_reg_name;
- }
- this._is_abs_path = relative._is_abs_path;
- this._is_rel_path = relative._is_rel_path;
- this._path = relative._path;
- }
- // resolve the path and query if necessary
- if (relative._authority == null
- && (relative._scheme == null || schemesEqual)) {
- if ((relative._path == null || relative._path.length == 0)
- && relative._query == null) {
- // handle a reference to the current document, see RFC 2396
- // section 5.2 step 2
- this._path = base._path;
- this._query = base._query;
- } else {
- this._path = resolvePath(base._path, relative._path);
- }
- }
- // base._query removed
- if (relative._query != null) {
- this._query = relative._query;
- }
- // base._fragment removed
- if (relative._fragment != null) {
- this._fragment = relative._fragment;
- }
- this.setURI();
- // reparse the newly built URI, this will ensure that all flags are set
- // correctly.
- // TODO there must be a better way to do this
- parseUriReference(new String(_uri), true);
- }
-
- // --------------------------------------------------- Instance Variables
-
- /** Version ID for serialization */
- static final long serialVersionUID = 604752400577948726L;
-
- /**
- * Cache the hash code for this URI.
- */
- protected int hash = 0;
-
- /**
- * This Uniform Resource Identifier (URI). The URI is always in an "escaped"
- * form, since escaping or unescaping a completed URI might change its
- * semantics.
- */
- protected char[] _uri = null;
-
- /**
- * The charset of the protocol used by this URI instance.
- */
- protected String protocolCharset = null;
-
- /**
- * The default charset of the protocol. RFC 2277, 2396
- */
- protected static String defaultProtocolCharset = "UTF-8";
-
- /**
- * The default charset of the document. RFC 2277, 2396 The platform's
- * charset is used for the document by default.
- */
- protected static String defaultDocumentCharset = null;
-
- protected static String defaultDocumentCharsetByLocale = null;
-
- protected static String defaultDocumentCharsetByPlatform = null;
- // Static initializer for defaultDocumentCharset
- static {
- Locale locale = Locale.getDefault();
- // in order to support backward compatiblity
- if (locale != null) {
- defaultDocumentCharsetByLocale = LocaleToCharsetMap.getCharset(locale);
- // set the default document charset
- defaultDocumentCharset = defaultDocumentCharsetByLocale;
- }
- // in order to support platform encoding
- try {
- defaultDocumentCharsetByPlatform = System.getProperty("file.encoding");
- } catch (SecurityException ignore) {
- }
- if (defaultDocumentCharset == null) {
- // set the default document charset
- defaultDocumentCharset = defaultDocumentCharsetByPlatform;
- }
- }
-
- /**
- * The scheme.
- */
- protected char[] _scheme = null;
-
- /**
- * The opaque.
- */
- protected char[] _opaque = null;
-
- /**
- * The authority.
- */
- protected char[] _authority = null;
-
- /**
- * The userinfo.
- */
- protected char[] _userinfo = null;
-
- /**
- * The host.
- */
- protected char[] _host = null;
-
- /**
- * The port.
- */
- protected int _port = -1;
-
- /**
- * The path.
- */
- protected char[] _path = null;
-
- /**
- * The query.
- */
- protected char[] _query = null;
-
- /**
- * The fragment.
- */
- protected char[] _fragment = null;
-
- /**
- * The root path.
- */
- protected static final char[] rootPath = { '/' };
-
- // ---------------------- Generous characters for each component validation
-
- /**
- * The percent "%" character always has the reserved purpose of being the
- * escape indicator, it must be escaped as "%25" in order to be used as data
- * within a URI.
- */
- protected static final BitSet percent = new BitSet(256);
- // Static initializer for percent
- static {
- percent.set('%');
- }
-
- /**
- * BitSet for digit.
- *
- * <blockquote>
- *
- * <pre>
- * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet digit = new BitSet(256);
- // Static initializer for digit
- static {
- for (int i = '0'; i <= '9'; i++) {
- digit.set(i);
- }
- }
-
- /**
- * BitSet for alpha.
- *
- * <blockquote>
- *
- * <pre>
- * alpha = lowalpha | upalpha
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet alpha = new BitSet(256);
- // Static initializer for alpha
- static {
- for (int i = 'a'; i <= 'z'; i++) {
- alpha.set(i);
- }
- for (int i = 'A'; i <= 'Z'; i++) {
- alpha.set(i);
- }
- }
-
- /**
- * BitSet for alphanum (join of alpha & digit).
- *
- * <blockquote>
- *
- * <pre>
- * alphanum = alpha | digit
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet alphanum = new BitSet(256);
- // Static initializer for alphanum
- static {
- alphanum.or(alpha);
- alphanum.or(digit);
- }
-
- /**
- * BitSet for hex.
- *
- * <blockquote>
- *
- * <pre>
- * hex = digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e"
- * | "f"
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet hex = new BitSet(256);
- // Static initializer for hex
- static {
- hex.or(digit);
- for (int i = 'a'; i <= 'f'; i++) {
- hex.set(i);
- }
- for (int i = 'A'; i <= 'F'; i++) {
- hex.set(i);
- }
- }
-
- /**
- * BitSet for escaped.
- *
- * <blockquote>
- *
- * <pre>
- * escaped = "%" hex hex
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet escaped = new BitSet(256);
- // Static initializer for escaped
- static {
- escaped.or(percent);
- escaped.or(hex);
- }
-
- /**
- * BitSet for mark.
- *
- * <blockquote>
- *
- * <pre>
- * mark = "-" | "_" | "." | "!" | "˜" | "*" | "'" | "(" | ")"
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet mark = new BitSet(256);
- // Static initializer for mark
- static {
- mark.set('-');
- mark.set('_');
- mark.set('.');
- mark.set('!');
- mark.set('~');
- mark.set('*');
- mark.set('\'');
- mark.set('(');
- mark.set(')');
- }
-
- /**
- * Data characters that are allowed in a URI but do not have a reserved
- * purpose are called unreserved.
- *
- * <blockquote>
- *
- * <pre>
- * unreserved = alphanum | mark
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet unreserved = new BitSet(256);
- // Static initializer for unreserved
- static {
- unreserved.or(alphanum);
- unreserved.or(mark);
- }
-
- /**
- * BitSet for reserved.
- *
- * <blockquote>
- *
- * <pre>
- * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet reserved = new BitSet(256);
- // Static initializer for reserved
- static {
- reserved.set(';');
- reserved.set('/');
- reserved.set('?');
- reserved.set(':');
- reserved.set('@');
- reserved.set('&');
- reserved.set('=');
- reserved.set('+');
- reserved.set('$');
- reserved.set(',');
- }
-
- /**
- * BitSet for uric.
- *
- * <blockquote>
- *
- * <pre>
- * uric = reserved | unreserved | escaped
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet uric = new BitSet(256);
- // Static initializer for uric
- static {
- uric.or(reserved);
- uric.or(unreserved);
- uric.or(escaped);
- }
-
- /**
- * BitSet for fragment (alias for uric).
- *
- * <blockquote>
- *
- * <pre>
- * fragment = *uric
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet fragment = uric;
-
- /**
- * BitSet for query (alias for uric).
- *
- * <blockquote>
- *
- * <pre>
- * query = *uric
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet query = uric;
-
- /**
- * BitSet for pchar.
- *
- * <blockquote>
- *
- * <pre>
- * pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | ","
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet pchar = new BitSet(256);
- // Static initializer for pchar
- static {
- pchar.or(unreserved);
- pchar.or(escaped);
- pchar.set(':');
- pchar.set('@');
- pchar.set('&');
- pchar.set('=');
- pchar.set('+');
- pchar.set('$');
- pchar.set(',');
- }
-
- /**
- * BitSet for param (alias for pchar).
- *
- * <blockquote>
- *
- * <pre>
- * param = *pchar
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet param = pchar;
-
- /**
- * BitSet for segment.
- *
- * <blockquote>
- *
- * <pre>
- * segment = *pchar *( ";" param )
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet segment = new BitSet(256);
- // Static initializer for segment
- static {
- segment.or(pchar);
- segment.set(';');
- segment.or(param);
- }
-
- /**
- * BitSet for path segments.
- *
- * <blockquote>
- *
- * <pre>
- * path_segments = segment *( "/" segment )
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet path_segments = new BitSet(256);
- // Static initializer for path_segments
- static {
- path_segments.set('/');
- path_segments.or(segment);
- }
-
- /**
- * URI absolute path.
- *
- * <blockquote>
- *
- * <pre>
- * abs_path = "/" path_segments
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet abs_path = new BitSet(256);
- // Static initializer for abs_path
- static {
- abs_path.set('/');
- abs_path.or(path_segments);
- }
-
- /**
- * URI bitset for encoding typical non-slash characters.
- *
- * <blockquote>
- *
- * <pre>
- * uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | "&" | "=" | "+"
- * | "$" | ","
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet uric_no_slash = new BitSet(256);
- // Static initializer for uric_no_slash
- static {
- uric_no_slash.or(unreserved);
- uric_no_slash.or(escaped);
- uric_no_slash.set(';');
- uric_no_slash.set('?');
- uric_no_slash.set(';');
- uric_no_slash.set('@');
- uric_no_slash.set('&');
- uric_no_slash.set('=');
- uric_no_slash.set('+');
- uric_no_slash.set('$');
- uric_no_slash.set(',');
- }
-
- /**
- * URI bitset that combines uric_no_slash and uric.
- *
- * <blockquote>
- *
- * <pre>
- * opaque_part = uric_no_slash * uric
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet opaque_part = new BitSet(256);
- // Static initializer for opaque_part
- static {
- // it's generous. because first character must not include a slash
- opaque_part.or(uric_no_slash);
- opaque_part.or(uric);
- }
-
- /**
- * URI bitset that combines absolute path and opaque part.
- *
- * <blockquote>
- *
- * <pre>
- * path = [ abs_path | opaque_part ]
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet path = new BitSet(256);
- // Static initializer for path
- static {
- path.or(abs_path);
- path.or(opaque_part);
- }
-
- /**
- * Port, a logical alias for digit.
- */
- protected static final BitSet port = digit;
-
- /**
- * Bitset that combines digit and dot fo IPv$address.
- *
- * <blockquote>
- *
- * <pre>
- * IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet IPv4address = new BitSet(256);
- // Static initializer for IPv4address
- static {
- IPv4address.or(digit);
- IPv4address.set('.');
- }
-
- /**
- * RFC 2373.
- *
- * <blockquote>
- *
- * <pre>
- * IPv6address = hexpart [ ":" IPv4address ]
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet IPv6address = new BitSet(256);
- // Static initializer for IPv6address reference
- static {
- IPv6address.or(hex); // hexpart
- IPv6address.set(':');
- IPv6address.or(IPv4address);
- }
-
- /**
- * RFC 2732, 2373.
- *
- * <blockquote>
- *
- * <pre>
- * IPv6reference = "[" IPv6address "]"
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet IPv6reference = new BitSet(256);
- // Static initializer for IPv6reference
- static {
- IPv6reference.set('[');
- IPv6reference.or(IPv6address);
- IPv6reference.set(']');
- }
-
- /**
- * BitSet for toplabel.
- *
- * <blockquote>
- *
- * <pre>
- * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet toplabel = new BitSet(256);
- // Static initializer for toplabel
- static {
- toplabel.or(alphanum);
- toplabel.set('-');
- }
-
- /**
- * BitSet for domainlabel.
- *
- * <blockquote>
- *
- * <pre>
- * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet domainlabel = toplabel;
-
- /**
- * BitSet for hostname.
- *
- * <blockquote>
- *
- * <pre>
- * hostname = *( domainlabel "." ) toplabel [ "." ]
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet hostname = new BitSet(256);
- // Static initializer for hostname
- static {
- hostname.or(toplabel);
- // hostname.or(domainlabel);
- hostname.set('.');
- }
-
- /**
- * BitSet for host.
- *
- * <blockquote>
- *
- * <pre>
- * host = hostname | IPv4address | IPv6reference
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet host = new BitSet(256);
- // Static initializer for host
- static {
- host.or(hostname);
- // host.or(IPv4address);
- host.or(IPv6reference); // IPv4address
- }
-
- /**
- * BitSet for hostport.
- *
- * <blockquote>
- *
- * <pre>
- * hostport = host [ ":" port ]
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet hostport = new BitSet(256);
- // Static initializer for hostport
- static {
- hostport.or(host);
- hostport.set(':');
- hostport.or(port);
- }
-
- /**
- * Bitset for userinfo.
- *
- * <blockquote>
- *
- * <pre>
- * userinfo = *( unreserved | escaped |
- * ";" | ":" | "&" | "=" | "+" | "$" | "," )
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet userinfo = new BitSet(256);
- // Static initializer for userinfo
- static {
- userinfo.or(unreserved);
- userinfo.or(escaped);
- userinfo.set(';');
- userinfo.set(':');
- userinfo.set('&');
- userinfo.set('=');
- userinfo.set('+');
- userinfo.set('$');
- userinfo.set(',');
- }
-
- /**
- * BitSet for within the userinfo component like user and password.
- */
- public static final BitSet within_userinfo = new BitSet(256);
- // Static initializer for within_userinfo
- static {
- within_userinfo.or(userinfo);
- within_userinfo.clear(';'); // reserved within authority
- within_userinfo.clear(':');
- within_userinfo.clear('@');
- within_userinfo.clear('?');
- within_userinfo.clear('/');
- }
-
- /**
- * Bitset for server.
- *
- * <blockquote>
- *
- * <pre>
- * server = [ [ userinfo "@" ] hostport ]
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet server = new BitSet(256);
- // Static initializer for server
- static {
- server.or(userinfo);
- server.set('@');
- server.or(hostport);
- }
-
- /**
- * BitSet for reg_name.
- *
- * <blockquote>
- *
- * <pre>
- * reg_name = 1 * (unreserved | escaped | "$" | "," | ";" | ":" | "@" | "&" | "=" | "+")
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet reg_name = new BitSet(256);
- // Static initializer for reg_name
- static {
- reg_name.or(unreserved);
- reg_name.or(escaped);
- reg_name.set('$');
- reg_name.set(',');
- reg_name.set(';');
- reg_name.set(':');
- reg_name.set('@');
- reg_name.set('&');
- reg_name.set('=');
- reg_name.set('+');
- }
-
- /**
- * BitSet for authority.
- *
- * <blockquote>
- *
- * <pre>
- * authority = server | reg_name
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet authority = new BitSet(256);
- // Static initializer for authority
- static {
- authority.or(server);
- authority.or(reg_name);
- }
-
- /**
- * BitSet for scheme.
- *
- * <blockquote>
- *
- * <pre>
- * scheme = alpha * (alpha | digit | "+" | "-" | ".")
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet scheme = new BitSet(256);
- // Static initializer for scheme
- static {
- scheme.or(alpha);
- scheme.or(digit);
- scheme.set('+');
- scheme.set('-');
- scheme.set('.');
- }
-
- /**
- * BitSet for rel_segment.
- *
- * <blockquote>
- *
- * <pre>
- * rel_segment = 1 * (unreserved | escaped | ";" | "@" | "&" | "=" | "+" | "$" | ",")
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet rel_segment = new BitSet(256);
- // Static initializer for rel_segment
- static {
- rel_segment.or(unreserved);
- rel_segment.or(escaped);
- rel_segment.set(';');
- rel_segment.set('@');
- rel_segment.set('&');
- rel_segment.set('=');
- rel_segment.set('+');
- rel_segment.set('$');
- rel_segment.set(',');
- }
-
- /**
- * BitSet for rel_path.
- *
- * <blockquote>
- *
- * <pre>
- * rel_path = rel_segment[abs_path]
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet rel_path = new BitSet(256);
- // Static initializer for rel_path
- static {
- rel_path.or(rel_segment);
- rel_path.or(abs_path);
- }
-
- /**
- * BitSet for net_path.
- *
- * <blockquote>
- *
- * <pre>
- * net_path = "//" authority [ abs_path ]
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet net_path = new BitSet(256);
- // Static initializer for net_path
- static {
- net_path.set('/');
- net_path.or(authority);
- net_path.or(abs_path);
- }
-
- /**
- * BitSet for hier_part.
- *
- * <blockquote>
- *
- * <pre>
- * hier_part = ( net_path | abs_path ) [ "?" query ]
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet hier_part = new BitSet(256);
- // Static initializer for hier_part
- static {
- hier_part.or(net_path);
- hier_part.or(abs_path);
- // hier_part.set('?'); aleady included
- hier_part.or(query);
- }
-
- /**
- * BitSet for relativeURI.
- *
- * <blockquote>
- *
- * <pre>
- * relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet relativeURI = new BitSet(256);
- // Static initializer for relativeURI
- static {
- relativeURI.or(net_path);
- relativeURI.or(abs_path);
- relativeURI.or(rel_path);
- // relativeURI.set('?'); aleady included
- relativeURI.or(query);
- }
-
- /**
- * BitSet for absoluteURI.
- *
- * <blockquote>
- *
- * <pre>
- * absoluteURI = scheme ":" ( hier_part | opaque_part )
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet absoluteURI = new BitSet(256);
- // Static initializer for absoluteURI
- static {
- absoluteURI.or(scheme);
- absoluteURI.set(':');
- absoluteURI.or(hier_part);
- absoluteURI.or(opaque_part);
- }
-
- /**
- * BitSet for URI-reference.
- *
- * <blockquote>
- *
- * <pre>
- * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
- * </pre>
- *
- * </blockquote>
- *
- */
- protected static final BitSet URI_reference = new BitSet(256);
- // Static initializer for URI_reference
- static {
- URI_reference.or(absoluteURI);
- URI_reference.or(relativeURI);
- URI_reference.set('#');
- URI_reference.or(fragment);
- }
-
- // ---------------------------- Characters disallowed within the URI syntax
- // Excluded US-ASCII Characters are like control, space, delims and unwise
-
- /**
- * BitSet for control.
- */
- public static final BitSet control = new BitSet(256);
- // Static initializer for control
- static {
- for (int i = 0; i <= 0x1F; i++) {
- control.set(i);
- }
- control.set(0x7F);
- }
-
- /**
- * BitSet for space.
- */
- public static final BitSet space = new BitSet(256);
- // Static initializer for space
- static {
- space.set(0x20);
- }
-
- /**
- * BitSet for delims.
- */
- public static final BitSet delims = new BitSet(256);
- // Static initializer for delims
- static {
- delims.set('<');
- delims.set('>');
- delims.set('#');
- delims.set('%');
- delims.set('"');
- }
-
- /**
- * BitSet for unwise.
- */
- public static final BitSet unwise = new BitSet(256);
- // Static initializer for unwise
- static {
- unwise.set('{');
- unwise.set('}');
- unwise.set('|');
- unwise.set('\\');
- unwise.set('^');
- unwise.set('[');
- unwise.set(']');
- unwise.set('`');
- }
-
- /**
- * Disallowed rel_path before escaping.
- */
- public static final BitSet disallowed_rel_path = new BitSet(256);
- // Static initializer for disallowed_rel_path
- static {
- disallowed_rel_path.or(uric);
- disallowed_rel_path.andNot(rel_path);
- }
-
- /**
- * Disallowed opaque_part before escaping.
- */
- public static final BitSet disallowed_opaque_part = new BitSet(256);
- // Static initializer for disallowed_opaque_part
- static {
- disallowed_opaque_part.or(uric);
- disallowed_opaque_part.andNot(opaque_part);
- }
-
- // ----------------------- Characters allowed within and for each component
-
- /**
- * Those characters that are allowed for the authority component.
- */
- public static final BitSet allowed_authority = new BitSet(256);
- // Static initializer for allowed_authority
- static {
- allowed_authority.or(authority);
- allowed_authority.clear('%');
- }
-
- /**
- * Those characters that are allowed for the opaque_part.
- */
- public static final BitSet allowed_opaque_part = new BitSet(256);
- // Static initializer for allowed_opaque_part
- static {
- allowed_opaque_part.or(opaque_part);
- allowed_opaque_part.clear('%');
- }
-
- /**
- * Those characters that are allowed for the reg_name.
- */
- public static final BitSet allowed_reg_name = new BitSet(256);
- // Static initializer for allowed_reg_name
- static {
- allowed_reg_name.or(reg_name);
- // allowed_reg_name.andNot(percent);
- allowed_reg_name.clear('%');
- }
-
- /**
- * Those characters that are allowed for the userinfo component.
- */
- public static final BitSet allowed_userinfo = new BitSet(256);
- // Static initializer for allowed_userinfo
- static {
- allowed_userinfo.or(userinfo);
- // allowed_userinfo.andNot(percent);
- allowed_userinfo.clear('%');
- }
-
- /**
- * Those characters that are allowed for within the userinfo component.
- */
- public static final BitSet allowed_within_userinfo = new BitSet(256);
- // Static initializer for allowed_within_userinfo
- static {
- allowed_within_userinfo.or(within_userinfo);
- allowed_within_userinfo.clear('%');
- }
-
- /**
- * Those characters that are allowed for the IPv6reference component. The
- * characters '[', ']' in IPv6reference should be excluded.
- */
- public static final BitSet allowed_IPv6reference = new BitSet(256);
- // Static initializer for allowed_IPv6reference
- static {
- allowed_IPv6reference.or(IPv6reference);
- // allowed_IPv6reference.andNot(unwise);
- allowed_IPv6reference.clear('[');
- allowed_IPv6reference.clear(']');
- }
-
- /**
- * Those characters that are allowed for the host component. The characters
- * '[', ']' in IPv6reference should be excluded.
- */
- public static final BitSet allowed_host = new BitSet(256);
- // Static initializer for allowed_host
- static {
- allowed_host.or(hostname);
- allowed_host.or(allowed_IPv6reference);
- }
-
- /**
- * Those characters that are allowed for the authority component.
- */
- public static final BitSet allowed_within_authority = new BitSet(256);
- // Static initializer for allowed_within_authority
- static {
- allowed_within_authority.or(server);
- allowed_within_authority.or(reg_name);
- allowed_within_authority.clear(';');
- allowed_within_authority.clear(':');
- allowed_within_authority.clear('@');
- allowed_within_authority.clear('?');
- allowed_within_authority.clear('/');
- }
-
- /**
- * Those characters that are allowed for the abs_path.
- */
- public static final BitSet allowed_abs_path = new BitSet(256);
- // Static initializer for allowed_abs_path
- static {
- allowed_abs_path.or(abs_path);
- // allowed_abs_path.set('/'); // aleady included
- allowed_abs_path.andNot(percent);
- allowed_abs_path.clear('+');
- }
-
- /**
- * Those characters that are allowed for the rel_path.
- */
- public static final BitSet allowed_rel_path = new BitSet(256);
- // Static initializer for allowed_rel_path
- static {
- allowed_rel_path.or(rel_path);
- allowed_rel_path.clear('%');
- allowed_rel_path.clear('+');
- }
-
- /**
- * Those characters that are allowed within the path.
- */
- public static final BitSet allowed_within_path = new BitSet(256);
- // Static initializer for allowed_within_path
- static {
- allowed_within_path.or(abs_path);
- allowed_within_path.clear('/');
- allowed_within_path.clear(';');
- allowed_within_path.clear('=');
- allowed_within_path.clear('?');
- }
-
- /**
- * Those characters that are allowed for the query component.
- */
- public static final BitSet allowed_query = new BitSet(256);
- // Static initializer for allowed_query
- static {
- allowed_query.or(uric);
- allowed_query.clear('%');
- }
-
- /**
- * Those characters that are allowed within the query component.
- */
- public static final BitSet allowed_within_query = new BitSet(256);
- // Static initializer for allowed_within_query
- static {
- allowed_within_query.or(allowed_query);
- allowed_within_query.andNot(reserved); // excluded 'reserved'
- }
-
- /**
- * Those characters that are allowed for the fragment component.
- */
- public static final BitSet allowed_fragment = new BitSet(256);
- // Static initializer for allowed_fragment
- static {
- allowed_fragment.or(uric);
- allowed_fragment.clear('%');
- }
-
- // ------------------------------------------- Flags for this URI-reference
-
- // TODO: Figure out what all these variables are for and provide javadoc
-
- // URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
- // absoluteURI = scheme ":" ( hier_part | opaque_part )
- protected boolean _is_hier_part;
-
- protected boolean _is_opaque_part;
-
- // relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
- // hier_part = ( net_path | abs_path ) [ "?" query ]
- protected boolean _is_net_path;
-
- protected boolean _is_abs_path;
-
- protected boolean _is_rel_path;
-
- // net_path = "//" authority [ abs_path ]
- // authority = server | reg_name
- protected boolean _is_reg_name;
-
- protected boolean _is_server; // = _has_server
-
- // server = [ [ userinfo "@" ] hostport ]
- // host = hostname | IPv4address | IPv6reference
- protected boolean _is_hostname;
-
- protected boolean _is_IPv4address;
-
- protected boolean _is_IPv6reference;
-
- // ------------------------------------------ Character and escape encoding
-
- /**
- * Encodes URI string. This is a two mapping, one from original characters
- * to octets, and subsequently a second from octets to URI characters:
- *
- * <blockquote>
- *
- * <pre>
- * original character sequence->octet sequence->URI character sequence
- * </pre>
- *
- * </blockquote>
- *
- * An escaped octet is encoded as a character triplet, consisting of the
- * percent character "%" followed by the two hexadecimal digits representing
- * the octet code. For example, "%20" is the escaped encoding for the
- * US-ASCII space character.
- *
- * Conversion from the local filesystem character set to UTF-8 will normally
- * involve a two step process. First convert the local character set to the
- * UCS; then convert the UCS to UTF-8. The first step in the process can be
- * performed by maintaining a mapping table that includes the local
- * character set code and the corresponding UCS code. The next step is to
- * convert the UCS character code to the UTF-8 encoding.
- *
- * Mapping between vendor codepages can be done in a very similar manner as
- * described above.
- *
- * The only time escape encodings can allowedly be made is when a URI is
- * being created from its component parts. The escape and validate methods
- * are internally performed within this method.
- *
- * @param original the original character sequence
- * @param allowed those characters that are allowed within a component
- * @param charset the protocol charset
- * @return URI character sequence
- * @throws URIException null component or unsupported character encoding
- */
-
- protected static char[] encode(String original, BitSet allowed,
- String charset) throws URIException {
- if (original == null) {
- throw new IllegalArgumentException(
- "Original string may not be null");
- }
- if (allowed == null) {
- throw new IllegalArgumentException("Allowed bitset may not be null");
- }
- byte[] rawdata = encodeUrl(allowed, getBytes(original, charset));
- return getAsciiString(rawdata).toCharArray();
- }
-
- /**
- * Decodes URI encoded string. This is a two mapping, one from URI
- * characters to octets, and subsequently a second from octets to original
- * characters:
- *
- * <blockquote>
- *
- * <pre>
- * URI character sequence->octet sequence->original character sequence
- * </pre>
- *
- * </blockquote>
- *
- * A URI must be separated into its components before the escaped characters
- * within those components can be allowedly decoded.
- *
- * Notice that there is a chance that URI characters that are non UTF-8 may
- * be parsed as valid UTF-8. A recent non-scientific analysis found that EUC
- * encoded Japanese words had a 2.7% false reading; SJIS had a 0.0005% false
- * reading; other encoding such as ASCII or KOI-8 have a 0% false reading.
- *
- * The percent "%" character always has the reserved purpose of being the
- * escape indicator, it must be escaped as "%25" in order to be used as data
- * within a URI.
- *
- * The unescape method is internally performed within this method.
- *
- * @param component the URI character sequence
- * @param charset the protocol charset
- * @return original character sequence
- * @throws URIException incomplete trailing escape pattern or unsupported
- * character encoding
- */
- protected static String decode(char[] component, String charset)
- throws URIException {
- if (component == null) {
- throw new IllegalArgumentException(
- "Component array of chars may not be null");
- }
- return decode(new String(component), charset);
- }
-
- /**
- * Decodes URI encoded string. This is a two mapping, one from URI
- * characters to octets, and subsequently a second from octets to original
- * characters:
- *
- * <blockquote>
- *
- * <pre>
- * URI character sequence->octet sequence->original character sequence
- * </pre>
- *
- * </blockquote>
- *
- * A URI must be separated into its components before the escaped characters
- * within those components can be allowedly decoded.
- *
- * Notice that there is a chance that URI characters that are non UTF-8 may
- * be parsed as valid UTF-8. A recent non-scientific analysis found that EUC
- * encoded Japanese words had a 2.7% false reading; SJIS had a 0.0005% false
- * reading; other encoding such as ASCII or KOI-8 have a 0% false reading.
- *
- * The percent "%" character always has the reserved purpose of being the
- * escape indicator, it must be escaped as "%25" in order to be used as data
- * within a URI.
- *
- * The unescape method is internally performed within this method.
- *
- * @param component the URI character sequence
- * @param charset the protocol charset
- * @return original character sequence
- * @throws URIException incomplete trailing escape pattern or unsupported
- * character encoding
- * @since 3.0
- */
- protected static String decode(String component, String charset)
- throws URIException {
- if (component == null) {
- throw new IllegalArgumentException(
- "Component array of chars may not be null");
- }
- byte[] rawdata = decodeUrl(getAsciiBytes(component));
- return getString(rawdata, charset);
- }
-
- /**
- * Pre-validate the unescaped URI string within a specific component.
- *
- * @param component the component string within the component
- * @param disallowed those characters disallowed within the component
- * @return if true, it doesn't have the disallowed characters if false, the
- * component is undefined or an incorrect one
- */
- protected boolean prevalidate(String component, BitSet disallowed) {
- // prevalidate the given component by disallowed characters
- if (component == null) {
- return false; // undefined
- }
- char[] target = component.toCharArray();
- for (int i = 0; i < target.length; i++) {
- if (disallowed.get(target[i])) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Validate the URI characters within a specific component. The component
- * must be performed after escape encoding. Or it doesn't include escaped
- * characters.
- *
- * @param component the characters sequence within the component
- * @param generous those characters that are allowed within a component
- * @return if true, it's the correct URI character sequence
- */
- protected boolean validate(char[] component, BitSet generous) {
- // validate each component by generous characters
- return validate(component, 0, -1, generous);
- }
-
- /**
- * Validate the URI characters within a specific component. The component
- * must be performed after escape encoding. Or it doesn't include escaped
- * characters.
- *
- * It's not that much strict, generous. The strict validation might be
- * performed before being called this method.
- *
- * @param component the characters sequence within the component
- * @param soffset the starting offset of the given component
- * @param eoffset the ending offset of the given component if -1, it means
- * the length of the component
- * @param generous those characters that are allowed within a component
- * @return if true, it's the correct URI character sequence
- */
- protected boolean validate(char[] component, int soffset, int eoffset,
- BitSet generous) {
- // validate each component by generous characters
- if (eoffset == -1) {
- eoffset = component.length - 1;
- }
- for (int i = soffset; i <= eoffset; i++) {
- if (!generous.get(component[i])) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * In order to avoid any possilbity of conflict with non-ASCII characters,
- * Parse a URI reference as a <code>String</code> with the character
- * encoding of the local system or the document.
- *
- * The following line is the regular expression for breaking-down a URI
- * reference into its components.
- *
- * <blockquote>
- *
- * <pre>
- * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- * 12 3 4 5 6 7 8 9
- * </pre>
- *
- * </blockquote>
- *
- * For example, matching the above expression to
- * http://jakarta.apache.org/ietf/uri/#Related results in the following
- * subexpression matches:
- *
- * <blockquote>
- *
- * <pre>
- * $1 = http:
- * scheme = $2 = http
- * $3 = //jakarta.apache.org
- * authority = $4 = jakarta.apache.org
- * path = $5 = /ietf/uri/
- * $6 = <undefined>
- * query = $7 = <undefined>
- * $8 = #Related
- * fragment = $9 = Related
- * </pre>
- *
- * </blockquote>
- *
- *
- * @param original the original character sequence
- * @param escaped <code>true</code> if <code>original</code> is escaped
- * @throws URIException If an error occurs.
- */
- protected void parseUriReference(String original, boolean escaped)
- throws URIException {
-
- // validate and contruct the URI character sequence
- if (original == null) {
- throw new URIException("URI-Reference required");
- }
-
- /*
- * @ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- */
- String tmp = original.trim();
-
- /*
- * The length of the string sequence of characters. It may not be equal
- * to the length of the byte array.
- */
- int length = tmp.length();
-
- /*
- * Remove the delimiters like angle brackets around an URI.
- */
- if (length > 0) {
- char[] firstDelimiter = { tmp.charAt(0) };
- if (validate(firstDelimiter, delims)) {
- if (length >= 2) {
- char[] lastDelimiter = { tmp.charAt(length - 1) };
- if (validate(lastDelimiter, delims)) {
- tmp = tmp.substring(1, length - 1);
- length = length - 2;
- }
- }
- }
- }
-
- /*
- * The starting index
- */
- int from = 0;
-
- /*
- * The test flag whether the URI is started from the path component.
- */
- boolean isStartedFromPath = false;
- int atColon = tmp.indexOf(':');
- int atSlash = tmp.indexOf('/');
- if ((atColon <= 0 && !tmp.startsWith("//"))
- || (atSlash >= 0 && atSlash < atColon)) {
- isStartedFromPath = true;
- }
-
- /*
- * <blockquote><pre>
- * @@@@@@@@ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- * </pre></blockquote>
- */
- int at = indexFirstOf(tmp, isStartedFromPath ? "/?#" : ":/?#", from);
- if (at == -1) {
- at = 0;
- }
-
- /*
- * Parse the scheme. <blockquote><pre> scheme = $2 = http
- * @ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- * </pre></blockquote>
- */
- if (at > 0 && at < length && tmp.charAt(at) == ':') {
- char[] target = tmp.substring(0, at).toLowerCase().toCharArray();
- if (validate(target, scheme)) {
- _scheme = target;
- } else {
- throw new URIException("incorrect scheme");
- }
- from = ++at;
- }
-
- /*
- * Parse the authority component. <blockquote><pre> authority = $4 =
- * jakarta.apache.org
- * @@ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- * </pre></blockquote>
- */
- // Reset flags
- _is_net_path = _is_abs_path = _is_rel_path = _is_hier_part = false;
- if (0 <= at && at < length && tmp.charAt(at) == '/') {
- // Set flag
- _is_hier_part = true;
- if (at + 2 < length && tmp.charAt(at + 1) == '/'
- && !isStartedFromPath) {
- // the temporary index to start the search from
- int next = indexFirstOf(tmp, "/?#", at + 2);
- if (next == -1) {
- next = (tmp.substring(at + 2).length() == 0)
- ? at + 2
- : tmp.length();
- }
- parseAuthority(tmp.substring(at + 2, next), escaped);
- from = at = next;
- // Set flag
- _is_net_path = true;
- }
- if (from == at) {
- // Set flag
- _is_abs_path = true;
- }
- }
-
- /*
- * Parse the path component. <blockquote><pre> path = $5 = /ietf/uri/
- * @@@@@@ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- * </pre></blockquote>
- */
- if (from < length) {
- // rel_path = rel_segment [ abs_path ]
- int next = indexFirstOf(tmp, "?#", from);
- if (next == -1) {
- next = tmp.length();
- }
- if (!_is_abs_path) {
- if (!escaped
- && prevalidate(tmp.substring(from, next),
- disallowed_rel_path)
- || escaped
- && validate(tmp.substring(from, next).toCharArray(),
- rel_path)) {
- // Set flag
- _is_rel_path = true;
- } else if (!escaped
- && prevalidate(tmp.substring(from, next),
- disallowed_opaque_part)
- || escaped
- && validate(tmp.substring(from, next).toCharArray(),
- opaque_part)) {
- // Set flag
- _is_opaque_part = true;
- } else {
- // the path component may be empty
- _path = null;
- }
- }
- String s = tmp.substring(from, next);
- if (escaped) {
- setRawPath(s.toCharArray());
- } else {
- setPath(s);
- }
- at = next;
- }
-
- // set the charset to do escape encoding
- String charset = getProtocolCharset();
-
- /*
- * Parse the query component. <blockquote><pre> query = $7 =
- * <undefined>
- * @@@@@@@@@ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- * </pre></blockquote>
- */
- if (0 <= at && at + 1 < length && tmp.charAt(at) == '?') {
- int next = tmp.indexOf('#', at + 1);
- if (next == -1) {
- next = tmp.length();
- }
- if (escaped) {
- _query = tmp.substring(at + 1, next).toCharArray();
- if (!validate(_query, uric)) {
- throw new URIException("Invalid query");
- }
- } else {
- _query = encode(tmp.substring(at + 1, next), allowed_query,
- charset);
- }
- at = next;
- }
-
- /*
- * Parse the fragment component. <blockquote><pre> fragment = $9 =
- * Related
- * @@@@@@@@ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- * </pre></blockquote>
- */
- if (0 <= at && at + 1 <= length && tmp.charAt(at) == '#') {
- if (at + 1 == length) { // empty fragment
- _fragment = "".toCharArray();
- } else {
- _fragment = (escaped)
- ? tmp.substring(at + 1).toCharArray()
- : encode(tmp.substring(at + 1), allowed_fragment,
- charset);
- }
- }
-
- // set this URI.
- setURI();
- }
-
- /**
- * Get the earlier index that to be searched for the first occurrance in one
- * of any of the given string.
- *
- * @param s the string to be indexed
- * @param delims the delimiters used to index
- * @return the earlier index if there are delimiters
- */
- protected int indexFirstOf(String s, String delims) {
- return indexFirstOf(s, delims, -1);
- }
-
- /**
- * Get the earlier index that to be searched for the first occurrance in one
- * of any of the given string.
- *
- * @param s the string to be indexed
- * @param delims the delimiters used to index
- * @param offset the from index
- * @return the earlier index if there are delimiters
- */
- protected int indexFirstOf(String s, String delims, int offset) {
- if (s == null || s.length() == 0) {
- return -1;
- }
- if (delims == null || delims.length() == 0) {
- return -1;
- }
- // check boundaries
- if (offset < 0) {
- offset = 0;
- } else if (offset > s.length()) {
- return -1;
- }
- // s is never null
- int min = s.length();
- char[] delim = delims.toCharArray();
- for (int i = 0; i < delim.length; i++) {
- int at = s.indexOf(delim[i], offset);
- if (at >= 0 && at < min) {
- min = at;
- }
- }
- return (min == s.length()) ? -1 : min;
- }
-
- /**
- * Get the earlier index that to be searched for the first occurrance in one
- * of any of the given array.
- *
- * @param s the character array to be indexed
- * @param delim the delimiter used to index
- * @return the ealier index if there are a delimiter
- */
- protected int indexFirstOf(char[] s, char delim) {
- return indexFirstOf(s, delim, 0);
- }
-
- /**
- * Get the earlier index that to be searched for the first occurrance in one
- * of any of the given array.
- *
- * @param s the character array to be indexed
- * @param delim the delimiter used to index
- * @param offset The offset.
- * @return the ealier index if there is a delimiter
- */
- protected int indexFirstOf(char[] s, char delim, int offset) {
- if (s == null || s.length == 0) {
- return -1;
- }
- // check boundaries
- if (offset < 0) {
- offset = 0;
- } else if (offset > s.length) {
- return -1;
- }
- for (int i = offset; i < s.length; i++) {
- if (s[i] == delim) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Parse the authority component.
- *
- * @param original the original character sequence of authority component
- * @param escaped <code>true</code> if <code>original</code> is escaped
- * @throws URIException If an error occurs.
- */
- protected void parseAuthority(String original, boolean escaped)
- throws URIException {
-
- // Reset flags
- _is_reg_name = _is_server = _is_hostname = _is_IPv4address = _is_IPv6reference = false;
-
- // set the charset to do escape encoding
- String charset = getProtocolCharset();
-
- boolean hasPort = true;
- int from = 0;
- int next = original.indexOf('@');
- if (next != -1) { // neither -1 and 0
- // each protocol extented from URI supports the specific userinfo
- _userinfo = (escaped)
- ? original.substring(0, next).toCharArray()
- : encode(original.substring(0, next), allowed_userinfo,
- charset);
- from = next + 1;
- }
- next = original.indexOf('[', from);
- if (next >= from) {
- next = original.indexOf(']', from);
- if (next == -1) {
- throw new URIException(URIException.PARSING, "IPv6reference");
- }
- next++;
- // In IPv6reference, '[', ']' should be excluded
- _host = (escaped)
- ? original.substring(from, next).toCharArray()
- : encode(original.substring(from, next),
- allowed_IPv6reference, charset);
- // Set flag
- _is_IPv6reference = true;
- } else { // only for !_is_IPv6reference
- next = original.indexOf(':', from);
- if (next == -1) {
- next = original.length();
- hasPort = false;
- }
- // REMINDME: it doesn't need the pre-validation
- _host = original.substring(from, next).toCharArray();
- if (validate(_host, IPv4address)) {
- // Set flag
- _is_IPv4address = true;
- } else if (validate(_host, hostname)) {
- // Set flag
- _is_hostname = true;
- } else {
- // Set flag
- _is_reg_name = true;
- }
- }
- if (_is_reg_name) {
- // Reset flags for a server-based naming authority
- _is_server = _is_hostname = _is_IPv4address = _is_IPv6reference = false;
- // set a registry-based naming authority
- if (escaped) {
- _authority = original.toCharArray();
- if (!validate(_authority, reg_name)) {
- throw new URIException("Invalid authority");
- }
- } else {
- _authority = encode(original, allowed_reg_name, charset);
- }
- } else {
- if (original.length() - 1 > next && hasPort
- && original.charAt(next) == ':') { // not empty
- from = next + 1;
- try {
- _port = Integer.parseInt(original.substring(from));
- } catch (NumberFormatException error) {
- throw new URIException(URIException.PARSING,
- "invalid port number");
- }
- }
- // set a server-based naming authority
- StringBuilder buf = new StringBuilder();
- if (_userinfo != null) { // has_userinfo
- buf.append(_userinfo);
- buf.append('@');
- }
- if (_host != null) {
- buf.append(_host);
- if (_port != -1) {
- buf.append(':');
- buf.append(_port);
- }
- }
- _authority = buf.toString().toCharArray();
- // Set flag
- _is_server = true;
- }
- }
-
- /**
- * Once it's parsed successfully, set this URI.
- *
- * @see #getRawURI
- */
- protected void setURI() {
- // set _uri
- StringBuilder buf = new StringBuilder();
- // ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- if (_scheme != null) {
- buf.append(_scheme);
- buf.append(':');
- }
- if (_is_net_path) {
- buf.append("//");
- if (_authority != null) { // has_authority
- buf.append(_authority);
- }
- }
- if (_opaque != null && _is_opaque_part) {
- buf.append(_opaque);
- } else if (_path != null) {
- // _is_hier_part or _is_relativeURI
- if (_path.length != 0) {
- buf.append(_path);
- }
- }
- if (_query != null) { // has_query
- buf.append('?');
- buf.append(_query);
- }
- // ignore the fragment identifier
- _uri = buf.toString().toCharArray();
- hash = 0;
- }
-
- // ----------------------------------------------------------- Test methods
-
- /**
- * Tell whether or not this URI is absolute.
- *
- * @return true iif this URI is absoluteURI
- */
- public boolean isAbsoluteURI() {
- return (_scheme != null);
- }
-
- /**
- * Tell whether or not this URI is relative.
- *
- * @return true iif this URI is relativeURI
- */
- public boolean isRelativeURI() {
- return (_scheme == null);
- }
-
- /**
- * Tell whether or not the absoluteURI of this URI is hier_part.
- *
- * @return true iif the absoluteURI is hier_part
- */
- public boolean isHierPart() {
- return _is_hier_part;
- }
-
- /**
- * Tell whether or not the absoluteURI of this URI is opaque_part.
- *
- * @return true iif the absoluteURI is opaque_part
- */
- public boolean isOpaquePart() {
- return _is_opaque_part;
- }
-
- /**
- * Tell whether or not the relativeURI or heir_part of this URI is net_path.
- * It's the same function as the has_authority() method.
- *
- * @return true iif the relativeURI or heir_part is net_path
- * @see #hasAuthority
- */
- public boolean isNetPath() {
- return _is_net_path || (_authority != null);
- }
-
- /**
- * Tell whether or not the relativeURI or hier_part of this URI is abs_path.
- *
- * @return true iif the relativeURI or hier_part is abs_path
- */
- public boolean isAbsPath() {
- return _is_abs_path;
- }
-
- /**
- * Tell whether or not the relativeURI of this URI is rel_path.
- *
- * @return true iif the relativeURI is rel_path
- */
- public boolean isRelPath() {
- return _is_rel_path;
- }
-
- /**
- * Tell whether or not this URI has authority. It's the same function as the
- * is_net_path() method.
- *
- * @return true iif this URI has authority
- * @see #isNetPath
- */
- public boolean hasAuthority() {
- return (_authority != null) || _is_net_path;
- }
-
- /**
- * Tell whether or not the authority component of this URI is reg_name.
- *
- * @return true iif the authority component is reg_name
- */
- public boolean isRegName() {
- return _is_reg_name;
- }
-
- /**
- * Tell whether or not the authority component of this URI is server.
- *
- * @return true iif the authority component is server
- */
- public boolean isServer() {
- return _is_server;
- }
-
- /**
- * Tell whether or not this URI has userinfo.
- *
- * @return true iif this URI has userinfo
- */
- public boolean hasUserinfo() {
- return (_userinfo != null);
- }
-
- /**
- * Tell whether or not the host part of this URI is hostname.
- *
- * @return true iif the host part is hostname
- */
- public boolean isHostname() {
- return _is_hostname;
- }
-
- /**
- * Tell whether or not the host part of this URI is IPv4address.
- *
- * @return true iif the host part is IPv4address
- */
- public boolean isIPv4address() {
- return _is_IPv4address;
- }
-
- /**
- * Tell whether or not the host part of this URI is IPv6reference.
- *
- * @return true iif the host part is IPv6reference
- */
- public boolean isIPv6reference() {
- return _is_IPv6reference;
- }
-
- /**
- * Tell whether or not this URI has query.
- *
- * @return true iif this URI has query
- */
- public boolean hasQuery() {
- return (_query != null);
- }
-
- /**
- * Tell whether or not this URI has fragment.
- *
- * @return true iif this URI has fragment
- */
- public boolean hasFragment() {
- return (_fragment != null);
- }
-
- // ---------------------------------------------------------------- Charset
-
- /**
- * Set the default charset of the protocol.
- *
- * The character set used to store files SHALL remain a local decision and
- * MAY depend on the capability of local operating systems. Prior to the
- * exchange of URIs they SHOULD be converted into a ISO/IEC 10646 format and
- * UTF-8 encoded. This approach, while allowing international exchange of
- * URIs, will still allow backward compatibility with older systems because
- * the code set positions for ASCII characters are identical to the one byte
- * sequence in UTF-8.
- *
- * An individual URI scheme may require a single charset, define a default
- * charset, or provide a way to indicate the charset used.
- *
- * Always all the time, the setter method is always succeeded and throws
- * <code>DefaultCharsetChanged</code> exception. So API programmer must
- * follow the following way: <code><pre>
- * import org.apache.util.URI$DefaultCharsetChanged;
- * .
- * .
- * .
- * try {
- * URI.setDefaultProtocolCharset("UTF-8");
- * } catch (DefaultCharsetChanged cc) {
- * // CASE 1: the exception could be ignored, when it is set by user
- * if (cc.getReasonCode() == DefaultCharsetChanged.PROTOCOL_CHARSET) {
- * // CASE 2: let user know the default protocol charset changed
- * } else {
- * // CASE 2: let user know the default document charset changed
- * }
- * }
- * </pre></code> The API programmer is responsible to set the correct
- * charset. And each application should remember its own charset to support.
- *
- * @param charset the default charset for each protocol
- * @throws DefaultCharsetChanged default charset changed
- */
- public static void setDefaultProtocolCharset(String charset)
- throws DefaultCharsetChanged {
-
- defaultProtocolCharset = charset;
- throw new DefaultCharsetChanged(DefaultCharsetChanged.PROTOCOL_CHARSET,
- "the default protocol charset changed");
- }
-
- /**
- * Get the default charset of the protocol.
- *
- * An individual URI scheme may require a single charset, define a default
- * charset, or provide a way to indicate the charset used.
- *
- * To work globally either requires support of a number of character sets
- * and to be able to convert between them, or the use of a single preferred
- * character set. For support of global compatibility it is STRONGLY
- * RECOMMENDED that clients and servers use UTF-8 encoding when exchanging
- * URIs.
- *
- * @return the default charset string
- */
- public static String getDefaultProtocolCharset() {
- return defaultProtocolCharset;
- }
-
- /**
- * Get the protocol charset used by this current URI instance. It was set by
- * the constructor for this instance. If it was not set by contructor, it
- * will return the default protocol charset.
- *
- * @return the protocol charset string
- * @see #getDefaultProtocolCharset
- */
- public String getProtocolCharset() {
- return (protocolCharset != null)
- ? protocolCharset
- : defaultProtocolCharset;
- }
-
- /**
- * Set the default charset of the document.
- *
- * Notice that it will be possible to contain mixed characters (e.g.
- * ftp://host/KoreanNamespace/ChineseResource). To handle the Bi-directional
- * display of these character sets, the protocol charset could be simply
- * used again. Because it's not yet implemented that the insertion of BIDI
- * control characters at different points during composition is extracted.
- *
- * Always all the time, the setter method is always succeeded and throws
- * <code>DefaultCharsetChanged</code> exception. So API programmer must
- * follow the following way: <code><pre>
- * import org.apache.util.URI$DefaultCharsetChanged;
- * .
- * .
- * .
- * try {
- * URI.setDefaultDocumentCharset("EUC-KR");
- * } catch (DefaultCharsetChanged cc) {
- * // CASE 1: the exception could be ignored, when it is set by user
- * if (cc.getReasonCode() == DefaultCharsetChanged.DOCUMENT_CHARSET) {
- * // CASE 2: let user know the default document charset changed
- * } else {
- * // CASE 2: let user know the default protocol charset changed
- * }
- * }
- * </pre></code> The API programmer is responsible to set the correct
- * charset. And each application should remember its own charset to support.
- *
- * @param charset the default charset for the document
- * @throws DefaultCharsetChanged default charset changed
- */
- public static void setDefaultDocumentCharset(String charset)
- throws DefaultCharsetChanged {
-
- defaultDocumentCharset = charset;
- throw new DefaultCharsetChanged(DefaultCharsetChanged.DOCUMENT_CHARSET,
- "the default document charset changed");
- }
-
- /**
- * Get the recommended default charset of the document.
- *
- * @return the default charset string
- */
- public static String getDefaultDocumentCharset() {
- return defaultDocumentCharset;
- }
-
- /**
- * Get the default charset of the document by locale.
- *
- * @return the default charset string by locale
- */
- public static String getDefaultDocumentCharsetByLocale() {
- return defaultDocumentCharsetByLocale;
- }
-
- /**
- * Get the default charset of the document by platform.
- *
- * @return the default charset string by platform
- */
- public static String getDefaultDocumentCharsetByPlatform() {
- return defaultDocumentCharsetByPlatform;
- }
-
- // ------------------------------------------------------------- The scheme
-
- /**
- * Get the scheme.
- *
- * @return the scheme
- */
- public char[] getRawScheme() {
- return _scheme;
- }
-
- /**
- * Get the scheme.
- *
- * @return the scheme null if undefined scheme
- */
- public String getScheme() {
- return (_scheme == null) ? null : new String(_scheme);
- }
-
- // ---------------------------------------------------------- The authority
-
- /**
- * Set the authority. It can be one type of server, hostport, hostname,
- * IPv4address, IPv6reference and reg_name.
- *
- * <blockquote>
- *
- * <pre>
- * authority = server | reg_name
- * </pre>
- *
- * </blockquote>
- *
- *
- * @param escapedAuthority the raw escaped authority
- * @throws URIException If {@link #parseAuthority(java.lang.String,boolean)}
- * fails
- * @throws NullPointerException null authority
- */
- public void setRawAuthority(char[] escapedAuthority) throws URIException,
- NullPointerException {
-
- parseAuthority(new String(escapedAuthority), true);
- setURI();
- }
-
- /**
- * Set the authority. It can be one type of server, hostport, hostname,
- * IPv4address, IPv6reference and reg_name. Note that there is no
- * setAuthority method by the escape encoding reason.
- *
- * @param escapedAuthority the escaped authority string
- * @throws URIException If {@link #parseAuthority(java.lang.String,boolean)}
- * fails
- */
- public void setEscapedAuthority(String escapedAuthority)
- throws URIException {
-
- parseAuthority(escapedAuthority, true);
- setURI();
- }
-
- /**
- * Get the raw-escaped authority.
- *
- * @return the raw-escaped authority
- */
- public char[] getRawAuthority() {
- return _authority;
- }
-
- /**
- * Get the escaped authority.
- *
- * @return the escaped authority
- */
- public String getEscapedAuthority() {
- return (_authority == null) ? null : new String(_authority);
- }
-
- /**
- * Get the authority.
- *
- * @return the authority
- * @throws URIException If {@link #decode} fails
- */
- public String getAuthority() throws URIException {
- return (_authority == null) ? null : decode(_authority,
- getProtocolCharset());
- }
-
- // ----------------------------------------------------------- The userinfo
-
- /**
- * Get the raw-escaped userinfo.
- *
- * @return the raw-escaped userinfo
- * @see #getAuthority
- */
- public char[] getRawUserinfo() {
- return _userinfo;
- }
-
- /**
- * Get the escaped userinfo.
- *
- * @return the escaped userinfo
- * @see #getAuthority
- */
- public String getEscapedUserinfo() {
- return (_userinfo == null) ? null : new String(_userinfo);
- }
-
- /**
- * Get the userinfo.
- *
- * @return the userinfo
- * @throws URIException If {@link #decode} fails
- * @see #getAuthority
- */
- public String getUserinfo() throws URIException {
- return (_userinfo == null) ? null : decode(_userinfo,
- getProtocolCharset());
- }
-
- // --------------------------------------------------------------- The host
-
- /**
- * Get the host.
- *
- * <blockquote>
- *
- * <pre>
- * host = hostname | IPv4address | IPv6reference
- * </pre>
- *
- * </blockquote>
- *
- *
- * @return the host
- * @see #getAuthority
- */
- public char[] getRawHost() {
- return _host;
- }
-
- /**
- * Get the host.
- *
- * <blockquote>
- *
- * <pre>
- * host = hostname | IPv4address | IPv6reference
- * </pre>
- *
- * </blockquote>
- *
- *
- * @return the host
- * @throws URIException If {@link #decode} fails
- * @see #getAuthority
- */
- public String getHost() throws URIException {
- if (_host != null) {
- return decode(_host, getProtocolCharset());
- }
- return null;
- }
-
- // --------------------------------------------------------------- The port
-
- /**
- * Get the port. In order to get the specfic default port, the specific
- * protocol-supported class extended from the URI class should be used. It
- * has the server-based naming authority.
- *
- * @return the port if -1, it has the default port for the scheme or the
- * server-based naming authority is not supported in the specific
- * URI.
- */
- public int getPort() {
- return _port;
- }
-
- // --------------------------------------------------------------- The path
-
- /**
- * Set the raw-escaped path.
- *
- * @param escapedPath the path character sequence
- * @throws URIException encoding error or not proper for initial instance
- * @see #encode
- */
- public void setRawPath(char[] escapedPath) throws URIException {
- if (escapedPath == null || escapedPath.length == 0) {
- _path = _opaque = escapedPath;
- setURI();
- return;
- }
- // remove the fragment identifier
- escapedPath = removeFragmentIdentifier(escapedPath);
- if (_is_net_path || _is_abs_path) {
- if (escapedPath[0] != '/') {
- throw new URIException(URIException.PARSING,
- "not absolute path");
- }
- if (!validate(escapedPath, abs_path)) {
- throw new URIException(URIException.ESCAPING,
- "escaped absolute path not valid");
- }
- _path = escapedPath;
- } else if (_is_rel_path) {
- int at = indexFirstOf(escapedPath, '/');
- if (at == 0) {
- throw new URIException(URIException.PARSING, "incorrect path");
- }
- if (at > 0 && !validate(escapedPath, 0, at - 1, rel_segment)
- && !validate(escapedPath, at, -1, abs_path) || at < 0
- && !validate(escapedPath, 0, -1, rel_segment)) {
-
- throw new URIException(URIException.ESCAPING,
- "escaped relative path not valid");
- }
- _path = escapedPath;
- } else if (_is_opaque_part) {
- if (!uric_no_slash.get(escapedPath[0])
- && !validate(escapedPath, 1, -1, uric)) {
- throw new URIException(URIException.ESCAPING,
- "escaped opaque part not valid");
- }
- _opaque = escapedPath;
- } else {
- throw new URIException(URIException.PARSING, "incorrect path");
- }
- setURI();
- }
-
- /**
- * Set the escaped path.
- *
- * @param escapedPath the escaped path string
- * @throws URIException encoding error or not proper for initial instance
- * @see #encode
- */
- public void setEscapedPath(String escapedPath) throws URIException {
- if (escapedPath == null) {
- _path = _opaque = null;
- setURI();
- return;
- }
- setRawPath(escapedPath.toCharArray());
- }
-
- /**
- * Set the path.
- *
- * @param path the path string
- * @throws URIException set incorrectly or fragment only
- * @see #encode
- */
- public void setPath(String path) throws URIException {
-
- if (path == null || path.length() == 0) {
- _path = _opaque = (path == null) ? null : path.toCharArray();
- setURI();
- return;
- }
- // set the charset to do escape encoding
- String charset = getProtocolCharset();
-
- if (_is_net_path || _is_abs_path) {
- _path = encode(path, allowed_abs_path, charset);
- } else if (_is_rel_path) {
- StringBuilder buff = new StringBuilder(path.length());
- int at = path.indexOf('/');
- if (at == 0) { // never 0
- throw new URIException(URIException.PARSING,
- "incorrect relative path");
- }
- if (at > 0) {
- buff.append(encode(path.substring(0, at), allowed_rel_path,
- charset));
- buff.append(encode(path.substring(at), allowed_abs_path,
- charset));
- } else {
- buff.append(encode(path, allowed_rel_path, charset));
- }
- _path = buff.toString().toCharArray();
- } else if (_is_opaque_part) {
- StringBuilder buf = new StringBuilder();
- buf.insert(0, encode(path.substring(0, 1), uric_no_slash, charset));
- buf.insert(1, encode(path.substring(1), uric, charset));
- _opaque = buf.toString().toCharArray();
- } else {
- throw new URIException(URIException.PARSING, "incorrect path");
- }
- setURI();
- }
-
- /**
- * Resolve the base and relative path.
- *
- * @param basePath a character array of the basePath
- * @param relPath a character array of the relPath
- * @return the resolved path
- * @throws URIException no more higher path level to be resolved
- */
- protected char[] resolvePath(char[] basePath, char[] relPath)
- throws URIException {
-
- // REMINDME: paths are never null
- String base = (basePath == null) ? "" : new String(basePath);
-
- // _path could be empty
- if (relPath == null || relPath.length == 0) {
- return normalize(basePath);
- } else if (relPath[0] == '/') {
- return normalize(relPath);
- } else {
- int at = base.lastIndexOf('/');
- if (at != -1) {
- basePath = base.substring(0, at + 1).toCharArray();
- }
- StringBuilder buff = new StringBuilder(base.length() + relPath.length);
- buff.append((at != -1) ? base.substring(0, at + 1) : "/");
- buff.append(relPath);
- return normalize(buff.toString().toCharArray());
- }
- }
-
- /**
- * Get the raw-escaped current hierarchy level in the given path. If the
- * last namespace is a collection, the slash mark ('/') should be ended with
- * at the last character of the path string.
- *
- * @param path the path
- * @return the current hierarchy level
- * @throws URIException no hierarchy level
- */
- protected char[] getRawCurrentHierPath(char[] path) throws URIException {
-
- if (_is_opaque_part) {
- throw new URIException(URIException.PARSING, "no hierarchy level");
- }
- if (path == null) {
- throw new URIException(URIException.PARSING, "empty path");
- }
- String buff = new String(path);
- int first = buff.indexOf('/');
- int last = buff.lastIndexOf('/');
- if (last == 0) {
- return rootPath;
- } else if (first != last && last != -1) {
- return buff.substring(0, last).toCharArray();
- }
- // FIXME: it could be a document on the server side
- return path;
- }
-
- /**
- * Get the raw-escaped current hierarchy level.
- *
- * @return the raw-escaped current hierarchy level
- * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails.
- */
- public char[] getRawCurrentHierPath() throws URIException {
- return (_path == null) ? null : getRawCurrentHierPath(_path);
- }
-
- /**
- * Get the escaped current hierarchy level.
- *
- * @return the escaped current hierarchy level
- * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails.
- */
- public String getEscapedCurrentHierPath() throws URIException {
- char[] path = getRawCurrentHierPath();
- return (path == null) ? null : new String(path);
- }
-
- /**
- * Get the current hierarchy level.
- *
- * @return the current hierarchy level
- * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails.
- * @see #decode
- */
- public String getCurrentHierPath() throws URIException {
- char[] path = getRawCurrentHierPath();
- return (path == null) ? null : decode(path, getProtocolCharset());
- }
-
- /**
- * Get the level above the this hierarchy level.
- *
- * @return the raw above hierarchy level
- * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails.
- */
- public char[] getRawAboveHierPath() throws URIException {
- char[] path = getRawCurrentHierPath();
- return (path == null) ? null : getRawCurrentHierPath(path);
- }
-
- /**
- * Get the level above the this hierarchy level.
- *
- * @return the raw above hierarchy level
- * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails.
- */
- public String getEscapedAboveHierPath() throws URIException {
- char[] path = getRawAboveHierPath();
- return (path == null) ? null : new String(path);
- }
-
- /**
- * Get the level above the this hierarchy level.
- *
- * @return the above hierarchy level
- * @throws URIException If {@link #getRawCurrentHierPath(char[])} fails.
- * @see #decode
- */
- public String getAboveHierPath() throws URIException {
- char[] path = getRawAboveHierPath();
- return (path == null) ? null : decode(path, getProtocolCharset());
- }
-
- /**
- * Get the raw-escaped path.
- *
- * <blockquote>
- *
- * <pre>
- * path = [ abs_path | opaque_part ]
- * </pre>
- *
- * </blockquote>
- *
- *
- * @return the raw-escaped path
- */
- public char[] getRawPath() {
- return _is_opaque_part ? _opaque : _path;
- }
-
- /**
- * Get the escaped path.
- *
- * <blockquote>
- *
- * <pre>
- * path = [ abs_path | opaque_part ]
- * abs_path = "/" path_segments
- * opaque_part = uric_no_slash *uric
- * </pre>
- *
- * </blockquote>
- *
- *
- * @return the escaped path string
- */
- public String getEscapedPath() {
- char[] path = getRawPath();
- return (path == null) ? null : new String(path);
- }
-
- /**
- * Get the path.
- *
- * <blockquote>
- *
- * <pre>
- * path = [ abs_path | opaque_part ]
- * </pre>
- *
- * </blockquote>
- *
- *
- * @return the path string
- * @throws URIException If {@link #decode} fails.
- * @see #decode
- */
- public String getPath() throws URIException {
- char[] path = getRawPath();
- return (path == null) ? null : decode(path, getProtocolCharset());
- }
-
- /**
- * Get the raw-escaped basename of the path.
- *
- * @return the raw-escaped basename
- */
- public char[] getRawName() {
- if (_path == null) {
- return null;
- }
-
- int at = 0;
- for (int i = _path.length - 1; i >= 0; i--) {
- if (_path[i] == '/') {
- at = i + 1;
- break;
- }
- }
- int len = _path.length - at;
- char[] basename = new char[len];
- System.arraycopy(_path, at, basename, 0, len);
- return basename;
- }
-
- /**
- * Get the escaped basename of the path.
- *
- * @return the escaped basename string
- */
- public String getEscapedName() {
- char[] basename = getRawName();
- return (basename == null) ? null : new String(basename);
- }
-
- /**
- * Get the basename of the path.
- *
- * @return the basename string
- * @throws URIException incomplete trailing escape pattern or unsupported
- * character encoding
- * @see #decode
- */
- public String getName() throws URIException {
- char[] basename = getRawName();
- return (basename == null) ? null : decode(getRawName(),
- getProtocolCharset());
- }
-
- // ----------------------------------------------------- The path and query
-
- /**
- * Get the raw-escaped path and query.
- *
- * @return the raw-escaped path and query
- */
- public char[] getRawPathQuery() {
-
- if (_path == null && _query == null) {
- return null;
- }
- StringBuilder buff = new StringBuilder();
- if (_path != null) {
- buff.append(_path);
- }
- if (_query != null) {
- buff.append('?');
- buff.append(_query);
- }
- return buff.toString().toCharArray();
- }
-
- /**
- * Get the escaped query.
- *
- * @return the escaped path and query string
- */
- public String getEscapedPathQuery() {
- char[] rawPathQuery = getRawPathQuery();
- return (rawPathQuery == null) ? null : new String(rawPathQuery);
- }
-
- /**
- * Get the path and query.
- *
- * @return the path and query string.
- * @throws URIException incomplete trailing escape pattern or unsupported
- * character encoding
- * @see #decode
- */
- public String getPathQuery() throws URIException {
- char[] rawPathQuery = getRawPathQuery();
- return (rawPathQuery == null) ? null : decode(rawPathQuery,
- getProtocolCharset());
- }
-
- // -------------------------------------------------------------- The query
-
- /**
- * Set the raw-escaped query.
- *
- * @param escapedQuery the raw-escaped query
- * @throws URIException escaped query not valid
- */
- public void setRawQuery(char[] escapedQuery) throws URIException {
- if (escapedQuery == null || escapedQuery.length == 0) {
- _query = escapedQuery;
- setURI();
- return;
- }
- // remove the fragment identifier
- escapedQuery = removeFragmentIdentifier(escapedQuery);
- if (!validate(escapedQuery, query)) {
- throw new URIException(URIException.ESCAPING,
- "escaped query not valid");
- }
- _query = escapedQuery;
- setURI();
- }
-
- /**
- * Set the escaped query string.
- *
- * @param escapedQuery the escaped query string
- * @throws URIException escaped query not valid
- */
- public void setEscapedQuery(String escapedQuery) throws URIException {
- if (escapedQuery == null) {
- _query = null;
- setURI();
- return;
- }
- setRawQuery(escapedQuery.toCharArray());
- }
-
- /**
- * Set the query.
- *
- * When a query string is not misunderstood the reserved special characters
- * ("&", "=", "+", ",", and "$") within a query component, it is
- * recommended to use in encoding the whole query with this method.
- *
- * The additional APIs for the special purpose using by the reserved special
- * characters used in each protocol are implemented in each protocol classes
- * inherited from <code>URI</code>. So refer to the same-named APIs
- * implemented in each specific protocol instance.
- *
- * @param query the query string.
- * @throws URIException incomplete trailing escape pattern or unsupported
- * character encoding
- * @see #encode
- */
- public void setQuery(String query) throws URIException {
- if (query == null || query.length() == 0) {
- _query = (query == null) ? null : query.toCharArray();
- setURI();
- return;
- }
- setRawQuery(encode(query, allowed_query, getProtocolCharset()));
- }
-
- /**
- * Get the raw-escaped query.
- *
- * @return the raw-escaped query
- */
- public char[] getRawQuery() {
- return _query;
- }
-
- /**
- * Get the escaped query.
- *
- * @return the escaped query string
- */
- public String getEscapedQuery() {
- return (_query == null) ? null : new String(_query);
- }
-
- /**
- * Get the query.
- *
- * @return the query string.
- * @throws URIException incomplete trailing escape pattern or unsupported
- * character encoding
- * @see #decode
- */
- public String getQuery() throws URIException {
- return (_query == null) ? null : decode(_query, getProtocolCharset());
- }
-
- // ----------------------------------------------------------- The fragment
-
- /**
- * Set the raw-escaped fragment.
- *
- * @param escapedFragment the raw-escaped fragment
- * @throws URIException escaped fragment not valid
- */
- public void setRawFragment(char[] escapedFragment) throws URIException {
- if (escapedFragment == null || escapedFragment.length == 0) {
- _fragment = escapedFragment;
- hash = 0;
- return;
- }
- if (!validate(escapedFragment, fragment)) {
- throw new URIException(URIException.ESCAPING,
- "escaped fragment not valid");
- }
- _fragment = escapedFragment;
- hash = 0;
- }
-
- /**
- * Set the escaped fragment string.
- *
- * @param escapedFragment the escaped fragment string
- * @throws URIException escaped fragment not valid
- */
- public void setEscapedFragment(String escapedFragment) throws URIException {
- if (escapedFragment == null) {
- _fragment = null;
- hash = 0;
- return;
- }
- setRawFragment(escapedFragment.toCharArray());
- }
-
- /**
- * Set the fragment.
- *
- * @param fragment the fragment string.
- * @throws URIException If an error occurs.
- */
- public void setFragment(String fragment) throws URIException {
- if (fragment == null || fragment.length() == 0) {
- _fragment = (fragment == null) ? null : fragment.toCharArray();
- hash = 0;
- return;
- }
- _fragment = encode(fragment, allowed_fragment, getProtocolCharset());
- hash = 0;
- }
-
- /**
- * Get the raw-escaped fragment.
- *
- * The optional fragment identifier is not part of a URI, but is often used
- * in conjunction with a URI.
- *
- * The format and interpretation of fragment identifiers is dependent on the
- * media type [RFC2046] of the retrieval result.
- *
- * A fragment identifier is only meaningful when a URI reference is intended
- * for retrieval and the result of that retrieval is a document for which
- * the identified fragment is consistently defined.
- *
- * @return the raw-escaped fragment
- */
- public char[] getRawFragment() {
- return _fragment;
- }
-
- /**
- * Get the escaped fragment.
- *
- * @return the escaped fragment string
- */
- public String getEscapedFragment() {
- return (_fragment == null) ? null : new String(_fragment);
- }
-
- /**
- * Get the fragment.
- *
- * @return the fragment string
- * @throws URIException incomplete trailing escape pattern or unsupported
- * character encoding
- * @see #decode
- */
- public String getFragment() throws URIException {
- return (_fragment == null) ? null : decode(_fragment,
- getProtocolCharset());
- }
-
- // ------------------------------------------------------------- Utilities
-
- /**
- * Remove the fragment identifier of the given component.
- *
- * @param component the component that a fragment may be included
- * @return the component that the fragment identifier is removed
- */
- protected char[] removeFragmentIdentifier(char[] component) {
- if (component == null) {
- return null;
- }
- int lastIndex = new String(component).indexOf('#');
- if (lastIndex != -1) {
- component = new String(component).substring(0, lastIndex).toCharArray();
- }
- return component;
- }
-
- /**
- * Normalize the given hier path part.
- *
- * Algorithm taken from URI reference parser at
- * http://www.apache.org/~fielding/uri/rev-2002/issues.html.
- *
- * @param path the path to normalize
- * @return the normalized path
- * @throws URIException no more higher path level to be normalized
- */
- protected char[] normalize(char[] path) throws URIException {
-
- if (path == null) {
- return null;
- }
-
- String normalized = new String(path);
-
- // If the buffer begins with "./" or "../", the "." or ".." is removed.
- if (normalized.startsWith("./")) {
- normalized = normalized.substring(1);
- } else if (normalized.startsWith("../")) {
- normalized = normalized.substring(2);
- } else if (normalized.startsWith("..")) {
- normalized = normalized.substring(2);
- }
-
- // All occurrences of "/./" in the buffer are replaced with "/"
- int index = -1;
- while ((index = normalized.indexOf("/./")) != -1) {
- normalized = normalized.substring(0, index)
- + normalized.substring(index + 2);
- }
-
- // If the buffer ends with "/.", the "." is removed.
- if (normalized.endsWith("/.")) {
- normalized = normalized.substring(0, normalized.length() - 1);
- }
-
- int startIndex = 0;
-
- // All occurrences of "/<segment>/../" in the buffer, where ".."
- // and <segment> are complete path segments, are iteratively replaced
- // with "/" in order from left to right until no matching pattern
- // remains.
- // If the buffer ends with "/<segment>/..", that is also replaced
- // with "/". Note that <segment> may be empty.
- while ((index = normalized.indexOf("/../", startIndex)) != -1) {
- int slashIndex = normalized.lastIndexOf('/', index - 1);
- if (slashIndex >= 0) {
- normalized = normalized.substring(0, slashIndex)
- + normalized.substring(index + 3);
- } else {
- startIndex = index + 3;
- }
- }
- if (normalized.endsWith("/..")) {
- int slashIndex = normalized.lastIndexOf('/',
- normalized.length() - 4);
- if (slashIndex >= 0) {
- normalized = normalized.substring(0, slashIndex + 1);
- }
- }
-
- // All prefixes of "<segment>/../" in the buffer, where ".."
- // and <segment> are complete path segments, are iteratively replaced
- // with "/" in order from left to right until no matching pattern
- // remains.
- // If the buffer ends with "<segment>/..", that is also replaced
- // with "/". Note that <segment> may be empty.
- while ((index = normalized.indexOf("/../")) != -1) {
- int slashIndex = normalized.lastIndexOf('/', index - 1);
- if (slashIndex >= 0) {
- break;
- }
- normalized = normalized.substring(index + 3);
- }
- if (normalized.endsWith("/..")) {
- int slashIndex = normalized.lastIndexOf('/',
- normalized.length() - 4);
- if (slashIndex < 0) {
- normalized = "/";
- }
- }
-
- return normalized.toCharArray();
- }
-
- /**
- * Normalizes the path part of this URI. Normalization is only meant to be
- * performed on URIs with an absolute path. Calling this method on a
- * relative path URI will have no effect.
- *
- * @throws URIException no more higher path level to be normalized
- * @see #isAbsPath()
- */
- public void normalize() throws URIException {
- if (isAbsPath()) {
- _path = normalize(_path);
- setURI();
- }
- }
-
- /**
- * Test if the first array is equal to the second array.
- *
- * @param first the first character array
- * @param second the second character array
- * @return true if they're equal
- */
- protected boolean equals(char[] first, char[] second) {
-
- if (first == null && second == null) {
- return true;
- }
- if (first == null || second == null) {
- return false;
- }
- if (first.length != second.length) {
- return false;
- }
- for (int i = 0; i < first.length; i++) {
- if (first[i] != second[i]) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Test an object if this URI is equal to another.
- *
- * @param obj an object to compare
- * @return true if two URI objects are equal
- */
- public boolean equals(Object obj) {
-
- // normalize and test each components
- if (obj == this) {
- return true;
- }
- if (!(obj instanceof URI)) {
- return false;
- }
- URI another = (URI) obj;
- // scheme
- if (!equals(_scheme, another._scheme)) {
- return false;
- }
- // is_opaque_part or is_hier_part? and opaque
- if (!equals(_opaque, another._opaque)) {
- return false;
- }
- // is_hier_part
- // has_authority
- if (!equals(_authority, another._authority)) {
- return false;
- }
- // path
- if (!equals(_path, another._path)) {
- return false;
- }
- // has_query
- if (!equals(_query, another._query)) {
- return false;
- }
- // has_fragment? should be careful of the only fragment case.
- if (!equals(_fragment, another._fragment)) {
- return false;
- }
- return true;
- }
-
- // ---------------------------------------------------------- Serialization
-
- /**
- * Write the content of this URI.
- *
- * @param oos the object-output stream
- * @throws IOException If an IO problem occurs.
- */
- private void writeObject(ObjectOutputStream oos) throws IOException {
-
- oos.defaultWriteObject();
- }
-
- /**
- * Read a URI.
- *
- * @param ois the object-input stream
- * @throws ClassNotFoundException If one of the classes specified in the
- * input stream cannot be found.
- * @throws IOException If an IO problem occurs.
- */
- private void readObject(ObjectInputStream ois)
- throws ClassNotFoundException, IOException {
-
- ois.defaultReadObject();
- }
-
- // -------------------------------------------------------------- Hash code
-
- /**
- * Return a hash code for this URI.
- *
- * @return a has code value for this URI
- */
- public int hashCode() {
- if (hash == 0) {
- char[] c = _uri;
- if (c != null) {
- for (int i = 0, len = c.length; i < len; i++) {
- hash = 31 * hash + c[i];
- }
- }
- c = _fragment;
- if (c != null) {
- for (int i = 0, len = c.length; i < len; i++) {
- hash = 31 * hash + c[i];
- }
- }
- }
- return hash;
- }
-
- // ------------------------------------------------------------- Comparison
-
- /**
- * Compare this URI to another object.
- *
- * @param another the object to be compared.
- * @return 0, if it's same, -1, if failed, first being compared with in the
- * authority component
- * @throws ClassCastException not URI argument
- */
- public int compareTo(URI another) {
-
- if (!equals(_authority, another.getRawAuthority())) {
- return -1;
- }
- return toString().compareTo(another.toString());
- }
-
- // ------------------------------------------------------------------ Clone
-
- /**
- * Create and return a copy of this object, the URI-reference containing the
- * userinfo component. Notice that the whole URI-reference including the
- * userinfo component counld not be gotten as a <code>String</code>.
- *
- * To copy the identical <code>URI</code> object including the userinfo
- * component, it should be used.
- *
- * @return a clone of this instance
- */
- public synchronized Object clone() throws CloneNotSupportedException {
-
- URI instance = (URI) super.clone();
-
- instance._uri = _uri;
- instance._scheme = _scheme;
- instance._opaque = _opaque;
- instance._authority = _authority;
- instance._userinfo = _userinfo;
- instance._host = _host;
- instance._port = _port;
- instance._path = _path;
- instance._query = _query;
- instance._fragment = _fragment;
- // the charset to do escape encoding for this instance
- instance.protocolCharset = protocolCharset;
- // flags
- instance._is_hier_part = _is_hier_part;
- instance._is_opaque_part = _is_opaque_part;
- instance._is_net_path = _is_net_path;
- instance._is_abs_path = _is_abs_path;
- instance._is_rel_path = _is_rel_path;
- instance._is_reg_name = _is_reg_name;
- instance._is_server = _is_server;
- instance._is_hostname = _is_hostname;
- instance._is_IPv4address = _is_IPv4address;
- instance._is_IPv6reference = _is_IPv6reference;
-
- return instance;
- }
-
- // ------------------------------------------------------------ Get the URI
-
- /**
- * It can be gotten the URI character sequence. It's raw-escaped. For the
- * purpose of the protocol to be transported, it will be useful.
- *
- * It is clearly unwise to use a URL that contains a password which is
- * intended to be secret. In particular, the use of a password within the
- * 'userinfo' component of a URL is strongly disrecommended except in those
- * rare cases where the 'password' parameter is intended to be public.
- *
- * When you want to get each part of the userinfo, you need to use the
- * specific methods in the specific URL. It depends on the specific URL.
- *
- * @return the URI character sequence
- */
- public char[] getRawURI() {
- return _uri;
- }
-
- /**
- * It can be gotten the URI character sequence. It's escaped. For the
- * purpose of the protocol to be transported, it will be useful.
- *
- * @return the escaped URI string
- */
- public String getEscapedURI() {
- return (_uri == null) ? null : new String(_uri);
- }
-
- /**
- * It can be gotten the URI character sequence.
- *
- * @return the original URI string
- * @throws URIException incomplete trailing escape pattern or unsupported
- * character encoding
- * @see #decode
- */
- public String getURI() throws URIException {
- return (_uri == null) ? null : decode(_uri, getProtocolCharset());
- }
-
- /**
- * Get the URI reference character sequence.
- *
- * @return the URI reference character sequence
- */
- public char[] getRawURIReference() {
- if (_fragment == null) {
- return _uri;
- }
- if (_uri == null) {
- return _fragment;
- }
- // if _uri != null && _fragment != null
- String uriReference = new String(_uri) + "#" + new String(_fragment);
- return uriReference.toCharArray();
- }
-
- /**
- * Get the escaped URI reference string.
- *
- * @return the escaped URI reference string
- */
- public String getEscapedURIReference() {
- char[] uriReference = getRawURIReference();
- return (uriReference == null) ? null : new String(uriReference);
- }
-
- /**
- * Get the original URI reference string.
- *
- * @return the original URI reference string
- * @throws URIException If {@link #decode} fails.
- */
- public String getURIReference() throws URIException {
- char[] uriReference = getRawURIReference();
- return (uriReference == null) ? null : decode(uriReference,
- getProtocolCharset());
- }
-
- /**
- * Get the escaped URI string.
- *
- * On the document, the URI-reference form is only used without the userinfo
- * component like http://jakarta.apache.org/ by the security reason. But the
- * URI-reference form with the userinfo component could be parsed.
- *
- * In other words, this URI and any its subclasses must not expose the
- * URI-reference expression with the userinfo component like
- * http://user:password@hostport/restricted_zone.<br>
- * It means that the API client programmer should extract each user and
- * password to access manually. Probably it will be supported in the each
- * subclass, however, not a whole URI-reference expression.
- *
- * @return the escaped URI string
- * @see #clone()
- */
- public String toString() {
- return getEscapedURI();
- }
-
- // ------------------------------------------------------------ Inner class
-
- /**
- * The charset-changed normal operation to represent to be required to alert
- * to user the fact the default charset is changed.
- */
- @SuppressWarnings("serial")
- public static class DefaultCharsetChanged extends SlingException {
-
- // ------------------------------------------------------- constructors
-
- /**
- * The constructor with a reason string and its code arguments.
- *
- * @param reasonCode the reason code
- * @param reason the reason
- */
- public DefaultCharsetChanged(int reasonCode, String reason) {
- super(reason);
- this.reason = reason;
- this.reasonCode = reasonCode;
- }
-
- // ---------------------------------------------------------- constants
-
- /** No specified reason code. */
- public static final int UNKNOWN = 0;
-
- /** Protocol charset changed. */
- public static final int PROTOCOL_CHARSET = 1;
-
- /** Document charset changed. */
- public static final int DOCUMENT_CHARSET = 2;
-
- // ------------------------------------------------- instance variables
-
- /** The reason code. */
- private int reasonCode;
-
- /** The reason message. */
- private String reason;
-
- // ------------------------------------------------------------ methods
-
- /**
- * Get the reason code.
- *
- * @return the reason code
- */
- public int getReasonCode() {
- return reasonCode;
- }
-
- /**
- * Get the reason message.
- *
- * @return the reason message
- */
- public String getReason() {
- return reason;
- }
-
- }
-
- /**
- * A mapping to determine the (somewhat arbitrarily) preferred charset for a
- * given locale. Supports all locales recognized in JDK 1.1.
- *
- * The distribution of this class is Servlets.com. It was originally written
- * by Jason Hunter [jhunter at acm.org] and used by with permission.
- */
- public static class LocaleToCharsetMap {
-
- /** A mapping of language code to charset */
- private static final HashMap<String, String> LOCALE_TO_CHARSET_MAP;
- static {
- LOCALE_TO_CHARSET_MAP = new HashMap<String, String>();
- LOCALE_TO_CHARSET_MAP.put("ar", "ISO-8859-6");
- LOCALE_TO_CHARSET_MAP.put("be", "ISO-8859-5");
- LOCALE_TO_CHARSET_MAP.put("bg", "ISO-8859-5");
- LOCALE_TO_CHARSET_MAP.put("ca", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("cs", "ISO-8859-2");
- LOCALE_TO_CHARSET_MAP.put("da", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("de", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("el", "ISO-8859-7");
- LOCALE_TO_CHARSET_MAP.put("en", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("es", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("et", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("fi", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("fr", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("hr", "ISO-8859-2");
- LOCALE_TO_CHARSET_MAP.put("hu", "ISO-8859-2");
- LOCALE_TO_CHARSET_MAP.put("is", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("it", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("iw", "ISO-8859-8");
- LOCALE_TO_CHARSET_MAP.put("ja", "Shift_JIS");
- LOCALE_TO_CHARSET_MAP.put("ko", "EUC-KR");
- LOCALE_TO_CHARSET_MAP.put("lt", "ISO-8859-2");
- LOCALE_TO_CHARSET_MAP.put("lv", "ISO-8859-2");
- LOCALE_TO_CHARSET_MAP.put("mk", "ISO-8859-5");
- LOCALE_TO_CHARSET_MAP.put("nl", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("no", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("pl", "ISO-8859-2");
- LOCALE_TO_CHARSET_MAP.put("pt", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("ro", "ISO-8859-2");
- LOCALE_TO_CHARSET_MAP.put("ru", "ISO-8859-5");
- LOCALE_TO_CHARSET_MAP.put("sh", "ISO-8859-5");
- LOCALE_TO_CHARSET_MAP.put("sk", "ISO-8859-2");
- LOCALE_TO_CHARSET_MAP.put("sl", "ISO-8859-2");
- LOCALE_TO_CHARSET_MAP.put("sq", "ISO-8859-2");
- LOCALE_TO_CHARSET_MAP.put("sr", "ISO-8859-5");
- LOCALE_TO_CHARSET_MAP.put("sv", "ISO-8859-1");
- LOCALE_TO_CHARSET_MAP.put("tr", "ISO-8859-9");
- LOCALE_TO_CHARSET_MAP.put("uk", "ISO-8859-5");
- LOCALE_TO_CHARSET_MAP.put("zh", "GB2312");
- LOCALE_TO_CHARSET_MAP.put("zh_TW", "Big5");
- }
-
- /**
- * Get the preferred charset for the given locale.
- *
- * @param locale the locale
- * @return the preferred charset or null if the locale is not
- * recognized.
- */
- public static String getCharset(Locale locale) {
- // try for an full name match (may include country)
- String charset = LOCALE_TO_CHARSET_MAP.get(locale.toString());
- if (charset != null) {
- return charset;
- }
-
- // if a full name didn't match, try just the language
- charset = LOCALE_TO_CHARSET_MAP.get(locale.getLanguage());
- return charset; // may be null
- }
-
- }
-
- // from EncodingUtils...
-
- /**
- * Converts the specified string to a byte array. If the charset is not
- * supported the default system charset is used.
- *
- * @param data the string to be encoded
- * @param charset the desired character encoding
- * @return The resulting byte array.
- * @since 3.0
- */
- private static byte[] getBytes(final String data, String charset) {
-
- if (data == null) {
- throw new IllegalArgumentException("data may not be null");
- }
-
- if (charset == null || charset.length() == 0) {
- throw new IllegalArgumentException(
- "charset may not be null or empty");
- }
-
- try {
- return data.getBytes(charset);
- } catch (UnsupportedEncodingException e) {
-
- // if (LOG.isWarnEnabled()) {
- // LOG.warn("Unsupported encoding: " + charset +
- // ". System encoding used.");
- // }
-
- return data.getBytes();
- }
- }
-
- /**
- * Converts the byte array of ASCII characters to a string. This method is
- * to be used when decoding content of HTTP elements (such as response
- * headers)
- *
- * @param data the byte array to be encoded
- * @param offset the index of the first byte to encode
- * @param length the number of bytes to encode
- * @return The string representation of the byte array
- * @since 3.0
- */
- private static String getAsciiString(final byte[] data) {
-
- if (data == null) {
- throw new IllegalArgumentException("Parameter may not be null");
- }
-
- try {
- return new String(data, "US-ASCII");
- } catch (UnsupportedEncodingException e) {
- throw new URIException("HttpClient requires ASCII support");
- }
- }
-
- /**
- * Converts the byte array of HTTP content characters to a string. If the
- * specified charset is not supported, default system encoding is used.
- *
- * @param data the byte array to be encoded
- * @param charset the desired character encoding
- * @return The result of the conversion.
- * @since 3.0
- */
- public static String getString(final byte[] data, String charset) {
-
- if (data == null) {
- throw new IllegalArgumentException("Parameter may not be null");
- }
-
- if (charset == null || charset.length() == 0) {
- throw new IllegalArgumentException(
- "charset may not be null or empty");
- }
-
- try {
- return new String(data, charset);
- } catch (UnsupportedEncodingException e) {
-
- // if (LOG.isWarnEnabled()) {
- // LOG.warn("Unsupported encoding: " + charset +
- // ". System encoding used");
- // }
- return new String(data);
- }
- }
-
- /**
- * Converts the specified string to byte array of ASCII characters.
- *
- * @param data the string to be encoded
- * @return The string as a byte array.
- * @since 3.0
- */
- public static byte[] getAsciiBytes(final String data) {
-
- if (data == null) {
- throw new IllegalArgumentException("Parameter may not be null");
- }
-
- try {
- return data.getBytes("US-ASCII");
- } catch (UnsupportedEncodingException e) {
- throw new URIException("HttpClient requires ASCII support");
- }
- }
-
- /**
- * Encodes an array of bytes into an array of URL safe 7-bit characters.
- * Unsafe characters are escaped.
- *
- * @param urlsafe bitset of characters deemed URL safe
- * @param bytes array of bytes to convert to URL safe characters
- * @return array of bytes containing URL safe characters
- */
- private static final byte[] encodeUrl(BitSet urlsafe, byte[] bytes) {
- if (bytes == null) {
- return null;
- }
-
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- for (int i = 0; i < bytes.length; i++) {
- int b = bytes[i];
- if (b < 0) {
- b = 256 + b;
- }
- if (urlsafe.get(b)) {
- if (b == ' ') {
- b = '+';
- }
- buffer.write(b);
- } else {
- buffer.write('%');
- char hex1 = Character.toUpperCase(Character.forDigit(
- (b >> 4) & 0xF, 16));
- char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF,
- 16));
- buffer.write(hex1);
- buffer.write(hex2);
- }
- }
- return buffer.toByteArray();
- }
-
- /**
- * Decodes an array of URL safe 7-bit characters into an array of original
- * bytes. Escaped characters are converted back to their original
- * representation.
- *
- * @param bytes array of URL safe characters
- * @return array of original bytes
- * @throws URIException Thrown if URL decoding is unsuccessful
- */
- private static final byte[] decodeUrl(byte[] bytes) {
- if (bytes == null) {
- return null;
- }
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- for (int i = 0; i < bytes.length; i++) {
- int b = bytes[i];
- if (b == '+') {
- buffer.write(' ');
- } else if (b == '%') {
- try {
- int u = Character.digit((char) bytes[++i], 16);
- int l = Character.digit((char) bytes[++i], 16);
- if (u == -1 || l == -1) {
- throw new URIException("Invalid URL encoding");
- }
- buffer.write((char) ((u << 4) + l));
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new URIException("Invalid URL encoding");
- }
- } else {
- buffer.write(b);
- }
- }
- return buffer.toByteArray();
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/URIException.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/URIException.java
deleted file mode 100644
index 435cc5c..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/URIException.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import org.apache.sling.api.SlingException;
-
-/**
- * The URI parsing and escape encoding exception.
- * <p>
- * This class is a slightly modified version of the URIException class
- * distributed with Http Client 3.1. The changes are removal of deprecated
- * methods and have the class itself extend the <code>SlingException</code> to
- * adapt it to the exception hierarchy of Sling.
- */
-@SuppressWarnings("serial")
-public class URIException extends SlingException {
-
- // ----------------------------------------------------------- constructors
-
- /**
- * Default constructor.
- */
- public URIException() {
- }
-
- /**
- * The constructor with a reason code argument.
- *
- * @param reasonCode the reason code
- */
- public URIException(int reasonCode) {
- this.reasonCode = reasonCode;
- }
-
- /**
- * The constructor with a reason string and its code arguments.
- *
- * @param reasonCode the reason code
- * @param reason the reason
- */
- public URIException(int reasonCode, String reason) {
- super(reason); // for backward compatibility of Throwable
- this.reason = reason;
- this.reasonCode = reasonCode;
- }
-
- /**
- * The constructor with a reason string argument.
- *
- * @param reason the reason
- */
- public URIException(String reason) {
- super(reason); // for backward compatibility of Throwable
- this.reason = reason;
- this.reasonCode = UNKNOWN;
- }
-
- // -------------------------------------------------------------- constants
-
- /**
- * No specified reason code.
- */
- public static final int UNKNOWN = 0;
-
- /**
- * The URI parsing error.
- */
- public static final int PARSING = 1;
-
- /**
- * The unsupported character encoding.
- */
- public static final int UNSUPPORTED_ENCODING = 2;
-
- /**
- * The URI escape encoding and decoding error.
- */
- public static final int ESCAPING = 3;
-
- /**
- * The DNS punycode encoding or decoding error.
- */
- public static final int PUNYCODE = 4;
-
- // ------------------------------------------------------------- properties
-
- /**
- * The reason code.
- */
- protected int reasonCode;
-
- /**
- * The reason message.
- */
- protected String reason;
-
- // ---------------------------------------------------------------- methods
-
- /**
- * Get the reason code.
- *
- * @return the reason code
- */
- public int getReasonCode() {
- return reasonCode;
- }
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/helper/UniqueResourceIterator.java b/src/main/java/org/apache/sling/resourceresolver/impl/helper/UniqueResourceIterator.java
deleted file mode 100644
index 1f0cade..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/helper/UniqueResourceIterator.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import java.util.Iterator;
-import java.util.Set;
-
-import org.apache.sling.api.resource.Resource;
-
-/**
- * This iterator removes duplicated Resource entries. Regular resources
- * overrides the synthetic ones.
- */
-public class UniqueResourceIterator extends AbstractIterator<Resource> {
-
- private final Iterator<Resource> input;
-
- private final Set<String> visited;
-
- public UniqueResourceIterator(final Set<String> visited, final Iterator<Resource> input) {
- this.input = input;
- this.visited = visited;
- }
-
- @Override
- protected Resource seek() {
- while (input.hasNext()) {
- final Resource next = input.next();
- final String name = next.getName();
-
- if (visited.contains(name)) {
- continue;
- } else {
- visited.add(name);
- next.getResourceMetadata().setResolutionPath(next.getPath());
- return next;
- }
- }
-
- return null;
- }
-}
-
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderAdapter.java b/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderAdapter.java
deleted file mode 100644
index 7c94ffb..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderAdapter.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * 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.resourceresolver.impl.legacy;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-
-import org.apache.sling.api.adapter.Adaptable;
-import org.apache.sling.api.resource.AttributableResourceProvider;
-import org.apache.sling.api.resource.DynamicResourceProvider;
-import org.apache.sling.api.resource.ModifyingResourceProvider;
-import org.apache.sling.api.resource.ParametrizableResourceProvider;
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.QueriableResourceProvider;
-import org.apache.sling.api.resource.RefreshableResourceProvider;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceMetadata;
-import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-
-@SuppressWarnings("deprecation")
-public class LegacyResourceProviderAdapter extends ResourceProvider<Object> implements Closeable {
-
- private final org.apache.sling.api.resource.ResourceProvider rp;
-
- private final String[] languages;
-
- private final boolean ownsRoot;
-
- public LegacyResourceProviderAdapter(org.apache.sling.api.resource.ResourceProvider rp, String[] languages, boolean ownsRoot) {
- this.rp = rp;
- this.languages = languages;
- this.ownsRoot = ownsRoot;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public Resource getResource(ResolveContext<Object> ctx, String path, ResourceContext resourceContext, Resource parent) {
- Resource resourceCandidate;
- if (rp instanceof ParametrizableResourceProvider) {
- resourceCandidate = ((ParametrizableResourceProvider) rp).getResource(ctx.getResourceResolver(), path,
- resourceContext.getResolveParameters());
- } else {
- resourceCandidate = rp.getResource(ctx.getResourceResolver(), path);
- }
-
- ResourceProvider<?> parentProvider = ctx.getParentResourceProvider();
- ResolveContext parentCtx = ctx.getParentResolveContext();
- // Ask the parent provider
- if (resourceCandidate == null && !ownsRoot && parentProvider != null) {
- return parentProvider.getResource(parentCtx, path, resourceContext, parent);
- }
-
- // Support the INTERNAL_CONTINUE_RESOLVING flag
- Resource fallbackResource = resourceCandidate;
- if (resourceCandidate != null && parentProvider != null && isContinueResolving(resourceCandidate)) {
- resourceCandidate = ctx.getParentResourceProvider().getResource(parentCtx, path, resourceContext, parent);
- }
- if (resourceCandidate != null) {
- return resourceCandidate;
- } else {
- return fallbackResource;
- }
- }
-
- private boolean isContinueResolving(Resource resource) {
- return resource.getResourceMetadata() != null
- && resource.getResourceMetadata().containsKey(ResourceMetadata.INTERNAL_CONTINUE_RESOLVING);
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public Iterator<Resource> listChildren(ResolveContext<Object> ctx, Resource parent) {
- Iterator<Resource> children = rp.listChildren(parent);
- if (children == null && !ownsRoot && ctx.getParentResourceProvider() != null) {
- children = ctx.getParentResourceProvider().listChildren((ResolveContext) ctx.getParentResolveContext(),
- parent);
- }
- return children;
- }
-
- @Override
- public void refresh(final @Nonnull ResolveContext<Object> ctx) {
- if (rp instanceof RefreshableResourceProvider) {
- ((RefreshableResourceProvider) rp).refresh();
- }
- }
-
- @Override
- public @CheckForNull QueryLanguageProvider<Object> getQueryLanguageProvider() {
- if (rp instanceof QueriableResourceProvider) {
- return new JCRQueryProviderAdapter((QueriableResourceProvider) rp, languages);
- } else {
- return super.getQueryLanguageProvider();
- }
- }
-
- @Override
- public Collection<String> getAttributeNames(final @Nonnull ResolveContext<Object> ctx) {
- if (rp instanceof AttributableResourceProvider) {
- return ((AttributableResourceProvider) rp).getAttributeNames(ctx.getResourceResolver());
- } else {
- return super.getAttributeNames(ctx);
- }
- }
-
- @Override
- public Object getAttribute(final @Nonnull ResolveContext<Object> ctx, final @Nonnull String name) {
- if (rp instanceof AttributableResourceProvider) {
- return ((AttributableResourceProvider) rp).getAttribute(ctx.getResourceResolver(), name);
- } else {
- return super.getAttribute(ctx, name);
- }
- }
-
- @Override
- public boolean isLive(final @Nonnull ResolveContext<Object> ctx) {
- if (rp instanceof DynamicResourceProvider) {
- return ((DynamicResourceProvider) rp).isLive();
- } else {
- return super.isLive(ctx);
- }
- }
-
- @Override
- public void logout(final @Nonnull Object state) {
- if (rp instanceof DynamicResourceProvider) {
- ((DynamicResourceProvider) rp).close();
- }
- }
-
- @Override
- public void close() throws IOException {
- logout(null);
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public Resource create(final @Nonnull ResolveContext<Object> ctx, final String path,
- final Map<String, Object> properties) throws PersistenceException {
- Resource createdResource = null;
- if (rp instanceof ModifyingResourceProvider) {
- createdResource = ((ModifyingResourceProvider) rp).create(ctx.getResourceResolver(), path, properties);
- }
- if (createdResource == null && !ownsRoot && ctx.getParentResourceProvider() != null) {
- createdResource = ctx.getParentResourceProvider().create((ResolveContext) ctx.getParentResolveContext(),
- path, properties);
- }
- return createdResource;
- }
-
- @Override
- public void delete(final @Nonnull ResolveContext<Object> ctx, final @Nonnull Resource resource)
- throws PersistenceException {
- if (rp instanceof ModifyingResourceProvider) {
- ((ModifyingResourceProvider) rp).delete(ctx.getResourceResolver(), resource.getPath());
- } else {
- super.delete(ctx, resource);
- }
- }
-
- @Override
- public void revert(final @Nonnull ResolveContext<Object> ctx) {
- if (rp instanceof ModifyingResourceProvider) {
- ((ModifyingResourceProvider) rp).revert(ctx.getResourceResolver());
- } else {
- super.revert(ctx);
- }
- }
-
- @Override
- public void commit(final @Nonnull ResolveContext<Object> ctx) throws PersistenceException {
- if (rp instanceof ModifyingResourceProvider) {
- ((ModifyingResourceProvider) rp).commit(ctx.getResourceResolver());
- } else {
- super.commit(ctx);
- }
- }
-
- @Override
- public boolean hasChanges(final @Nonnull ResolveContext<Object> ctx) {
- if (rp instanceof ModifyingResourceProvider) {
- return ((ModifyingResourceProvider) rp).hasChanges(ctx.getResourceResolver());
- } else {
- return super.hasChanges(ctx);
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <AdapterType> AdapterType adaptTo(final @Nonnull ResolveContext<Object> ctx, final @Nonnull Class<AdapterType> type) {
- if ( rp instanceof Adaptable ) {
- final Object value = ((Adaptable)rp).adaptTo(type);
- if ( value != null ) {
- return (AdapterType) value;
- }
- }
- return super.adaptTo(ctx, type);
- }
-
- private static class JCRQueryProviderAdapter implements QueryLanguageProvider<Object> {
-
- private final QueriableResourceProvider rp;
-
- private final String[] languages;
-
- public JCRQueryProviderAdapter(QueriableResourceProvider rp, String[] languages) {
- this.rp = rp;
- this.languages = languages;
- }
-
- @Override
- public String[] getSupportedLanguages(ResolveContext<Object> ctx) {
- return languages;
- }
-
- @Override
- public Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language) {
- return rp.findResources(ctx.getResourceResolver(), query, language);
- }
-
- @Override
- public Iterator<ValueMap> queryResources(ResolveContext<Object> ctx, String query, String language) {
- return rp.queryResources(ctx.getResourceResolver(), query, language);
- }
- }
-
- @Override
- public String toString() {
- return "[" + getClass().getSimpleName() + ": " + rp.toString() + " ]";
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderFactoryAdapter.java b/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderFactoryAdapter.java
deleted file mode 100644
index ff75009..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderFactoryAdapter.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.resourceresolver.impl.legacy;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-
-import org.apache.commons.lang.ArrayUtils;
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceProviderFactory;
-import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-
-@SuppressWarnings({ "deprecation", "rawtypes", "unchecked" })
-public class LegacyResourceProviderFactoryAdapter extends ResourceProvider<LegacyResourceProviderAdapter> {
-
- private final ResourceProviderFactory rpFactory;
-
- private final String[] languages;
-
- private final boolean ownsRoot;
-
- public LegacyResourceProviderFactoryAdapter(ResourceProviderFactory rpFactory, String[] languages, boolean ownsRoot) {
- this.rpFactory = rpFactory;
- this.languages = languages;
- this.ownsRoot = ownsRoot;
- }
-
- @Override
- @Nonnull
- public LegacyResourceProviderAdapter authenticate(final @Nonnull Map<String, Object> authenticationInfo)
- throws LoginException {
- return new LegacyResourceProviderAdapter(rpFactory.getResourceProvider(authenticationInfo), languages, ownsRoot);
- }
-
- @Override
- public void logout(final @Nonnull LegacyResourceProviderAdapter state) {
- state.logout(null);
- }
-
- @Override
- public Resource getResource(ResolveContext<LegacyResourceProviderAdapter> ctx, String path, ResourceContext resourceContext, Resource parent) {
- return ctx.getProviderState().getResource((ResolveContext) ctx, path, resourceContext, parent);
- }
-
- @Override
- public Iterator<Resource> listChildren(ResolveContext<LegacyResourceProviderAdapter> ctx, Resource parent) {
- return ctx.getProviderState().listChildren((ResolveContext) ctx, parent);
- }
-
- @Override
- public void refresh(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) {
- ctx.getProviderState().refresh((ResolveContext) ctx);
- }
-
- @Override
- public @CheckForNull QueryLanguageProvider<LegacyResourceProviderAdapter> getQueryLanguageProvider() {
- if (ArrayUtils.isEmpty(languages)) {
- return super.getQueryLanguageProvider();
- } else {
- return new JCRQueryProviderAdapter(languages);
- }
- }
-
- @Override
- public Collection<String> getAttributeNames(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) {
- return ctx.getProviderState().getAttributeNames((ResolveContext) ctx);
- }
-
- @Override
- public Object getAttribute(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx,
- final @Nonnull String name) {
- return ctx.getProviderState().getAttribute((ResolveContext) ctx, name);
- }
-
- @Override
- public boolean isLive(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) {
- return ctx.getProviderState().isLive((ResolveContext) ctx);
- }
-
- @Override
- public Resource create(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx, final String path,
- final Map<String, Object> properties) throws PersistenceException {
- return ctx.getProviderState().create((ResolveContext) ctx, path, properties);
- }
-
- @Override
- public void delete(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx,
- final @Nonnull Resource resource) throws PersistenceException {
- ctx.getProviderState().delete((ResolveContext) ctx, resource);
- }
-
- @Override
- public void revert(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) {
- ctx.getProviderState().revert((ResolveContext) ctx);
- }
-
- @Override
- public void commit(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) throws PersistenceException {
- ctx.getProviderState().commit((ResolveContext) ctx);
- }
-
- @Override
- public boolean hasChanges(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx) {
- return ctx.getProviderState().hasChanges((ResolveContext) ctx);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <AdapterType> AdapterType adaptTo(final @Nonnull ResolveContext<LegacyResourceProviderAdapter> ctx, final @Nonnull Class<AdapterType> type) {
- return (AdapterType) ctx.getProviderState().adaptTo((ResolveContext)ctx, type);
- }
-
- private static class JCRQueryProviderAdapter implements QueryLanguageProvider<LegacyResourceProviderAdapter> {
-
- private final String[] languages;
-
- public JCRQueryProviderAdapter(String[] languages) {
- this.languages = languages;
- }
-
- @Override
- public String[] getSupportedLanguages(ResolveContext<LegacyResourceProviderAdapter> ctx) {
- return languages;
- }
-
- @Override
- public Iterator<Resource> findResources(ResolveContext<LegacyResourceProviderAdapter> ctx, String query,
- String language) {
- return ctx.getProviderState().getQueryLanguageProvider().findResources((ResolveContext) ctx, query, language);
- }
-
- @Override
- public Iterator<ValueMap> queryResources(ResolveContext<LegacyResourceProviderAdapter> ctx, String query,
- String language) {
- return ctx.getProviderState().getQueryLanguageProvider().queryResources((ResolveContext) ctx, query, language);
- }
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderWhiteboard.java b/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderWhiteboard.java
deleted file mode 100644
index 088d067..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/legacy/LegacyResourceProviderWhiteboard.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.resourceresolver.impl.legacy;
-
-import static org.apache.sling.api.resource.QueriableResourceProvider.LANGUAGES;
-import static org.apache.sling.api.resource.ResourceProvider.OWNS_ROOTS;
-import static org.apache.sling.api.resource.ResourceProvider.ROOTS;
-import static org.apache.sling.api.resource.ResourceProvider.USE_RESOURCE_ACCESS_SECURITY;
-import static org.apache.sling.api.resource.ResourceProviderFactory.PROPERTY_REQUIRED;
-import static org.apache.sling.commons.osgi.PropertiesUtil.toBoolean;
-import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_ADAPTABLE;
-import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_ATTRIBUTABLE;
-import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_AUTHENTICATE;
-import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_MODIFIABLE;
-import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_NAME;
-import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_REFRESHABLE;
-import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_ROOT;
-import static org.apache.sling.spi.resource.provider.ResourceProvider.PROPERTY_USE_RESOURCE_ACCESS_SECURITY;
-import static org.osgi.framework.Constants.SERVICE_PID;
-import static org.osgi.framework.Constants.SERVICE_RANKING;
-
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.lang.ArrayUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.References;
-import org.apache.sling.api.adapter.Adaptable;
-import org.apache.sling.api.resource.AttributableResourceProvider;
-import org.apache.sling.api.resource.ModifyingResourceProvider;
-import org.apache.sling.api.resource.RefreshableResourceProvider;
-import org.apache.sling.api.resource.ResourceProvider;
-import org.apache.sling.api.resource.ResourceProviderFactory;
-import org.apache.sling.api.resource.runtime.dto.AuthType;
-import org.apache.sling.commons.osgi.PropertiesUtil;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-@SuppressWarnings("deprecation")
-@Component(immediate = true)
-@References({
- @Reference(name = "ResourceProvider", referenceInterface = ResourceProvider.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC),
- @Reference(name = "ResourceProviderFactory", referenceInterface = ResourceProviderFactory.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC) })
-public class LegacyResourceProviderWhiteboard {
-
- public static final String ORIGINAL_SERVICE_PID = "original.service.pid";
-
- private Map<Object, List<ServiceRegistration>> registrations = new HashMap<Object, List<ServiceRegistration>>();
-
- protected void bindResourceProvider(final ServiceReference ref) {
- final BundleContext bundleContext = ref.getBundle().getBundleContext();
- final ResourceProvider provider = (ResourceProvider) bundleContext.getService(ref);
- if ( provider != null ) {
- final String[] propertyNames = ref.getPropertyKeys();
- final boolean ownsRoot = toBoolean(ref.getProperty(OWNS_ROOTS), false);
-
- final List<ServiceRegistration> newServices = new ArrayList<ServiceRegistration>();
- for (final String path : PropertiesUtil.toStringArray(ref.getProperty(ROOTS), new String[0])) {
- if ( path != null && !path.isEmpty() ) {
- final Dictionary<String, Object> newProps = new Hashtable<String, Object>();
- newProps.put(PROPERTY_AUTHENTICATE, AuthType.no.toString());
- newProps.put(PROPERTY_MODIFIABLE, provider instanceof ModifyingResourceProvider);
- newProps.put(PROPERTY_ADAPTABLE, provider instanceof Adaptable);
- newProps.put(PROPERTY_ATTRIBUTABLE, provider instanceof AttributableResourceProvider);
- newProps.put(PROPERTY_REFRESHABLE, provider instanceof RefreshableResourceProvider);
- newProps.put(PROPERTY_NAME, provider.getClass().getName());
- newProps.put(PROPERTY_ROOT, normalizePath(path));
- if (ArrayUtils.contains(propertyNames, SERVICE_PID)) {
- newProps.put(ORIGINAL_SERVICE_PID, ref.getProperty(SERVICE_PID));
- }
- if (ArrayUtils.contains(propertyNames, USE_RESOURCE_ACCESS_SECURITY)) {
- newProps.put(PROPERTY_USE_RESOURCE_ACCESS_SECURITY, ref.getProperty(USE_RESOURCE_ACCESS_SECURITY));
- }
- if (ArrayUtils.contains(propertyNames, SERVICE_RANKING)) {
- newProps.put(SERVICE_RANKING, ref.getProperty(SERVICE_RANKING));
- }
-
- String[] languages = PropertiesUtil.toStringArray(ref.getProperty(LANGUAGES), new String[0]);
- ServiceRegistration reg = bundleContext.registerService(
- org.apache.sling.spi.resource.provider.ResourceProvider.class.getName(),
- new LegacyResourceProviderAdapter(provider, languages, ownsRoot), newProps);
- newServices.add(reg);
- }
- }
- registrations.put(provider, newServices);
- }
- }
-
- protected void unbindResourceProvider(final ResourceProvider provider, final Map<String, Object> props) {
- for (ServiceRegistration r : registrations.remove(provider)) {
- r.unregister();
- }
- }
-
- protected void bindResourceProviderFactory(final ServiceReference ref) {
- final BundleContext bundleContext = ref.getBundle().getBundleContext();
- final ResourceProviderFactory factory = (ResourceProviderFactory) bundleContext.getService(ref);
- if ( factory != null ) {
- final String[] propertyNames = ref.getPropertyKeys();
- final boolean ownsRoot = toBoolean(ref.getProperty(OWNS_ROOTS), false);
-
- final List<ServiceRegistration> newServices = new ArrayList<ServiceRegistration>();
- for (final String path : PropertiesUtil.toStringArray(ref.getProperty(ROOTS), new String[0])) {
- if ( path != null && !path.isEmpty() ) {
- final Dictionary<String, Object> newProps = new Hashtable<String, Object>();
- if (PropertiesUtil.toBoolean(ref.getProperty(PROPERTY_REQUIRED), false)) {
- newProps.put(PROPERTY_AUTHENTICATE, AuthType.required.toString());
- } else {
- newProps.put(PROPERTY_AUTHENTICATE, AuthType.lazy.toString());
- }
- newProps.put(PROPERTY_MODIFIABLE, true);
- newProps.put(PROPERTY_ADAPTABLE, true);
- newProps.put(PROPERTY_ATTRIBUTABLE, true);
- newProps.put(PROPERTY_REFRESHABLE, true);
- newProps.put(PROPERTY_NAME, factory.getClass().getName());
- newProps.put(PROPERTY_ROOT, normalizePath(path));
- if (ArrayUtils.contains(propertyNames, SERVICE_PID)) {
- newProps.put(ORIGINAL_SERVICE_PID, ref.getProperty(SERVICE_PID));
- }
- if (ArrayUtils.contains(propertyNames, USE_RESOURCE_ACCESS_SECURITY)) {
- newProps.put(PROPERTY_USE_RESOURCE_ACCESS_SECURITY, ref.getProperty(USE_RESOURCE_ACCESS_SECURITY));
- }
- if (ArrayUtils.contains(propertyNames, SERVICE_RANKING)) {
- newProps.put(SERVICE_RANKING, ref.getProperty(SERVICE_RANKING));
- }
- String[] languages = PropertiesUtil.toStringArray(ref.getProperty(LANGUAGES), new String[0]);
- ServiceRegistration reg = bundleContext.registerService(
- org.apache.sling.spi.resource.provider.ResourceProvider.class.getName(),
- new LegacyResourceProviderFactoryAdapter(factory, languages, ownsRoot), newProps);
- newServices.add(reg);
- }
- }
- registrations.put(factory, newServices);
- }
- }
-
- protected void unbindResourceProviderFactory(final ResourceProviderFactory factory,
- final Map<String, Object> props) {
- for (ServiceRegistration r : registrations.remove(factory)) {
- r.unregister();
- }
- }
-
- private static String normalizePath(final String path) {
- String result = path;
- result = StringUtils.removeEnd(path, "/");
- if (result != null && !result.startsWith("/")) {
- result = "/" + result;
- }
- return result;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/BloomFilterUtils.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/BloomFilterUtils.java
deleted file mode 100644
index a947a2c..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/BloomFilterUtils.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.resourceresolver.impl.mapping;
-
-/**
- * Bloom filter utilities.
- */
-public class BloomFilterUtils {
-
- /**
- * The number of bits needed per stored element.
- * Using the formula m = - (n * ln(p)) / (ln(2)^2) as described in
- * http://en.wikipedia.org/wiki/Bloom_filter
- * (simplified, as we used a fixed K: 2).
- */
- private static final double BIT_FACTOR = -Math.log(0.02) / Math.pow(Math.log(2), 2);
-
- /**
- * Create a bloom filter array for the given number of elements.
- *
- * @param elementCount the number of entries
- * @param maxBytes the maximum number of bytes
- * @return the empty bloom filter
- */
- public static byte[] createFilter(int elementCount, int maxBytes) {
- int bits = (int) (elementCount * BIT_FACTOR) + 7;
- return new byte[Math.min(maxBytes, bits / 8)];
- }
-
- /**
- * Add the key.
- *
- * @param bloom the bloom filter
- * @param key the key
- */
- public static void add(byte[] bloom, Object key) {
- int len = bloom.length;
- if (len > 0) {
- int h1 = hash(key.hashCode()), h2 = hash(h1);
- bloom[(h1 >>> 3) % len] |= 1 << (h1 & 7);
- bloom[(h2 >>> 3) % len] |= 1 << (h2 & 7);
- }
- }
-
- /**
- * Remove the key.
- *
- * @param bloom the bloom filter
- * @param key the key
- */
- public static void remove(byte[] bloom, Object key){
- throw new UnsupportedOperationException();
- }
-
- /**
- * Check whether the given key is probably in the set. This method never
- * returns false if the key is in the set, but possibly returns true even if
- * it isn't.
- *
- * @param bloom the bloom filter
- * @param key the key
- * @return true if the given key is probably in the set
- */
- public static boolean probablyContains(byte[] bloom, Object key) {
- int len = bloom.length;
- if (len == 0) {
- return true;
- }
- int h1 = hash(key.hashCode());
- long x = bloom[(h1 >>> 3) % len] & (1 << (h1 & 7));
- if (x != 0) {
- int h2 = hash(h1);
- x = bloom[(h2 >>> 3) % len] & (1 << (h2 & 7));
- }
- return x != 0;
- }
-
- /**
- * Get the hash value for the given key. The returned hash value is
- * stretched so that it should work well even for relatively bad hashCode
- * implementations.
- *
- * @param key the key
- * @return the hash value
- */
- private static int hash(int key) {
- int hash = key;
- // a supplemental secondary hash function
- // to protect against hash codes that don't differ much
- hash = ((hash >>> 16) ^ hash) * 0x45d9f3b;
- hash = ((hash >>> 16) ^ hash) * 0x45d9f3b;
- hash = (hash >>> 16) ^ hash;
- return hash;
- }
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java
deleted file mode 100644
index 0dd8f70..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.resourceresolver.impl.mapping;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.sling.api.resource.ResourceResolverFactory;
-
-/**
- * Internal interface representing the additional methods
- * MapEntries needs from the ResourceResolverFactory.
- *
- * Exists primarily to facilitate mocking of the ResourceResolverFactory
- * when testing MapEntries.
- */
-public interface MapConfigurationProvider extends ResourceResolverFactory {
-
- String getMapRoot();
-
- Map<?, ?> getVirtualURLMap();
-
- Mapping[] getMappings();
-
- int getDefaultVanityPathRedirectStatus();
-
- boolean isVanityPathEnabled();
-
- long getMaxCachedVanityPathEntries();
-
- boolean isMaxCachedVanityPathEntriesStartup();
-
- int getVanityBloomFilterMaxBytes();
-
- boolean isOptimizeAliasResolutionEnabled();
-
- boolean hasVanityPathPrecedence();
-
- public class VanityPathConfig implements Comparable<VanityPathConfig> {
- public final boolean isExclude;
- public final String prefix;
-
- public VanityPathConfig(final String prefix, final boolean isExclude) {
- this.prefix = prefix;
- this.isExclude = isExclude;
- }
-
- public int compareTo(VanityPathConfig o2) {
- return new Integer(o2.prefix.length()).compareTo(this.prefix.length());
- }
- }
-
- /**
- * A list of white and black list prefixes all ending with a slash.
- * If <code>null</code> is returned, all paths are allowed.
- */
- List<VanityPathConfig> getVanityPathConfig();
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
deleted file mode 100644
index 69cc457..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
+++ /dev/null
@@ -1,1575 +0,0 @@
-/*
- * 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.resourceresolver.impl.mapping;
-
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.NoSuchElementException;
-import java.util.SortedMap;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.ReentrantLock;
-
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.sling.api.SlingConstants;
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
-import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider.VanityPathConfig;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.service.event.EventConstants;
-import org.osgi.service.event.EventHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class MapEntries implements EventHandler {
-
- public static final MapEntries EMPTY = new MapEntries();
-
- private static final String PROP_REG_EXP = "sling:match";
-
- public static final String PROP_REDIRECT_EXTERNAL = "sling:redirect";
-
- public static final String PROP_REDIRECT_EXTERNAL_STATUS = "sling:status";
-
- public static final String PROP_REDIRECT_EXTERNAL_REDIRECT_STATUS = "sling:redirectStatus";
-
- public static final String PROP_VANITY_PATH = "sling:vanityPath";
-
- public static final String PROP_VANITY_ORDER = "sling:vanityOrder";
-
- private static final String VANITY_BLOOM_FILTER_NAME = "vanityBloomFilter.txt";
-
- private static final int VANITY_BLOOM_FILTER_MAX_ENTRIES = 10000000;
-
- /** Key for the global list. */
- private static final String GLOBAL_LIST_KEY = "*";
-
- public static final String DEFAULT_MAP_ROOT = "/etc/map";
-
- public static final int DEFAULT_DEFAULT_VANITY_PATH_REDIRECT_STATUS = HttpServletResponse.SC_FOUND;
-
- private static final String JCR_SYSTEM_PREFIX = "/jcr:system/";
-
- static final String ANY_SCHEME_HOST = "[^/]+/[^/]+";
-
- /** default log */
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- private MapConfigurationProvider factory;
-
- private volatile ResourceResolver resolver;
-
- private final String mapRoot;
-
- private Map<String, List<MapEntry>> resolveMapsMap;
-
- private Collection<MapEntry> mapMaps;
-
- private Map <String,List <String>> vanityTargets;
-
- private Map<String, Map<String, String>> aliasMap;
-
- private ServiceRegistration registration;
-
- private EventAdmin eventAdmin;
-
- private final ReentrantLock initializing = new ReentrantLock();
-
- private final boolean enabledVanityPaths;
-
- private final long maxCachedVanityPathEntries;
-
- private final boolean maxCachedVanityPathEntriesStartup;
-
- private final int vanityBloomFilterMaxBytes;
-
- private final boolean enableOptimizeAliasResolution;
-
- private final boolean vanityPathPrecedence;
-
- private final List<VanityPathConfig> vanityPathConfig;
-
- private final AtomicLong vanityCounter;
-
- private final File vanityBloomFilterFile;
-
- private byte[] vanityBloomFilter;
-
- private Timer timer;
-
- private boolean updateBloomFilterFile = false;
-
- @SuppressWarnings("unchecked")
- private MapEntries() {
- this.factory = null;
- this.resolver = null;
- this.mapRoot = DEFAULT_MAP_ROOT;
-
- this.resolveMapsMap = Collections.singletonMap(GLOBAL_LIST_KEY, (List<MapEntry>)Collections.EMPTY_LIST);
- this.mapMaps = Collections.<MapEntry> emptyList();
- this.vanityTargets = Collections.<String,List <String>>emptyMap();
- this.aliasMap = Collections.<String, Map<String, String>>emptyMap();
- this.registration = null;
- this.eventAdmin = null;
- this.enabledVanityPaths = true;
- this.maxCachedVanityPathEntries = -1;
- this.maxCachedVanityPathEntriesStartup = true;
- this.vanityBloomFilterMaxBytes = 0;
- this.enableOptimizeAliasResolution = true;
- this.vanityPathConfig = null;
- this.vanityPathPrecedence = false;
- this.vanityCounter = new AtomicLong(0);
- this.vanityBloomFilterFile = null;
- }
-
- @SuppressWarnings({ "unchecked", "deprecation" })
- public MapEntries(final MapConfigurationProvider factory, final BundleContext bundleContext, final EventAdmin eventAdmin)
- throws LoginException, IOException {
- this.resolver = factory.getAdministrativeResourceResolver(null);
- this.factory = factory;
- this.mapRoot = factory.getMapRoot();
- this.enabledVanityPaths = factory.isVanityPathEnabled();
- this.maxCachedVanityPathEntries = factory.getMaxCachedVanityPathEntries();
- this.maxCachedVanityPathEntriesStartup = factory.isMaxCachedVanityPathEntriesStartup();
- this.vanityBloomFilterMaxBytes = factory.getVanityBloomFilterMaxBytes();
- this.vanityPathConfig = factory.getVanityPathConfig();
- this.enableOptimizeAliasResolution = factory.isOptimizeAliasResolutionEnabled();
- this.vanityPathPrecedence = factory.hasVanityPathPrecedence();
- this.eventAdmin = eventAdmin;
-
- this.resolveMapsMap = Collections.singletonMap(GLOBAL_LIST_KEY, (List<MapEntry>)Collections.EMPTY_LIST);
- this.mapMaps = Collections.<MapEntry> emptyList();
- this.vanityTargets = Collections.<String,List <String>>emptyMap();
- this.aliasMap = Collections.<String, Map<String, String>>emptyMap();
-
- doInit();
-
- final Dictionary<String, String> props = new Hashtable<String, String>();
- props.put(EventConstants.EVENT_TOPIC, "org/apache/sling/api/resource/*");
- props.put(EventConstants.EVENT_FILTER, createFilter(this.enabledVanityPaths));
- props.put(Constants.SERVICE_DESCRIPTION, "Map Entries Observation");
- props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
- this.registration = bundleContext.registerService(EventHandler.class.getName(), this, props);
-
- this.vanityCounter = new AtomicLong(0);
- this.vanityBloomFilterFile = bundleContext.getDataFile(VANITY_BLOOM_FILTER_NAME);
- initializeVanityPaths();
- }
-
- /**
- * Actual initializer. Guards itself against concurrent use by using a
- * ReentrantLock. Does nothing if the resource resolver has already been
- * null-ed.
- */
- protected void doInit() {
-
- this.initializing.lock();
- try {
- final ResourceResolver resolver = this.resolver;
- final MapConfigurationProvider factory = this.factory;
- if (resolver == null || factory == null) {
- return;
- }
-
- final Map<String, List<MapEntry>> newResolveMapsMap = new ConcurrentHashMap<String, List<MapEntry>>();
-
- //optimization made in SLING-2521
- if (enableOptimizeAliasResolution){
- final Map<String, Map<String, String>> aliasMap = this.loadAliases(resolver);
- this.aliasMap = aliasMap;
- }
-
- this.resolveMapsMap = newResolveMapsMap;
-
- doUpdateConfiguration();
-
- sendChangeEvent();
- } catch (final Exception e) {
-
- log.warn("doInit: Unexpected problem during initialization", e);
-
- } finally {
-
- this.initializing.unlock();
-
- }
- }
-
- /**
- * Actual vanity paths initializer. Guards itself against concurrent use by
- * using a ReentrantLock. Does nothing if the resource resolver has already
- * been null-ed.
- *
- * @throws IOException
- */
- protected void initializeVanityPaths() throws IOException {
- this.initializing.lock();
- try {
- if (this.enabledVanityPaths) {
-
- if (vanityBloomFilterFile == null) {
- throw new RuntimeException(
- "This platform does not have file system support");
- }
- boolean createVanityBloomFilter = false;
- if (!vanityBloomFilterFile.exists()) {
- log.debug("creating bloom filter file {}",
- vanityBloomFilterFile.getAbsolutePath());
- vanityBloomFilter = createVanityBloomFilter();
- persistBloomFilter();
- createVanityBloomFilter = true;
- } else {
- // initialize bloom filter from disk
- vanityBloomFilter = new byte[(int) vanityBloomFilterFile
- .length()];
- DataInputStream dis = new DataInputStream(
- new FileInputStream(vanityBloomFilterFile));
- try {
- dis.readFully(vanityBloomFilter);
- } finally {
- dis.close();
- }
- }
-
- // task for persisting the bloom filter every minute (if changes
- // exist)
- timer = new Timer();
- timer.schedule(new BloomFilterTask(), 60 * 1000);
-
- final Map<String, List<String>> vanityTargets = this
- .loadVanityPaths(createVanityBloomFilter);
- this.vanityTargets = vanityTargets;
- }
- } finally {
- this.initializing.unlock();
- }
-
- }
-
- private boolean doNodeAdded(String path, boolean refreshed) {
- this.initializing.lock();
- boolean newRefreshed = refreshed;
- if (!newRefreshed) {
- resolver.refresh();
- newRefreshed = true;
- }
- try {
- Resource resource = resolver.getResource(path);
- if (resource != null) {
- final ValueMap props = resource.adaptTo(ValueMap.class);
- if (props.containsKey(PROP_VANITY_PATH)) {
- doAddVanity(path);
- }
- if (props.containsKey(ResourceResolverImpl.PROP_ALIAS)) {
- doAddAlias(path);
- }
- if (path.startsWith(this.mapRoot)) {
- doUpdateConfiguration();
- }
- }
- sendChangeEvent();
-
- } finally {
- this.initializing.unlock();
- }
- return newRefreshed;
- }
-
- private boolean doAddAttributes(String path, String[] addedAttributes, boolean refreshed) {
- this.initializing.lock();
- boolean newRefreshed = refreshed;
- if (!newRefreshed) {
- resolver.refresh();
- newRefreshed = true;
- }
- try {
- for (String changedAttribute:addedAttributes){
- if (PROP_VANITY_PATH.equals(changedAttribute)) {
- doAddVanity(path);
- } else if (PROP_VANITY_ORDER.equals(changedAttribute)) {
- doUpdateVanityOrder(path, false);
- } else if (PROP_REDIRECT_EXTERNAL.equals(changedAttribute)
- || PROP_REDIRECT_EXTERNAL_REDIRECT_STATUS.equals(changedAttribute)) {
- doUpdateRedirectStatus(path);
- } else if (ResourceResolverImpl.PROP_ALIAS.equals(changedAttribute)) {
- if (enableOptimizeAliasResolution) {
- doAddAlias(path);
- }
- }
- }
- if (path.startsWith(this.mapRoot)) {
- doUpdateConfiguration();
- }
- sendChangeEvent();
- } finally {
- this.initializing.unlock();
- }
- return newRefreshed;
- }
-
- private boolean doUpdateAttributes(String path, String[] changedAttributes, boolean refreshed) {
- this.initializing.lock();
- boolean newRefreshed = refreshed;
- if (!newRefreshed) {
- resolver.refresh();
- newRefreshed = true;
- }
- try {
- for (String changedAttribute:changedAttributes){
- if (PROP_VANITY_PATH.equals(changedAttribute)) {
- doUpdateVanity(path);
- } else if (PROP_VANITY_ORDER.equals(changedAttribute)) {
- doUpdateVanityOrder(path, false);
- } else if (PROP_REDIRECT_EXTERNAL.equals(changedAttribute)
- || PROP_REDIRECT_EXTERNAL_REDIRECT_STATUS.equals(changedAttribute)) {
- doUpdateRedirectStatus(path);
- } else if (ResourceResolverImpl.PROP_ALIAS.equals(changedAttribute)) {
- if (enableOptimizeAliasResolution) {
- doRemoveAlias(path, false);
- doAddAlias(path);
- doUpdateAlias(path, false);
- }
- }
- }
- if (path.startsWith(this.mapRoot)) {
- doUpdateConfiguration();
- }
- sendChangeEvent();
- } finally {
- this.initializing.unlock();
- }
- return newRefreshed;
- }
-
- private boolean doRemoveAttributes(String path, String[] removedAttributes, boolean nodeDeletion, boolean refreshed) {
- this.initializing.lock();
- boolean newRefreshed = refreshed;
- if (!newRefreshed) {
- resolver.refresh();
- newRefreshed = true;
- }
- try {
- for (String changedAttribute:removedAttributes){
- if (PROP_VANITY_PATH.equals(changedAttribute)){
- doRemoveVanity(path);
- } else if (PROP_VANITY_ORDER.equals(changedAttribute)) {
- doUpdateVanityOrder(path, true);
- } else if (PROP_REDIRECT_EXTERNAL.equals(changedAttribute)
- || PROP_REDIRECT_EXTERNAL_REDIRECT_STATUS.equals(changedAttribute)) {
- doUpdateRedirectStatus(path);
- } else if (ResourceResolverImpl.PROP_ALIAS.equals(changedAttribute)) {
- if (enableOptimizeAliasResolution) {
- doRemoveAlias(path, nodeDeletion);
- doUpdateAlias(path, nodeDeletion);
- }
- }
- }
- if (path.startsWith(this.mapRoot)) {
- doUpdateConfiguration();
- }
- sendChangeEvent();
- } finally {
- this.initializing.unlock();
- }
- return newRefreshed;
- }
-
- private boolean doUpdateConfiguration(boolean refreshed){
- this.initializing.lock();
- boolean newRefreshed = refreshed;
- if (!newRefreshed) {
- resolver.refresh();
- newRefreshed = true;
- }
- try {
- doUpdateConfiguration();
- sendChangeEvent();
- } finally {
- this.initializing.unlock();
- }
- return newRefreshed;
- }
-
- private void doUpdateConfiguration(){
- final List<MapEntry> globalResolveMap = new ArrayList<MapEntry>();
- final SortedMap<String, MapEntry> newMapMaps = new TreeMap<String, MapEntry>();
- // load the /etc/map entries into the maps
- loadResolverMap(resolver, globalResolveMap, newMapMaps);
- // load the configuration into the resolver map
- loadConfiguration(factory, globalResolveMap);
- // load the configuration into the mapper map
- loadMapConfiguration(factory, newMapMaps);
- // sort global list and add to map
- Collections.sort(globalResolveMap);
- resolveMapsMap.put(GLOBAL_LIST_KEY, globalResolveMap);
- this.mapMaps = Collections.unmodifiableSet(new TreeSet<MapEntry>(newMapMaps.values()));
- }
-
- private void doAddVanity(String path) {
- Resource resource = resolver.getResource(path);
- if (isAllVanityPathEntriesCached() || vanityCounter.longValue() < maxCachedVanityPathEntries) {
- // fill up the cache and the bloom filter
- loadVanityPath(resource, resolveMapsMap, vanityTargets, true, true);
- } else {
- // fill up the bloom filter
- loadVanityPath(resource, resolveMapsMap, vanityTargets, false, true);
- }
- updateBloomFilterFile = true;
- }
-
- private void doUpdateVanity(String path) {
- doRemoveVanity(path);
- doAddVanity(path);
- }
-
- private void doRemoveVanity(String path) {
- String actualContentPath = getActualContentPath(path);
- List <String> l = vanityTargets.get(actualContentPath);
- if (l != null){
- for (String s : l){
- List<MapEntry> entries = this.resolveMapsMap.get(s);
- if (entries!= null) {
- for (Iterator<MapEntry> iterator =entries.iterator(); iterator.hasNext(); ) {
- MapEntry entry = iterator.next();
- String redirect = getMapEntryRedirect(entry);
- if (redirect != null && redirect.equals(actualContentPath)) {
- iterator.remove();
- }
- }
- }
- if (entries!= null && entries.isEmpty()) {
- this.resolveMapsMap.remove(s);
- }
- }
- }
- vanityTargets.remove(actualContentPath);
- if (vanityCounter.longValue() > 0) {
- vanityCounter.addAndGet(-2);
- }
- }
-
- private void doUpdateVanityOrder(String path, boolean deletion) {
- Resource resource = resolver.getResource(path);
- final ValueMap props = resource.adaptTo(ValueMap.class);
-
- long vanityOrder;
- if (deletion) {
- vanityOrder = 0;
- } else {
- vanityOrder = props.get(PROP_VANITY_ORDER, Long.class);
- }
-
- String actualContentPath = getActualContentPath(path);
- List<String> vanityPaths = vanityTargets.get(actualContentPath);
- if (vanityPaths != null) {
- boolean updatedOrder = false;
- for (String vanityTarget : vanityPaths) {
- List<MapEntry> entries = this.resolveMapsMap.get(vanityTarget);
- for (MapEntry entry : entries) {
- String redirect = getMapEntryRedirect(entry);
- if (redirect != null && redirect.equals(actualContentPath)) {
- entry.setOrder(vanityOrder);
- updatedOrder = true;
- }
- }
- if (updatedOrder) {
- Collections.sort(entries);
- }
- }
- }
- }
-
- private void doUpdateRedirectStatus(String path) {
- String actualContentPath = getActualContentPath(path);
- List<String> vanityPaths = vanityTargets.get(actualContentPath);
- if (vanityPaths != null) {
- doUpdateVanity(path);
- }
- }
-
- private void doAddAlias(String path) {
- Resource resource = resolver.getResource(path);
- loadAlias(resource, this.aliasMap);
- }
-
- private void doUpdateAlias(String path, boolean nodeDeletion) {
- if (nodeDeletion){
- if (path.endsWith("/jcr:content")) {
- path = path.substring(0, path.length() - "/jcr:content".length());
- final Resource resource = resolver.getResource(path);
- if (resource != null) {
- path = resource.getPath();
- final ValueMap props = resource.adaptTo(ValueMap.class);
- if (props.get(ResourceResolverImpl.PROP_ALIAS, String[].class) != null) {
- doAddAlias(path);
- }
- }
- }
- } else {
- final Resource resource = resolver.getResource(path);
- if (resource != null) {
- if (resource.getName().equals("jcr:content")) {
- final Resource parent = resource.getParent();
- path = parent.getPath();
- final ValueMap props = parent.adaptTo(ValueMap.class);
- if (props.get(ResourceResolverImpl.PROP_ALIAS, String[].class) != null) {
- doAddAlias(path);
- }
- } else if (resource.getChild("jcr:content") != null) {
- Resource jcrContent = resource.getChild("jcr:content");
- path = jcrContent.getPath();
- final ValueMap props = jcrContent.adaptTo(ValueMap.class);
- if (props.get(ResourceResolverImpl.PROP_ALIAS, String[].class) != null) {
- doAddAlias(path);
- }
- }
- }
- }
- }
-
- private void doRemoveAlias(String path, boolean nodeDeletion) {
- String resourceName = null;
- if (nodeDeletion) {
- if (!"/".equals(path)){
- if (path.endsWith("/jcr:content")) {
- path = path.substring(0, path.length() - "/jcr:content".length());
- }
- resourceName = path.substring(path.lastIndexOf("/") + 1);
- path = ResourceUtil.getParent(path);
- } else {
- resourceName = "";
- }
- } else {
- final Resource resource = resolver.getResource(path);
- if (resource.getName().equals("jcr:content")) {
- final Resource containingResource = resource.getParent();
- path = containingResource.getParent().getPath();
- resourceName = containingResource.getName();
- } else {
- path = resource.getParent().getPath();
- resourceName = resource.getName();
- }
- }
- Map<String, String> aliasMapEntry = aliasMap.get(path);
- if (aliasMapEntry != null) {
- for (Iterator<String> iterator =aliasMapEntry.keySet().iterator(); iterator.hasNext(); ) {
- String key = iterator.next();
- if (resourceName.equals(aliasMapEntry.get(key))){
- iterator.remove();
- }
- }
- }
- if (aliasMapEntry != null && aliasMapEntry.isEmpty()) {
- this.aliasMap.remove(path);
- }
- }
-
- public boolean isOptimizeAliasResolutionEnabled() {
- return this.enableOptimizeAliasResolution;
- }
-
- /**
- * Cleans up this class.
- */
- public void dispose() {
- try {
- persistBloomFilter();
- } catch (IOException e) {
- log.error("Error while saving bloom filter to disk", e);
- }
-
- if (this.registration != null) {
- this.registration.unregister();
- this.registration = null;
- }
-
- /*
- * Cooperation with doInit: The same lock as used by doInit is acquired
- * thus preventing doInit from running and waiting for a concurrent
- * doInit to terminate. Once the lock has been acquired, the resource
- * resolver is null-ed (thus causing the init to terminate when
- * triggered the right after and prevent the doInit method from doing
- * any thing).
- */
-
- // wait at most 10 seconds for a notifcation during initialization
- boolean initLocked;
- try {
- initLocked = this.initializing.tryLock(10, TimeUnit.SECONDS);
- } catch (final InterruptedException ie) {
- initLocked = false;
- }
-
- try {
- if (!initLocked) {
- log.warn("dispose: Could not acquire initialization lock within 10 seconds; ongoing intialization may fail");
- }
-
- // immediately set the resolver field to null to indicate
- // that we have been disposed (this also signals to the
- // event handler to stop working
- final ResourceResolver oldResolver = this.resolver;
- this.resolver = null;
-
- if (oldResolver != null) {
- oldResolver.close();
- } else {
- log.warn("dispose: ResourceResolver has already been cleared before; duplicate call to dispose ?");
- }
- } finally {
- if (initLocked) {
- this.initializing.unlock();
- }
- }
-
- // clear the rest of the fields
- this.factory = null;
- this.eventAdmin = null;
- }
-
- /**
- * This is for the web console plugin
- */
- public List<MapEntry> getResolveMaps() {
- final List<MapEntry> entries = new ArrayList<MapEntry>();
- for (final List<MapEntry> list : this.resolveMapsMap.values()) {
- entries.addAll(list);
- }
- Collections.sort(entries);
- return Collections.unmodifiableList(entries);
- }
-
- /**
- * Calculate the resolve maps. As the entries have to be sorted by pattern
- * length, we have to create a new list containing all relevant entries.
- */
- public Iterator<MapEntry> getResolveMapsIterator(final String requestPath) {
- String key = null;
- final int firstIndex = requestPath.indexOf('/');
- final int secondIndex = requestPath.indexOf('/', firstIndex + 1);
- if (secondIndex != -1) {
- key = requestPath.substring(secondIndex);
- }
-
- return new MapEntryIterator(key, resolveMapsMap, vanityPathPrecedence);
- }
-
- public Collection<MapEntry> getMapMaps() {
- return mapMaps;
- }
-
- public Map<String, String> getAliasMap(final String parentPath) {
- return aliasMap.get(parentPath);
- }
-
- /**
- * get the MapEnty containing all the nodes having a specific vanityPath
- */
- private List<MapEntry> getMapEntryList(String vanityPath){
- List<MapEntry> mapEntries = null;
-
- if (BloomFilterUtils.probablyContains(vanityBloomFilter, vanityPath)) {
- mapEntries = this.resolveMapsMap.get(vanityPath);
- if (mapEntries == null) {
- Map<String, List<MapEntry>> mapEntry = getVanityPaths(vanityPath);
- mapEntries = mapEntry.get(vanityPath);
- }
- }
-
- return mapEntries;
- }
-
- // ---------- EventListener interface
-
- /**
- * Handles the change to any of the node properties relevant for vanity URL
- * mappings. The {@link #MapEntries(ResourceResolverFactoryImpl, BundleContext, EventAdmin)}
- * constructor makes sure the event listener is registered to only get
- * appropriate events.
- */
- public void handleEvent(final Event event) {
-
- // check for path (used for some tests below
- final Object p = event.getProperty(SlingConstants.PROPERTY_PATH);
- final String path;
- if (p instanceof String) {
- path = (String) p;
- log.debug("handleEvent, topic={}, path={}", event.getTopic(), path);
- } else {
- log.debug("handleEvent, topic={}, no path provided, event ignored", event.getTopic());
- return;
- }
-
- // don't care for system area
- if (path.startsWith(JCR_SYSTEM_PREFIX)) {
- return;
- }
-
- boolean wasResolverRefreshed = false;
-
- //removal of a node is handled differently
- if (SlingConstants.TOPIC_RESOURCE_REMOVED.equals(event.getTopic())) {
- final String actualContentPath = getActualContentPath(path);
- for (final String target : this.vanityTargets.keySet()) {
- if (target.startsWith(actualContentPath)) {
- wasResolverRefreshed = doRemoveAttributes(path, new String [] {PROP_VANITY_PATH}, true, wasResolverRefreshed);
- }
- }
- for (final String target : this.aliasMap.keySet()) {
- if (actualContentPath.startsWith(target)) {
- wasResolverRefreshed = doRemoveAttributes(path, new String [] {ResourceResolverImpl.PROP_ALIAS}, true, wasResolverRefreshed);
- }
- }
- if (path.startsWith(this.mapRoot)) {
- //need to update the configuration
- wasResolverRefreshed = doUpdateConfiguration(wasResolverRefreshed);
- }
- //session.move() is handled differently see also SLING-3713 and
- } else if (SlingConstants.TOPIC_RESOURCE_ADDED.equals(event.getTopic()) && event.getProperty(SlingConstants.PROPERTY_ADDED_ATTRIBUTES) == null) {
- wasResolverRefreshed = doNodeAdded(path, wasResolverRefreshed);
- } else {
- String [] addedAttributes = (String []) event.getProperty(SlingConstants.PROPERTY_ADDED_ATTRIBUTES);
- if (addedAttributes != null) {
- if (log.isDebugEnabled()) {
- log.debug("found added attributes {}", addedAttributes);
- }
- wasResolverRefreshed = doAddAttributes(path, addedAttributes, wasResolverRefreshed);
- }
-
- String [] changedAttributes = (String []) event.getProperty(SlingConstants.PROPERTY_CHANGED_ATTRIBUTES);
- if (changedAttributes != null) {
- if (log.isDebugEnabled()) {
- log.debug("found changed attributes {}", changedAttributes);
- }
- wasResolverRefreshed = doUpdateAttributes(path, changedAttributes, wasResolverRefreshed);
- }
-
- String [] removedAttributes = (String []) event.getProperty(SlingConstants.PROPERTY_REMOVED_ATTRIBUTES);
- if (removedAttributes != null) {
- if (log.isDebugEnabled()) {
- log.debug("found removed attributes {}", removedAttributes);
- }
- wasResolverRefreshed = doRemoveAttributes(path, removedAttributes, false, wasResolverRefreshed);
- }
- }
- }
-
- // ---------- internal
-
- private byte[] createVanityBloomFilter() throws IOException {
- byte bloomFilter[] = null;
- if (vanityBloomFilter == null) {
- bloomFilter = BloomFilterUtils.createFilter(VANITY_BLOOM_FILTER_MAX_ENTRIES, this.vanityBloomFilterMaxBytes);
- }
- return bloomFilter;
- }
-
- private void persistBloomFilter() throws IOException {
- if (vanityBloomFilterFile != null && vanityBloomFilter != null) {
- FileOutputStream out = new FileOutputStream(vanityBloomFilterFile);
- try {
- out.write(this.vanityBloomFilter);
- } finally {
- out.close();
- }
- }
- }
-
- private boolean isAllVanityPathEntriesCached() {
- return maxCachedVanityPathEntries == -1;
- }
-
- /**
- * Escapes illegal XPath search characters at the end of a string.
- * <p>
- * Example:<br>
- * A search string like 'test?' will run into a ParseException documented in
- * http://issues.apache.org/jira/browse/JCR-1248
- *
- * @param s
- * the string to encode
- * @return the escaped string
- */
- private static String escapeIllegalXpathSearchChars(String s) {
- StringBuilder sb = new StringBuilder();
- if (s != null && s.length() > 1) {
- sb.append(s.substring(0, (s.length() - 1)));
- char c = s.charAt(s.length() - 1);
- // NOTE: keep this in sync with _ESCAPED_CHAR below!
- if (c == '!' || c == '(' || c == ':' || c == '^' || c == '['
- || c == ']' || c == '{' || c == '}' || c == '?') {
- sb.append('\\');
- }
- sb.append(c);
- }
- return sb.toString();
- }
-
- /**
- * get the vanity paths Search for all nodes having a specific vanityPath
- */
- @SuppressWarnings("deprecation")
- private Map<String, List<MapEntry>> getVanityPaths(String vanityPath) {
-
- Map<String, List<MapEntry>> entryMap = new HashMap<String, List<MapEntry>>();
-
- // sling:VanityPath (uppercase V) is the mixin name
- // sling:vanityPath (lowercase) is the property name
- final String queryString = "SELECT sling:vanityPath, sling:redirect, sling:redirectStatus FROM sling:VanityPath WHERE sling:vanityPath ="
- + "'"+escapeIllegalXpathSearchChars(vanityPath).replaceAll("'", "''")+"' OR sling:vanityPath ="+ "'"+escapeIllegalXpathSearchChars(vanityPath.substring(1)).replaceAll("'", "''")+"' ORDER BY sling:vanityOrder DESC";
-
- ResourceResolver queryResolver = null;
-
- try {
- queryResolver = factory.getAdministrativeResourceResolver(null);
- final Iterator<Resource> i = queryResolver.findResources(queryString, "sql");
- while (i.hasNext()) {
- final Resource resource = i.next();
- if (maxCachedVanityPathEntriesStartup || vanityCounter.longValue() < maxCachedVanityPathEntries) {
- loadVanityPath(resource, resolveMapsMap, vanityTargets, true, false);
- entryMap = resolveMapsMap;
- } else {
- final Map <String, List<String>> targetPaths = new HashMap <String, List<String>>();
- loadVanityPath(resource, entryMap, targetPaths, true, false);
- }
- }
- } catch (LoginException e) {
- log.error("Exception while obtaining queryResolver", e);
- } finally {
- if (queryResolver != null) {
- queryResolver.close();
- }
- }
- return entryMap;
- }
-
- private boolean isValidVanityPath(Resource resource){
- // ignore system tree
- if (resource.getPath().startsWith(JCR_SYSTEM_PREFIX)) {
- log.debug("isValidVanityPath: not valid {}", resource);
- return false;
- }
-
- // check white list
- if ( this.vanityPathConfig != null ) {
- boolean allowed = false;
- for(final VanityPathConfig config : this.vanityPathConfig) {
- if ( resource.getPath().startsWith(config.prefix) ) {
- allowed = !config.isExclude;
- break;
- }
- }
- if ( !allowed ) {
- log.debug("isValidVanityPath: not valid as not in white list {}", resource);
- return false;
- }
- }
- // require properties
- final ValueMap props = resource.adaptTo(ValueMap.class);
- if (props == null) {
- log.debug("isValidVanityPath: not valid {} without properties", resource);
- return false;
- }
- return true;
- }
-
- private String getActualContentPath(String path){
- final String checkPath;
- if ( path.endsWith("/jcr:content") ) {
- checkPath = path.substring(0, path.length() - "/jcr:content".length());
- } else {
- checkPath = path;
- }
- return checkPath;
- }
-
- private String getMapEntryRedirect(MapEntry mapEntry) {
- String[] redirect = mapEntry.getRedirect();
- if (redirect.length > 1) {
- log.warn("something went wrong, please restart the bundle");
- return null;
- }
-
- String path = redirect[0];
- if (path.endsWith("$1")) {
- path = path.substring(0, path.length() - "$1".length());
- } else if (path.endsWith(".html")) {
- path = path.substring(0, path.length() - ".html".length());
- }
-
- return path;
- }
-
- /**
- * Send an OSGi event
- */
- private void sendChangeEvent() {
- if (this.eventAdmin != null) {
- final Event event = new Event(SlingConstants.TOPIC_RESOURCE_RESOLVER_MAPPING_CHANGED,
- (Dictionary<?, ?>) null);
- this.eventAdmin.postEvent(event);
- }
- }
-
- private void loadResolverMap(final ResourceResolver resolver, final List<MapEntry> entries, final Map<String, MapEntry> mapEntries) {
- // the standard map configuration
- final Resource res = resolver.getResource(mapRoot);
- if (res != null) {
- gather(resolver, entries, mapEntries, res, "");
- }
- }
-
- private void gather(final ResourceResolver resolver, final List<MapEntry> entries, final Map<String, MapEntry> mapEntries,
- final Resource parent, final String parentPath) {
- // scheme list
- final Iterator<Resource> children = parent.listChildren();
- while (children.hasNext()) {
- final Resource child = children.next();
- final ValueMap vm = ResourceUtil.getValueMap(child);
-
- String name = vm.get(PROP_REG_EXP, String.class);
- boolean trailingSlash = false;
- if (name == null) {
- name = child.getName().concat("/");
- trailingSlash = true;
- }
-
- final String childPath = parentPath.concat(name);
-
- // gather the children of this entry (only if child is not end
- // hooked)
- if (!childPath.endsWith("$")) {
-
- // add trailing slash to child path to append the child
- String childParent = childPath;
- if (!trailingSlash) {
- childParent = childParent.concat("/");
- }
-
- gather(resolver, entries, mapEntries, child, childParent);
- }
-
- // add resolution entries for this node
- MapEntry childResolveEntry = null;
- try{
- childResolveEntry=MapEntry.createResolveEntry(childPath, child, trailingSlash);
- }catch (IllegalArgumentException iae){
- //ignore this entry
- log.debug("ignored entry due exception ",iae);
- }
- if (childResolveEntry != null) {
- entries.add(childResolveEntry);
- }
-
- // add map entries for this node
- final List<MapEntry> childMapEntries = MapEntry.createMapEntry(childPath, child, trailingSlash);
- if (childMapEntries != null) {
- for (final MapEntry mapEntry : childMapEntries) {
- addMapEntry(mapEntries, mapEntry.getPattern(), mapEntry.getRedirect()[0], mapEntry.getStatus());
- }
- }
-
- }
- }
-
- /**
- * Add an entry to the resolve map.
- */
- private boolean addEntry(final Map<String, List<MapEntry>> entryMap, final String key, final MapEntry entry) {
-
- if (entry==null){
- return false;
- }
-
- List<MapEntry> entries = entryMap.get(key);
- if (entries == null) {
- entries = new ArrayList<MapEntry>();
- entries.add(entry);
- // and finally sort list
- Collections.sort(entries);
- entryMap.put(key, entries);
- } else {
- List<MapEntry> entriesCopy =new ArrayList<MapEntry>(entries);
- entriesCopy.add(entry);
- // and finally sort list
- Collections.sort( entriesCopy);
- entryMap.put(key, entriesCopy);
- }
- return true;
- }
-
- /**
- * Load aliases Search for all nodes inheriting the sling:alias
- * property
- */
- private Map<String, Map<String, String>> loadAliases(final ResourceResolver resolver) {
- final Map<String, Map<String, String>> map = new ConcurrentHashMap<String, Map<String, String>>();
- final String queryString = "SELECT sling:alias FROM nt:base WHERE sling:alias IS NOT NULL";
- final Iterator<Resource> i = resolver.findResources(queryString, "sql");
- while (i.hasNext()) {
- final Resource resource = i.next();
- loadAlias(resource, map);
- }
- return map;
- }
-
- /**
- * Load alias given a resource
- */
- private void loadAlias(final Resource resource, Map<String, Map<String, String>> map) {
- // ignore system tree
- if (resource.getPath().startsWith(JCR_SYSTEM_PREFIX)) {
- log.debug("loadAliases: Ignoring {}", resource);
- return;
- }
-
- // require properties
- final ValueMap props = resource.adaptTo(ValueMap.class);
- if (props == null) {
- log.debug("loadAliases: Ignoring {} without properties", resource);
- return;
- }
-
- final String resourceName;
- final String parentPath;
- if (resource.getName().equals("jcr:content")) {
- final Resource containingResource = resource.getParent();
- parentPath = containingResource.getParent().getPath();
- resourceName = containingResource.getName();
- } else {
- parentPath = resource.getParent().getPath();
- resourceName = resource.getName();
- }
- Map<String, String> parentMap = map.get(parentPath);
- for (final String alias : props.get(ResourceResolverImpl.PROP_ALIAS, String[].class)) {
- if (parentMap != null && parentMap.containsKey(alias)) {
- log.warn("Encountered duplicate alias {} under parent path {}. Refusing to replace current target {} with {}.", new Object[] {
- alias,
- parentPath,
- parentMap.get(alias),
- resourceName
- });
- } else {
- // check alias
- boolean invalid = alias.equals("..") || alias.equals(".");
- if ( !invalid ) {
- for(final char c : alias.toCharArray()) {
- // invalid if / or # or a ?
- if ( c == '/' || c == '#' || c == '?' ) {
- invalid = true;
- break;
- }
- }
- }
- if ( invalid ) {
- log.warn("Encountered invalid alias {} under parent path {}. Refusing to use it.",
- alias, parentPath);
- } else {
- if (parentMap == null) {
- parentMap = new LinkedHashMap<String, String>();
- map.put(parentPath, parentMap);
- }
- parentMap.put(alias, resourceName);
- }
- }
- }
- }
-
- /**
- * Load vanity paths Search for all nodes inheriting the sling:VanityPath
- * mixin
- */
- private Map <String, List<String>> loadVanityPaths(boolean createVanityBloomFilter) {
- // sling:VanityPath (uppercase V) is the mixin name
- // sling:vanityPath (lowercase) is the property name
- final Map <String, List<String>> targetPaths = new ConcurrentHashMap <String, List<String>>();
- final String queryString = "SELECT sling:vanityPath, sling:redirect, sling:redirectStatus FROM sling:VanityPath WHERE sling:vanityPath IS NOT NULL";
- final Iterator<Resource> i = resolver.findResources(queryString, "sql");
-
- while (i.hasNext() && (createVanityBloomFilter || isAllVanityPathEntriesCached() || vanityCounter.longValue() < maxCachedVanityPathEntries)) {
- final Resource resource = i.next();
- if (isAllVanityPathEntriesCached() || vanityCounter.longValue() < maxCachedVanityPathEntries) {
- // fill up the cache and the bloom filter
- loadVanityPath(resource, resolveMapsMap, targetPaths, true,
- createVanityBloomFilter);
- } else {
- // fill up the bloom filter
- loadVanityPath(resource, resolveMapsMap, targetPaths, false,
- createVanityBloomFilter);
- }
-
- }
-
-
- return targetPaths;
- }
-
- /**
- * Load vanity path given a resource
- */
- private void loadVanityPath(final Resource resource, final Map<String, List<MapEntry>> entryMap, final Map <String, List<String>> targetPaths, boolean addToCache, boolean newVanity) {
-
- if (!isValidVanityPath(resource)) {
- return;
- }
-
- final ValueMap props = resource.adaptTo(ValueMap.class);
- long vanityOrder = 0;
- if (props.containsKey(PROP_VANITY_ORDER)) {
- vanityOrder = props.get(PROP_VANITY_ORDER, Long.class);
- }
-
- // url is ignoring scheme and host.port and the path is
- // what is stored in the sling:vanityPath property
- final String[] pVanityPaths = props.get(PROP_VANITY_PATH, new String[0]);
- for (final String pVanityPath : pVanityPaths) {
- final String[] result = this.getVanityPathDefinition(pVanityPath);
- if (result != null) {
- final String url = result[0] + result[1];
- // redirect target is the node providing the
- // sling:vanityPath
- // property (or its parent if the node is called
- // jcr:content)
- final Resource redirectTarget;
- if (resource.getName().equals("jcr:content")) {
- redirectTarget = resource.getParent();
- } else {
- redirectTarget = resource;
- }
- final String redirect = redirectTarget.getPath();
- final String redirectName = redirectTarget.getName();
-
- // whether the target is attained by a external redirect or
- // by an internal redirect is defined by the sling:redirect
- // property
- final int status = props.get(PROP_REDIRECT_EXTERNAL, false) ? props.get(
- PROP_REDIRECT_EXTERNAL_REDIRECT_STATUS, factory.getDefaultVanityPathRedirectStatus())
- : -1;
-
- final String checkPath = result[1];
-
- boolean addedEntry;
- if (addToCache) {
- if (redirectName.indexOf('.') > -1) {
- // 1. entry with exact match
- this.addEntry(entryMap, checkPath, getMapEntry(url + "$", status, false, vanityOrder, redirect));
-
- final int idx = redirectName.lastIndexOf('.');
- final String extension = redirectName.substring(idx + 1);
-
- // 2. entry with extension
- addedEntry = this.addEntry(entryMap, checkPath, getMapEntry(url + "\\." + extension, status, false, vanityOrder, redirect));
- } else {
- // 1. entry with exact match
- this.addEntry(entryMap, checkPath, getMapEntry(url + "$", status, false, vanityOrder, redirect + ".html"));
-
- // 2. entry with match supporting selectors and extension
- addedEntry = this.addEntry(entryMap, checkPath, getMapEntry(url + "(\\..*)", status, false, vanityOrder, redirect + "$1"));
- }
- if (addedEntry) {
- // 3. keep the path to return
- this.updateTargetPaths(targetPaths, redirect, checkPath);
- //increment only if the instance variable
- if (entryMap == resolveMapsMap) {
- vanityCounter.addAndGet(2);
- }
-
- if (newVanity) {
- // update bloom filter
- BloomFilterUtils.add(vanityBloomFilter, checkPath);
- }
- }
- } else {
- if (newVanity) {
- // update bloom filter
- BloomFilterUtils.add(vanityBloomFilter, checkPath);
- }
- }
- }
- }
- }
-
- private void updateTargetPaths(final Map<String, List<String>> targetPaths, final String key, final String entry) {
- if (entry == null) {
- return;
- }
- List<String> entries = targetPaths.get(key);
- if (entries == null) {
- entries = new ArrayList<String>();
- targetPaths.put(key, entries);
- }
- entries.add(entry);
- }
-
- /**
- * Create the vanity path definition. String array containing:
- * {protocol}/{host}[.port] {absolute path}
- */
- private String[] getVanityPathDefinition(final String pVanityPath) {
- String[] result = null;
- if (pVanityPath != null) {
- final String info = pVanityPath.trim();
- if (info.length() > 0) {
- String prefix = null;
- String path = null;
- // check for url
- if (info.indexOf(":/") > -1) {
- try {
- final URL u = new URL(info);
- prefix = u.getProtocol() + '/' + u.getHost() + '.' + u.getPort();
- path = u.getPath();
- } catch (final MalformedURLException e) {
- log.warn("Ignoring malformed vanity path {}", pVanityPath);
- }
- } else {
- prefix = "^" + ANY_SCHEME_HOST;
- if (!info.startsWith("/")) {
- path = "/" + info;
- } else {
- path = info;
- }
- }
-
- // remove extension
- if (prefix != null) {
- final int lastSlash = path.lastIndexOf('/');
- final int firstDot = path.indexOf('.', lastSlash + 1);
- if (firstDot != -1) {
- path = path.substring(0, firstDot);
- log.warn("Removing extension from vanity path {}", pVanityPath);
- }
- result = new String[] { prefix, path };
- }
- }
- }
- return result;
- }
-
- private void loadConfiguration(final MapConfigurationProvider factory, final List<MapEntry> entries) {
- // virtual uris
- final Map<?, ?> virtuals = factory.getVirtualURLMap();
- if (virtuals != null) {
- for (final Entry<?, ?> virtualEntry : virtuals.entrySet()) {
- final String extPath = (String) virtualEntry.getKey();
- final String intPath = (String) virtualEntry.getValue();
- if (!extPath.equals(intPath)) {
- // this regular expression must match the whole URL !!
- final String url = "^" + ANY_SCHEME_HOST + extPath + "$";
- final String redirect = intPath;
- MapEntry mapEntry = getMapEntry(url, -1, false, redirect);
- if (mapEntry!=null){
- entries.add(mapEntry);
- }
- }
- }
- }
-
- // URL Mappings
- final Mapping[] mappings = factory.getMappings();
- if (mappings != null) {
- final Map<String, List<String>> map = new HashMap<String, List<String>>();
- for (final Mapping mapping : mappings) {
- if (mapping.mapsInbound()) {
- final String url = mapping.getTo();
- final String alias = mapping.getFrom();
- if (url.length() > 0) {
- List<String> aliasList = map.get(url);
- if (aliasList == null) {
- aliasList = new ArrayList<String>();
- map.put(url, aliasList);
- }
- aliasList.add(alias);
- }
- }
- }
-
- for (final Entry<String, List<String>> entry : map.entrySet()) {
- MapEntry mapEntry = getMapEntry(ANY_SCHEME_HOST + entry.getKey(), -1, false, entry.getValue().toArray(new String[0]));
- if (mapEntry!=null){
- entries.add(mapEntry);
- }
- }
- }
- }
-
- private void loadMapConfiguration(final MapConfigurationProvider factory, final Map<String, MapEntry> entries) {
- // URL Mappings
- final Mapping[] mappings = factory.getMappings();
- if (mappings != null) {
- for (int i = mappings.length - 1; i >= 0; i--) {
- final Mapping mapping = mappings[i];
- if (mapping.mapsOutbound()) {
- final String url = mapping.getTo();
- final String alias = mapping.getFrom();
- if (!url.equals(alias)) {
- addMapEntry(entries, alias, url, -1);
- }
- }
- }
- }
-
- // virtual uris
- final Map<?, ?> virtuals = factory.getVirtualURLMap();
- if (virtuals != null) {
- for (final Entry<?, ?> virtualEntry : virtuals.entrySet()) {
- final String extPath = (String) virtualEntry.getKey();
- final String intPath = (String) virtualEntry.getValue();
- if (!extPath.equals(intPath)) {
- // this regular expression must match the whole URL !!
- final String path = "^" + intPath + "$";
- final String url = extPath;
- addMapEntry(entries, path, url, -1);
- }
- }
- }
- }
-
- private void addMapEntry(final Map<String, MapEntry> entries, final String path, final String url, final int status) {
- MapEntry entry = entries.get(path);
- if (entry == null) {
- entry = getMapEntry(path, status, false, url);
- } else {
- final String[] redir = entry.getRedirect();
- final String[] newRedir = new String[redir.length + 1];
- System.arraycopy(redir, 0, newRedir, 0, redir.length);
- newRedir[redir.length] = url;
- entry = getMapEntry(entry.getPattern(), entry.getStatus(), false, newRedir);
- }
- if (entry!=null){
- entries.put(path, entry);
- }
- }
-
- /**
- * Returns a filter which matches if any of the nodeProps (JCR properties
- * modified) is listed in any of the eventProps (event properties listing
- * modified JCR properties) this allows to only get events interesting for
- * updating the internal structure
- */
- private static String createFilter(final boolean vanityPathEnabled) {
- final String[] nodeProps = {
- PROP_REDIRECT_EXTERNAL_REDIRECT_STATUS, PROP_REDIRECT_EXTERNAL,
- ResourceResolverImpl.PROP_REDIRECT_INTERNAL, PROP_REDIRECT_EXTERNAL_STATUS,
- PROP_REG_EXP, ResourceResolverImpl.PROP_ALIAS };
- final String[] eventProps = { SlingConstants.PROPERTY_ADDED_ATTRIBUTES, SlingConstants.PROPERTY_CHANGED_ATTRIBUTES, SlingConstants.PROPERTY_REMOVED_ATTRIBUTES };
- final StringBuilder filter = new StringBuilder();
- filter.append("(|");
- for (final String eventProp : eventProps) {
- filter.append("(|");
- if ( vanityPathEnabled ) {
- filter.append('(').append(eventProp).append('=').append(PROP_VANITY_PATH).append(')');
- filter.append('(').append(eventProp).append('=').append(PROP_VANITY_ORDER).append(')');
- }
- for (final String nodeProp : nodeProps) {
- filter.append('(').append(eventProp).append('=').append(nodeProp).append(')');
- }
- filter.append(")");
- }
- filter.append("(").append(EventConstants.EVENT_TOPIC).append("=").append(SlingConstants.TOPIC_RESOURCE_REMOVED).append(")");
- filter.append("(").append(EventConstants.EVENT_TOPIC).append("=").append(SlingConstants.TOPIC_RESOURCE_ADDED).append(")");
- filter.append(")");
-
- return filter.toString();
- }
-
- private final class MapEntryIterator implements Iterator<MapEntry> {
-
- private final Map<String, List<MapEntry>> resolveMapsMap;
-
- private String key;
-
- private MapEntry next;
-
- private final Iterator<MapEntry> globalListIterator;
- private MapEntry nextGlobal;
-
- private Iterator<MapEntry> specialIterator;
- private MapEntry nextSpecial;
-
- private boolean vanityPathPrecedence;
-
- public MapEntryIterator(final String startKey, final Map<String, List<MapEntry>> resolveMapsMap, final boolean vanityPathPrecedence) {
- this.key = startKey;
- this.resolveMapsMap = resolveMapsMap;
- this.globalListIterator = this.resolveMapsMap.get(GLOBAL_LIST_KEY).iterator();
- this.vanityPathPrecedence = vanityPathPrecedence;
- this.seek();
- }
-
- /**
- * @see java.util.Iterator#hasNext()
- */
- public boolean hasNext() {
- return this.next != null;
- }
-
- /**
- * @see java.util.Iterator#next()
- */
- public MapEntry next() {
- if (this.next == null) {
- throw new NoSuchElementException();
- }
- final MapEntry result = this.next;
- this.seek();
- return result;
- }
-
- /**
- * @see java.util.Iterator#remove()
- */
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- private void seek() {
- if (this.nextGlobal == null && this.globalListIterator.hasNext()) {
- this.nextGlobal = this.globalListIterator.next();
- }
- if (this.nextSpecial == null) {
- if (specialIterator != null && !specialIterator.hasNext()) {
- specialIterator = null;
- }
- while (specialIterator == null && key != null) {
- // remove selectors and extension
- final int lastSlashPos = key.lastIndexOf('/');
- final int lastDotPos = key.indexOf('.', lastSlashPos);
- if (lastDotPos != -1) {
- key = key.substring(0, lastDotPos);
- }
-
- final List<MapEntry> special;
- if (MapEntries.this.isAllVanityPathEntriesCached()) {
- special = this.resolveMapsMap.get(key);
- } else {
- special = MapEntries.this.getMapEntryList(key)
-; }
- if (special != null) {
- specialIterator = special.iterator();
- }
- // recurse to the parent
- if (key.length() > 1) {
- final int lastSlash = key.lastIndexOf("/");
- if (lastSlash == 0) {
- key = null;
- } else {
- key = key.substring(0, lastSlash);
- }
- } else {
- key = null;
- }
- }
- if (this.specialIterator != null && this.specialIterator.hasNext()) {
- this.nextSpecial = this.specialIterator.next();
- }
- }
- if (this.nextSpecial == null) {
- this.next = this.nextGlobal;
- this.nextGlobal = null;
- } else if (!this.vanityPathPrecedence){
- if (this.nextGlobal == null) {
- this.next = this.nextSpecial;
- this.nextSpecial = null;
- } else if (this.nextGlobal.getPattern().length() >= this.nextSpecial.getPattern().length()) {
- this.next = this.nextGlobal;
- this.nextGlobal = null;
-
- }else {
- this.next = this.nextSpecial;
- this.nextSpecial = null;
- }
- } else {
- this.next = this.nextSpecial;
- this.nextSpecial = null;
- }
- }
- };
-
- private MapEntry getMapEntry(String url, final int status, final boolean trailingSlash,
- final String... redirect){
-
- MapEntry mapEntry = null;
- try{
- mapEntry = new MapEntry(url, status, trailingSlash, 0, redirect);
- }catch (IllegalArgumentException iae){
- //ignore this entry
- log.debug("ignored entry due exception ",iae);
- }
- return mapEntry;
- }
-
- private MapEntry getMapEntry(String url, final int status, final boolean trailingSlash, long order,
- final String... redirect){
-
- MapEntry mapEntry = null;
- try{
- mapEntry = new MapEntry(url, status, trailingSlash, order, redirect);
- }catch (IllegalArgumentException iae){
- //ignore this entry
- log.debug("ignored entry due exception ",iae);
- }
- return mapEntry;
- }
-
- final class BloomFilterTask extends TimerTask {
- @Override
- public void run() {
- try {
- if (updateBloomFilterFile) {
- persistBloomFilter();
- updateBloomFilterFile = false;
- }
- } catch (IOException e) {
- throw new RuntimeException(
- "Error while saving bloom filter to disk", e);
- }
- }
- }
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntry.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntry.java
deleted file mode 100644
index f5d5d66..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntry.java
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * 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.resourceresolver.impl.mapping;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The <code>MapEntry</code> class represents a mapping entry in the mapping
- * configuration tree at <code>/etc/map</code>.
- * <p>
- *
- * @see "http://cwiki.apache.org/SLING/flexible-resource-resolution.html"
- */
-public class MapEntry implements Comparable<MapEntry> {
-
- /** default log */
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- private static final Pattern[] URL_WITH_PORT_MATCH = {
- Pattern.compile("http/([^/]+)(\\.[^\\d/]+)(/.*)?$"),
- Pattern.compile("https/([^/]+)(\\.[^\\d/]+)(/.*)?$") };
-
- private static final String[] URL_WITH_PORT_REPLACEMENT = {
- "http/$1$2.80$3", "https/$1$2.443$3" };
-
- private static final Pattern[] PATH_TO_URL_MATCH = {
- Pattern.compile("http/([^/]+)\\.80(/.*)?$"),
- Pattern.compile("https/([^/]+)\\.443(/.*)?$"),
- Pattern.compile("([^/]+)/([^/]+)\\.(\\d+)(/.*)?$"),
- Pattern.compile("([^/]+)/([^/]+)(/.*)?$") };
-
- private static final String[] PATH_TO_URL_REPLACEMENT = { "http://$1$2",
- "https://$1$2", "$1://$2:$3$4", "$1://$2$3" };
-
- private final Pattern urlPattern;
-
- private final String[] redirect;
-
- private final int status;
-
- private long order;
-
- public static String appendSlash(String path) {
- if (!path.endsWith("/")) {
- path = path.concat("/");
- }
- return path;
- }
-
- /**
- * Returns a string used for matching map entries against the given request
- * or URI parts.
- *
- * @param scheme
- * The URI scheme
- * @param host
- * The host name
- * @param port
- * The port number. If this is negative, the default value used
- * is 80 unless the scheme is "https" in which case the default
- * value is 443.
- * @param path
- * The (absolute) path
- * @return The request path string {scheme}://{host}:{port}{path}.
- */
- public static String getURI(final String scheme, final String host, final int port,
- final String path) {
-
- final StringBuilder sb = new StringBuilder();
- sb.append(scheme).append("://").append(host);
- if (port > 0 && !(port == 80 && "http".equals(scheme))
- && !(port == 443 && "https".equals(scheme))) {
- sb.append(':').append(port);
- }
- sb.append(path);
-
- return sb.toString();
- }
-
- public static String fixUriPath(final String uriPath) {
- for (int i = 0; i < URL_WITH_PORT_MATCH.length; i++) {
- final Matcher m = URL_WITH_PORT_MATCH[i].matcher(uriPath);
- if (m.find()) {
- return m.replaceAll(URL_WITH_PORT_REPLACEMENT[i]);
- }
- }
-
- return uriPath;
- }
-
- /**
- * Converts the resolution path of the form http/host.77/the/path into an
- * URI of the form http://host:77/the/path where any potential default port
- * (80 for http and 443 for https) is actually removed. If the path is just
- * a regular path such as /the/path, this method returns <code>null</code>.
- */
- public static String toURI(final String uriPath) {
- for (int i = 0; i < PATH_TO_URL_MATCH.length; i++) {
- final Matcher m = PATH_TO_URL_MATCH[i].matcher(uriPath);
- if (m.find()) {
- return m.replaceAll(PATH_TO_URL_REPLACEMENT[i]);
- }
- }
-
- return null;
- }
-
- public static MapEntry createResolveEntry(String url, final Resource resource,
- final boolean trailingSlash) {
- final ValueMap props = resource.adaptTo(ValueMap.class);
- if (props != null) {
-
- // ensure the url contains a port number (if possible)
- url = fixUriPath(url);
-
- final String redirect = props.get(
- MapEntries.PROP_REDIRECT_EXTERNAL, String.class);
- if (redirect != null) {
- final int status = props
- .get(MapEntries.PROP_REDIRECT_EXTERNAL_STATUS,
- 302);
- return new MapEntry(url, status, trailingSlash, 0, redirect);
- }
-
- final String[] internalRedirectProps = props.get(ResourceResolverImpl.PROP_REDIRECT_INTERNAL,
- String[].class);
- final String[] internalRedirect = filterRegExp(internalRedirectProps);
- if (internalRedirect != null) {
- return new MapEntry(url, -1, trailingSlash, 0, internalRedirect);
- }
- }
-
- return null;
- }
-
- public static List<MapEntry> createMapEntry(String url, final Resource resource,
- final boolean trailingSlash) {
- final ValueMap props = resource.adaptTo(ValueMap.class);
- if (props != null) {
- final String redirect = props.get(
- MapEntries.PROP_REDIRECT_EXTERNAL, String.class);
- if (redirect != null) {
- // ignoring external redirects for mapping
- LoggerFactory
- .getLogger(MapEntry.class)
- .info("createMapEntry: Configuration has external redirect to {}; not creating mapping for configuration in {}",
- redirect, resource.getPath());
- return null;
- }
-
- // ignore potential regular expression url
- if (isRegExp(url)) {
- LoggerFactory
- .getLogger(MapEntry.class)
- .info("createMapEntry: URL {} contains a regular expression; not creating mapping for configuration in {}",
- url, resource.getPath());
-
- return null;
- }
-
- // check whether the url is a match hooked to then string end
- String endHook = "";
- if (url.endsWith("$")) {
- endHook = "$";
- url = url.substring(0, url.length() - 1);
- }
-
- // check whether the url is for ANY_SCHEME_HOST
- if (url.startsWith(MapEntries.ANY_SCHEME_HOST)) {
- url = url.substring(MapEntries.ANY_SCHEME_HOST.length());
- }
-
- final String[] internalRedirect = props
- .get(ResourceResolverImpl.PROP_REDIRECT_INTERNAL,
- String[].class);
- if (internalRedirect != null) {
-
- // check whether the url is considered external or internal
- int status = -1;
- final String pathUri = toURI(url);
- if (pathUri != null) {
- url = pathUri;
- status = 302;
- }
-
- final List<MapEntry> prepEntries = new ArrayList<MapEntry>(
- internalRedirect.length);
- for (final String redir : internalRedirect) {
- if (!redir.contains("$")) {
- MapEntry mapEntry = null;
- try{
- mapEntry = new MapEntry(redir.concat(endHook), status, trailingSlash, 0, url);
- }catch (IllegalArgumentException iae){
- //ignore this entry
- LoggerFactory
- .getLogger(MapEntry.class)
- .debug("Ignoring mapping due to exception: " + iae.getMessage(), iae);
- }
- if (mapEntry!=null){
- prepEntries.add(mapEntry);
- }
- }
- }
-
- if (prepEntries.size() > 0) {
- return prepEntries;
- }
- }
- }
-
- return null;
- }
-
- public MapEntry(String url, final int status, final boolean trailingSlash,
- final long order, final String... redirect) {
-
- // ensure trailing slashes on redirects if the url
- // ends with a trailing slash
- if (trailingSlash) {
- url = appendSlash(url);
- for (int i = 0; i < redirect.length; i++) {
- redirect[i] = appendSlash(redirect[i]);
- }
- }
-
- // ensure pattern is hooked to the start of the string
- if (!url.startsWith("^")) {
- url = "^".concat(url);
- }
-
- try {
- this.urlPattern = Pattern.compile(url);
- } catch (Exception e){
- throw new IllegalArgumentException("Bad url pattern: " + url,e);
- }
-
- this.redirect = redirect;
- this.status = status;
- this.order = order;
- }
-
- // Returns the replacement or null if the value does not match
- public String[] replace(final String value) {
- final Matcher m = urlPattern.matcher(value);
- if (m.find()) {
- final String[] redirects = getRedirect();
- final String[] results = new String[redirects.length];
- for (int i = 0; i < redirects.length; i++) {
- try{
- results[i] = m.replaceFirst(redirects[i]);
- } catch (final StringIndexOutOfBoundsException siob){
- log.debug("Exception while replacing, ignoring entry {} ", redirects[i], siob);
- } catch (final IllegalArgumentException iae){
- log.debug("Exception while replacing, ignoring entry {} ", redirects[i], iae);
- }
- }
- return results;
- }
-
- return null;
- }
-
- public String getPattern() {
- return urlPattern.toString();
- }
-
- public String[] getRedirect() {
- return redirect;
- }
-
- public boolean isInternal() {
- return getStatus() < 0;
- }
-
- public int getStatus() {
- return status;
- }
-
- // ---------- Comparable
-
- public int compareTo(final MapEntry m) {
- if (this == m) {
- return 0;
- }
-
- final String ownPatternString = urlPattern.toString();
- final String mPatternString = m.urlPattern.toString();
-
- final int tlen = ownPatternString.length();
- final int mlen = mPatternString.length();
- if (tlen < mlen) {
- return 1;
- } else if (tlen > mlen) {
- return -1;
- }
-
- // lengths are equal, but the entries are not
- // so order based on the pattern
- int stringComparison = ownPatternString.toString().compareTo(mPatternString);
- if (stringComparison == 0 && order != m.order) {
- if (m.order > order) {
- return 1;
- } else {
- return -1;
- }
- }
- return stringComparison;
- }
-
- // ---------- Object overwrite
-
- @Override
- public String toString() {
- final StringBuilder buf = new StringBuilder();
- buf.append("MapEntry: match:").append(urlPattern);
-
- buf.append(", replacement:");
- if (getRedirect().length == 1) {
- buf.append(getRedirect()[0]);
- } else {
- buf.append(Arrays.asList(getRedirect()));
- }
-
- if (isInternal()) {
- buf.append(", internal");
- } else {
- buf.append(", status:").append(getStatus());
- }
- return buf.toString();
- }
-
- // ---------- helper
-
- /**
- * Returns <code>true</code> if the string contains unescaped regular
- * expression special characters '+', '*', '?', '|', '(', '), '[', and ']'
- *
- * @param string
- * @return
- */
- private static boolean isRegExp(final String string) {
- for (int i = 0; i < string.length(); i++) {
- final char c = string.charAt(i);
- if (c == '\\') {
- i++; // just skip
- } else if ("+*?|()[]".indexOf(c) >= 0) {
- return true; // assume an unescaped pattern character
- }
- }
- return false;
- }
-
- /**
- * Returns an array of strings copied from the given strings where any
- * regular expressions in the array are removed. If the input is
- * <code>null</code> or no strings are provided <code>null</code> is
- * returned. <code>null</code> is also returned if the strings only contain
- * regular expressions.
- */
- private static String[] filterRegExp(final String... strings) {
- if (strings == null || strings.length == 0) {
- return null;
- }
-
- ArrayList<String> list = new ArrayList<String>(strings.length);
- for (String string : strings) {
- if (!isRegExp(string)) {
- list.add(string);
- }
- }
-
- return list.isEmpty() ? null : (String[]) list.toArray(new String[list.size()]);
- }
-
- void setOrder(long order) {
- this.order = order;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/Mapping.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/Mapping.java
deleted file mode 100644
index 4d4f0d9..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/Mapping.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.resourceresolver.impl.mapping;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * The <code>Mapping</code> class conveys the mapping configuration used by the
- * {@link org.apache.sling.resourceresolver.impl.ResourceResolverFactoryImpl}.
- */
-public class Mapping {
-
- /**
- * defines the 'inbound' direction, that is mapping request path to item
- * path
- */
- public static final int INBOUND = 1;
-
- /** defined the 'outbound' direction, that is mapping item path to URL path */
- public static final int OUTBOUND = 2;
-
- /** defines the 'both' direction */
- public static final int BOTH = 3;
-
- /** Simple mapper instance mapping path to URLs 1:1 in both directions */
- public static final Mapping DIRECT = new Mapping("", "", BOTH) {
-
- @Override
- public String mapHandle(String handle) {
- return handle;
- }
-
- @Override
- public boolean mapsInbound() {
- return true;
- }
-
- @Override
- public boolean mapsOutbound() {
- return true;
- }
-
- @Override
- public String mapUri(String uriPath) {
- return uriPath;
- }
- };
-
- // Regular expression to split mapping configuration strings into three
- // groups:
- // 1 - external path prefix
- // 2 - direction (Outbound (>), Bidirectional (:), Inbound (>))
- // 3 - internap path prefix
- private static final Pattern CONFIG_SPLITTER = Pattern
- .compile("(.+)([:<>])(.+)");
-
- /** the 'from' (inside, repository) mapping */
- private final String from;
-
- /** the 'to' (outside, URL) mapping */
- private final String to;
-
- /** the length of the 'from' field */
- private final int fromLength;
-
- /** the length of the 'to' field */
- private final int toLength;
-
- /** the mapping direction */
- private final int direction;
-
- public Mapping(String config) {
- this(split(config));
- }
-
- public Mapping(String[] parts) {
- this.from = parts[0];
- this.to = parts[2];
- this.fromLength = this.from.length();
- this.toLength = this.to.length();
-
- this.direction = ">".equals(parts[1]) ? Mapping.INBOUND : ("<"
- .equals(parts[1]) ? Mapping.OUTBOUND : Mapping.BOTH);
- }
-
- @Override
- public String toString() {
- return "Mapping (from=" + from + ", to=" + to + ", direction="
- + direction + ", lengths=" + fromLength + "/" + toLength;
- }
-
- /**
- * Replaces the prefix <em>to</em> by the new prefix <em>from</em>, if and
- * only if <code>uriPath</code> starts with the <em>to</em> prefix. If
- * <code>uriPath</code> does not start with the <em>to</em> prefix, or if
- * this mapping is not defined as a 'inward' mapping, <code>null</code> is
- * returned.
- *
- * @param uriPath
- * The URI path for which to replace the <em>to</em> prefix by
- * the <em>from</em> prefix.
- * @return The string after replacement or <code>null</code> if the
- * <code>uriPath</code> does not start with the <em>to</em> prefix,
- * or {@link #mapsInbound()} returns <code>false</code>.
- */
- public String mapUri(String uriPath) {
- return (this.mapsInbound() && uriPath.startsWith(this.to)) ? this.from
- + uriPath.substring(this.toLength) : null;
- }
-
- /**
- * Replaces the prefix <em>from</em> by the new prefix <em>to</em>, if and
- * only if <code>handle</code> starts with the <em>from</em> prefix. If
- * <code>uriPath</code> does not start with the <em>from</em> prefix, or if
- * this mapping is not defined as a 'outward' mapping, <code>null</code> is
- * returned.
- *
- * @param handle
- * The URI path for which to replace the <em>from</em> prefix by
- * the <em>to</em> prefix.
- * @return The string after replacement or <code>null</code> if the
- * <code>handle</code> does not start with the <em>from</em> prefix,
- * or {@link #mapsOutbound()} returns <code>false</code>.
- */
- public String mapHandle(String handle) {
- return (this.mapsOutbound() && handle.startsWith(this.from)) ? this.to
- + handle.substring(this.fromLength) : null;
- }
-
- // TODO: temporary
- public String getFrom() {
- return from;
- }
-
- // TODO: temporary
- public String getTo() {
- return to;
- }
-
- /**
- * Checks, if this mapping is defined for inbound mapping.
- *
- * @return <code>true</code> if this mapping is defined for inbound mapping;
- * <code>false</code> otherwise
- */
- public boolean mapsInbound() {
- return (this.direction & Mapping.INBOUND) > 0;
- }
-
- /**
- * Checks, if this mapping is defined for outbound mapping.
- *
- * @return <code>true</code> if this mapping is defined for outbound
- * mapping; <code>false</code> otherwise
- */
- public boolean mapsOutbound() {
- return (this.direction & Mapping.OUTBOUND) > 0;
- }
-
- /**
- * Constructs a new mapping with the given mapping string and the direction
- */
- private Mapping(String from, String to, int dir) {
- this.from = from;
- this.to = to;
- this.fromLength = from.length();
- this.toLength = to.length();
- this.direction = dir;
- }
-
- public static String[] split(String map) {
-
- // standard case of mapping <path>[<:>]<path>
- Matcher mapMatch = CONFIG_SPLITTER.matcher(map);
- if (mapMatch.matches()) {
- return new String[] { mapMatch.group(1), mapMatch.group(2),
- mapMatch.group(3) };
- }
-
- // backwards compatibility using "-" instead of ":"
- int dash = map.indexOf('-');
- if (dash > 0) {
- return new String[] { map.substring(0, dash),
- map.substring(dash, dash + 1),
- map.substring(dash + 1, map.length()) };
- }
-
- return new String[] { map, "-", map };
- }
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObservationReporter.java b/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObservationReporter.java
deleted file mode 100644
index bc155e6..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObservationReporter.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * 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.resourceresolver.impl.observation;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.sling.api.resource.observation.ResourceChange;
-import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
-import org.apache.sling.api.resource.path.Path;
-import org.apache.sling.api.resource.path.PathSet;
-import org.apache.sling.spi.resource.provider.ObservationReporter;
-import org.apache.sling.spi.resource.provider.ObserverConfiguration;
-
-/**
- * Implementation of the observation reporter.
- * Each resource provider gets its on instance.
- */
-public class BasicObservationReporter implements ObservationReporter {
-
-
- private final List<ObserverConfiguration> configs;
-
- private final Map<ListenerConfig, List<ResourceChangeListenerInfo>> listeners = new HashMap<BasicObservationReporter.ListenerConfig, List<ResourceChangeListenerInfo>>();;
-
- /**
- * Create a reporter listening for resource provider changes
- * @param infos The listeners map
- */
- public BasicObservationReporter(final Collection<ResourceChangeListenerInfo> infos) {
- final Set<String> paths = new HashSet<String>();
- for(final ResourceChangeListenerInfo info : infos) {
- if ( !info.getProviderChangeTypes().isEmpty() ) {
- for(final Path p : info.getPaths()) {
- paths.add(p.getPath());
- }
- fillListeners(info, info.getResourceChangeTypes());
- }
- }
- final ObserverConfiguration cfg = new BasicObserverConfiguration(PathSet.fromStringCollection(paths));
- this.configs = Collections.singletonList(cfg);
- }
-
- /**
- * Create a reporter listening for a provider
- * @param infos The listeners map
- * @param providerPath The mount point of the provider
- * @param excludePaths Excluded paths for that provider
- */
- public BasicObservationReporter(final Collection<ResourceChangeListenerInfo> infos,
- final Path providerPath, final PathSet excludePaths) {
- final Map<String, ObserverConfig> configMap = new HashMap<String, ObserverConfig>();
- for(final ResourceChangeListenerInfo info : infos) {
- if ( !info.getResourceChangeTypes().isEmpty() ) {
- boolean add = false;
- for(final Path p : info.getPaths()) {
- if ( providerPath.matches(p.getPath()) && excludePaths.matches(p.getPath()) == null ) {
- ObserverConfig config = configMap.get(p);
- if ( config == null ) {
- config = new ObserverConfig();
- configMap.put(p.getPath(), config);
- }
- config.types.addAll(info.getResourceChangeTypes());
- if ( info.isExternal() ) {
- config.isExternal = true;
- }
- add = true;
- }
- }
- if ( add ) {
- fillListeners(info, info.getResourceChangeTypes());
- }
- }
- }
- final List<ObserverConfiguration> result = new ArrayList<ObserverConfiguration>();
- for(final Map.Entry<String, ObserverConfig> entry : configMap.entrySet()) {
- final ObserverConfiguration cfg = new BasicObserverConfiguration(entry.getKey(), entry.getValue().types,
- entry.getValue().isExternal, excludePaths);
- result.add(cfg);
- }
- this.configs = Collections.unmodifiableList(result);
- }
-
- private void fillListeners(final ResourceChangeListenerInfo info, final Set<ChangeType> types) {
- final ListenerConfig cfg = new ListenerConfig(info, types);
- List<ResourceChangeListenerInfo> list = this.listeners.get(cfg);
- if ( list == null ) {
- list = new ArrayList<ResourceChangeListenerInfo>();
- this.listeners.put(cfg, list);
- }
- list.add(info);
- }
-
- @Override
- public List<ObserverConfiguration> getObserverConfigurations() {
- return configs;
- }
-
- @Override
- public void reportChanges(final Iterable<ResourceChange> changes, final boolean distribute) {
- for (final Map.Entry<ListenerConfig, List<ResourceChangeListenerInfo>> entry : this.listeners.entrySet()) {
- final List<ResourceChange> filtered = filterChanges(changes, entry.getKey());
- if ( !filtered.isEmpty() ) {
- for(final ResourceChangeListenerInfo info : entry.getValue()) {
- info.getListener().onChange(filtered);
- }
- }
- }
- // TODO implement distribute
- }
-
- /**
- * Filter the change list based on the configuration
- * @param changes The list of changes
- * @param config The configuration
- * @return The filtered list.
- */
- private List<ResourceChange> filterChanges(final Iterable<ResourceChange> changes, final ListenerConfig config) {
- final List<ResourceChange> filtered = new ArrayList<ResourceChange>();
- for (final ResourceChange c : changes) {
- if (matches(c, config)) {
- filtered.add(c);
- }
- }
- return filtered;
- }
-
- /**
- * Match a change against the configuration
- * @param change The change
- * @param config The configuration
- * @return {@code true} whether it matches
- */
- private boolean matches(final ResourceChange change, final ListenerConfig config) {
- if (!config.types.contains(change.getType())) {
- return false;
- }
- if (!config.isExternal && change.isExternal()) {
- return false;
- }
- if (config.paths.matches(change.getPath()) == null ) {
- return false;
- }
- return true;
- }
-
- private static final class ObserverConfig {
- public final Set<ChangeType> types = new HashSet<ChangeType>();
- public boolean isExternal;
- }
-
- private static final class ListenerConfig {
-
- public final PathSet paths;
-
- public final boolean isExternal;
-
- public final Set<ChangeType> types;
-
- public ListenerConfig(final ResourceChangeListenerInfo info, Set<ChangeType> types) {
- this.paths = info.getPaths();
- this.isExternal = info.isExternal();
- this.types = types;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + (isExternal ? 1231 : 1237);
- result = prime * result + paths.hashCode();
- result = prime * result + types.hashCode();
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- ListenerConfig other = (ListenerConfig) obj;
- if (isExternal != other.isExternal)
- return false;
- if (!paths.equals(other.paths))
- return false;
- if (!types.equals(other.types))
- return false;
- return true;
- }
-
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObserverConfiguration.java b/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObserverConfiguration.java
deleted file mode 100644
index e2996c0..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/observation/BasicObserverConfiguration.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.resourceresolver.impl.observation;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
-import org.apache.sling.api.resource.path.PathSet;
-import org.apache.sling.spi.resource.provider.ObserverConfiguration;
-
-public class BasicObserverConfiguration implements ObserverConfiguration {
-
- private final boolean includeExternal;
-
- private final PathSet paths;
-
- private final PathSet excludedPaths;
-
- private final Set<ChangeType> changeTypes;
-
- public BasicObserverConfiguration(final String path, final Set<ChangeType> types,
- final boolean isExternal, final PathSet excludePaths) {
- this.includeExternal = isExternal;
- this.paths = PathSet.fromStrings(path);
- this.changeTypes = Collections.unmodifiableSet(types);
- this.excludedPaths = excludePaths.getSubset(path);
- }
-
- public BasicObserverConfiguration(final PathSet set) {
- this.includeExternal = false;
- this.paths = set;
- final Set<ChangeType> types = new HashSet<ChangeType>();
- types.add(ChangeType.PROVIDER_ADDED);
- types.add(ChangeType.PROVIDER_REMOVED);
- this.changeTypes = Collections.unmodifiableSet(types);
- this.excludedPaths = PathSet.EMPTY_SET;
- }
-
- @Override
- public boolean includeExternal() {
- return includeExternal;
- }
-
- @Override
- public PathSet getPaths() {
- return paths;
- }
-
- @Override
- public PathSet getExcludedPaths() {
- return excludedPaths;
- }
-
- @Override
- public Set<ChangeType> getChangeTypes() {
- return changeTypes;
- }
-
- @Override
- public boolean matches(final String path) {
- if ( this.paths.matches(path) != null && this.excludedPaths.matches(path) == null ) {
- return true;
- }
- return false;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/observation/OsgiObservationBridge.java b/src/main/java/org/apache/sling/resourceresolver/impl/observation/OsgiObservationBridge.java
deleted file mode 100644
index 80b87b3..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/observation/OsgiObservationBridge.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.resourceresolver.impl.observation;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.ConfigurationPolicy;
-import org.apache.felix.scr.annotations.Properties;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.Service;
-import org.apache.sling.api.SlingConstants;
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.api.resource.observation.ExternalResourceChangeListener;
-import org.apache.sling.api.resource.observation.ResourceChange;
-import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
-import org.apache.sling.api.resource.observation.ResourceChangeListener;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Component(policy = ConfigurationPolicy.REQUIRE, metatype = true,
- label="Apache Sling OSGi Observation Bridge", description="Legacy bridge which converts resource change events to OSGi events")
-@Service(ResourceChangeListener.class)
-@Properties({ @Property(name = ResourceChangeListener.CHANGES, value = { "ADDED", "CHANGED", "REMOVED" }),
- @Property(name = ResourceChangeListener.PATHS, value = "/") })
-public class OsgiObservationBridge implements ResourceChangeListener, ExternalResourceChangeListener {
-
- private static final Logger logger = LoggerFactory.getLogger(OsgiObservationBridge.class);
-
- @Reference
- private EventAdmin eventAdmin;
-
- @Reference
- private ResourceResolverFactory resolverFactory;
-
- private ResourceResolver resolver;
-
- private BlockingQueue<ResourceChange> changesQueue;
-
- private EventSendingJob job;
-
- @SuppressWarnings("deprecation")
- protected void activate() throws LoginException {
- resolver = resolverFactory.getAdministrativeResourceResolver(null);
- changesQueue = new LinkedBlockingQueue<ResourceChange>();
- job = new EventSendingJob(changesQueue);
- Executors.newSingleThreadExecutor().submit(job);
- }
-
- protected void deactivate() {
- changesQueue.clear();
- job.stop();
- resolver.close();
- }
-
- @Override
- public void onChange(List<ResourceChange> changes) {
- changesQueue.addAll(changes);
- }
-
- @SuppressWarnings("deprecation")
- private void sendOsgiEvent(ResourceChange change) {
- Dictionary<String, Object> props = new Hashtable<String, Object>();
- String topic;
- switch (change.getType()) {
- case ADDED:
- topic = SlingConstants.TOPIC_RESOURCE_ADDED;
- break;
-
- case CHANGED:
- topic = SlingConstants.TOPIC_RESOURCE_CHANGED;
- break;
-
- case REMOVED:
- topic = SlingConstants.TOPIC_RESOURCE_REMOVED;
- break;
-
- default:
- return;
- }
-
- props.put(SlingConstants.PROPERTY_PATH, change.getPath());
- if (change.getUserId() != null) {
- props.put(SlingConstants.PROPERTY_USERID, change.getUserId());
- }
- if (change.getAddedPropertyNames() != null ) {
- props.put(SlingConstants.PROPERTY_ADDED_ATTRIBUTES, change.getAddedPropertyNames().toArray(new String[change.getAddedPropertyNames().size()]));
- }
- if (change.getChangedPropertyNames() != null) {
- props.put(SlingConstants.PROPERTY_CHANGED_ATTRIBUTES, change.getChangedPropertyNames().toArray(new String[change.getChangedPropertyNames().size()]));
- }
- if ( change.getRemovedPropertyNames() != null ) {
- props.put(SlingConstants.PROPERTY_REMOVED_ATTRIBUTES, change.getRemovedPropertyNames().toArray(new String[change.getRemovedPropertyNames().size()]));
- }
- if (change.getType() != ChangeType.REMOVED) {
- Resource resource = resolver.getResource(change.getPath());
- if (resource == null) {
- resolver.refresh();
- resource = resolver.getResource(change.getPath());
- }
- if (resource != null) {
- if (resource.getResourceType() != null) {
- props.put(SlingConstants.PROPERTY_RESOURCE_TYPE, resource.getResourceType());
- }
- if (resource.getResourceSuperType() != null) {
- props.put(SlingConstants.PROPERTY_RESOURCE_SUPER_TYPE, resource.getResourceSuperType());
- }
- }
- }
- if (change.isExternal()) {
- props.put("event.application", "unknown");
- }
-
- final Event event = new Event(topic, props);
- eventAdmin.sendEvent(event);
- }
-
- private class EventSendingJob implements Runnable {
-
- private final BlockingQueue<ResourceChange> changes;
-
- private volatile boolean stop;
-
- public EventSendingJob(BlockingQueue<ResourceChange> changes) {
- this.changes = changes;
- }
-
- @Override
- public void run() {
- while (!stop) {
- ResourceChange change = null;
- try {
- change = changes.poll(100, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- logger.warn("Interrupted the OSGi runnable", e);
- }
- if (change == null) {
- continue;
- }
- try {
- sendOsgiEvent(change);
- } catch (Exception e) {
- logger.error("processOsgiEventQueue: Unexpected problem processing resource change {}", change, e);
- }
- }
- }
-
- public void stop() {
- stop = true;
- }
- }
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerInfo.java b/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerInfo.java
deleted file mode 100644
index d01ad6f..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerInfo.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.resourceresolver.impl.observation;
-
-import static org.apache.sling.api.resource.observation.ResourceChangeListener.CHANGES;
-import static org.apache.sling.api.resource.observation.ResourceChangeListener.PATHS;
-import static org.apache.sling.commons.osgi.PropertiesUtil.toStringArray;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.resource.observation.ExternalResourceChangeListener;
-import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
-import org.apache.sling.api.resource.path.PathSet;
-import org.apache.sling.api.resource.observation.ResourceChangeListener;
-import org.osgi.framework.ServiceReference;
-
-/**
- * Information about a resource change listener.
- */
-public class ResourceChangeListenerInfo {
-
- private static final Set<ChangeType> DEFAULT_CHANGE_RESOURCE_TYPES = EnumSet.of(ChangeType.ADDED, ChangeType.REMOVED, ChangeType.CHANGED);
-
- private static final Set<ChangeType> DEFAULT_CHANGE_PROVIDER_TYPES = EnumSet.of(ChangeType.PROVIDER_ADDED, ChangeType.PROVIDER_REMOVED);
-
- private final PathSet paths;
-
- private final Set<ChangeType> resourceChangeTypes;
-
- private final Set<ChangeType> providerChangeTypes;
-
- private final boolean valid;
-
- private volatile boolean external = false;
-
- private volatile ResourceChangeListener listener;
-
- public ResourceChangeListenerInfo(final ServiceReference ref, final String[] searchPaths) {
- boolean configValid = true;
- final Set<String> pathsSet = new HashSet<String>();
- final String paths[] = toStringArray(ref.getProperty(PATHS), null);
- if ( paths != null ) {
- for(final String p : paths) {
- String normalisedPath = ResourceUtil.normalize(p);
- if (!".".equals(p) && normalisedPath.isEmpty()) {
- configValid = false;
- } else if ( normalisedPath.startsWith("/") ) {
- pathsSet.add(normalisedPath);
- } else {
- for(final String sp : searchPaths) {
- if ( p.equals(".") ) {
- pathsSet.add(sp);
- } else {
- pathsSet.add(ResourceUtil.normalize(sp + normalisedPath));
- }
- }
- }
- }
- }
- if ( pathsSet.isEmpty() ) {
- configValid = false;
- } else {
- // check for sub paths
- final Iterator<String> iter = pathsSet.iterator();
- while ( iter.hasNext() ) {
- final String path = iter.next();
- boolean remove = false;
- for(final String p : pathsSet) {
- if ( p.length() > path.length() && path.startsWith(p + "/") ) {
- remove = true;
- break;
- }
- }
- if ( remove ) {
- iter.remove();
- }
- }
- }
- this.paths = PathSet.fromStringCollection(pathsSet);
- if (ref.getProperty(CHANGES) != null ) {
- final Set<ChangeType> rts = new HashSet<ChangeType>();
- final Set<ChangeType> pts = new HashSet<ChangeType>();
- for (final String changeName : toStringArray(ref.getProperty(CHANGES))) {
- try {
- final ChangeType ct = ChangeType.valueOf(changeName);
- if ( ct.ordinal() < ChangeType.PROVIDER_ADDED.ordinal()) {
- rts.add(ct);
- } else {
- pts.add(ct);
- }
- } catch ( final IllegalArgumentException iae) {
- configValid = false;
- }
- }
- if ( rts.isEmpty() ) {
- this.resourceChangeTypes = Collections.emptySet();
- } else if ( rts.size() == 3 ) {
- this.resourceChangeTypes = DEFAULT_CHANGE_RESOURCE_TYPES;
- } else {
- this.resourceChangeTypes = Collections.unmodifiableSet(rts);
- }
- if ( pts.isEmpty() ) {
- this.providerChangeTypes = Collections.emptySet();
- } else if ( pts.size() == 2 ) {
- this.providerChangeTypes = DEFAULT_CHANGE_PROVIDER_TYPES;
- } else {
- this.providerChangeTypes = Collections.unmodifiableSet(pts);
- }
- } else {
- // default is added, changed, removed for resources and
- // added and removed for providers
- this.resourceChangeTypes = DEFAULT_CHANGE_RESOURCE_TYPES;
- this.providerChangeTypes = DEFAULT_CHANGE_PROVIDER_TYPES;
- }
-
- this.valid = configValid;
- }
-
- public boolean isValid() {
- return this.valid;
- }
-
- public Set<ChangeType> getResourceChangeTypes() {
- return this.resourceChangeTypes;
- }
-
- public Set<ChangeType> getProviderChangeTypes() {
- return this.providerChangeTypes;
- }
-
- public PathSet getPaths() {
- return this.paths;
- }
-
- public boolean isExternal() {
- return this.external;
- }
-
- public ResourceChangeListener getListener() {
- return listener;
- }
-
- public void setListener(final ResourceChangeListener listener) {
- this.listener = listener;
- this.external = listener instanceof ExternalResourceChangeListener;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerWhiteboard.java b/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerWhiteboard.java
deleted file mode 100644
index 1a1c959..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerWhiteboard.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.resourceresolver.impl.observation;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.sling.api.resource.observation.ResourceChange;
-import org.apache.sling.api.resource.observation.ResourceChangeListener;
-import org.apache.sling.api.resource.path.Path;
-import org.apache.sling.api.resource.path.PathSet;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker.ObservationReporterGenerator;
-import org.apache.sling.spi.resource.provider.ObservationReporter;
-import org.apache.sling.spi.resource.provider.ObserverConfiguration;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Tracker component for the resource change listeners.
- */
-public class ResourceChangeListenerWhiteboard implements ResourceProviderTracker.ObservationReporterGenerator {
-
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- private final Map<ServiceReference, ResourceChangeListenerInfo> listeners = new ConcurrentHashMap<ServiceReference, ResourceChangeListenerInfo>();
-
- private volatile ResourceProviderTracker resourceProviderTracker;
-
- private volatile ServiceTracker tracker;
-
- public void activate(final BundleContext bundleContext,
- final ResourceProviderTracker resourceProviderTracker,
- final String[] searchPaths) {
- this.resourceProviderTracker = resourceProviderTracker;
- this.resourceProviderTracker.setObservationReporterGenerator(this);
- this.tracker = new ServiceTracker(bundleContext,
- ResourceChangeListener.class.getName(),
- new ServiceTrackerCustomizer() {
-
- @Override
- public void removedService(final ServiceReference reference, final Object service) {
- final ServiceReference ref = (ServiceReference)service;
- final ResourceChangeListenerInfo info = listeners.remove(ref);
- if ( info != null ) {
- updateProviderTracker();
- }
- }
-
- @Override
- public void modifiedService(final ServiceReference reference, final Object service) {
- removedService(reference, service);
- addingService(reference);
- }
-
- @Override
- public Object addingService(final ServiceReference reference) {
- final ResourceChangeListenerInfo info = new ResourceChangeListenerInfo(reference, searchPaths);
- if ( info.isValid() ) {
- final ResourceChangeListener listener = (ResourceChangeListener) bundleContext.getService(reference);
- if ( listener != null ) {
- info.setListener(listener);
- listeners.put(reference, info);
- updateProviderTracker();
- }
- } else {
- logger.warn("Ignoring invalid resource change listenr {}", reference);
- }
- return reference;
- }
- });
- this.tracker.open();
- }
-
- public void deactivate() {
- if ( this.tracker != null ) {
- this.tracker.close();
- this.tracker = null;
- }
- this.resourceProviderTracker.setObservationReporterGenerator(NOP_GENERATOR);
- this.resourceProviderTracker = null;
- }
-
- private void updateProviderTracker() {
- this.resourceProviderTracker.setObservationReporterGenerator(this);
- }
-
- @Override
- public ObservationReporter create(final Path path, final PathSet excludes) {
- return new BasicObservationReporter(this.listeners.values(), path, excludes);
- }
-
- @Override
- public ObservationReporter createProviderReporter() {
- return new BasicObservationReporter(this.listeners.values());
- }
-
- private static final ObservationReporter EMPTY_REPORTER = new ObservationReporter() {
-
- @Override
- public void reportChanges(Iterable<ResourceChange> changes, boolean distribute) {
- // ignore
- }
-
- @Override
- public List<ObserverConfiguration> getObserverConfigurations() {
- return Collections.emptyList();
- }
- };
-
- private static final ObservationReporterGenerator NOP_GENERATOR = new ObservationReporterGenerator() {
-
- @Override
- public ObservationReporter create(Path path, PathSet excludes) {
- return EMPTY_REPORTER;
- }
-
- @Override
- public ObservationReporter createProviderReporter() {
- return EMPTY_REPORTER;
- }
- };
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/params/ParametersParser.java b/src/main/java/org/apache/sling/resourceresolver/impl/params/ParametersParser.java
deleted file mode 100644
index 3acbd27..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/params/ParametersParser.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.resourceresolver.impl.params;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-class ParametersParser {
-
- private enum ParamsState {
- INIT, NAME, EQUALS, VALUE, QUOTED_VALUE, QUOTE_END
- }
-
- private StringBuilder name;
-
- private StringBuilder value;
-
- private Map<String, String> parameters = new LinkedHashMap<String, String>();
-
- private boolean invalid;
-
- /**
- * Parses parameters string, eg.: {@code ;x=123;a='1.0'}. The result of the method is available in
- * {@link #parameters} and {@link #invalid}.
- *
- * @param chars Array containing path with parameters.
- * @param from Index of the first character of the parameters substring (it must be a semicolon).
- * @param dotAllowed If true, the dot in parameter value won't stop parsing.
- * @return Index of the first character not related to parameters.
- */
- public int parseParameters(final char[] chars, final int from, final boolean dotAllowed) {
- resetCurrentParameter();
- parameters.clear();
- invalid = false;
-
- ParamsState state = ParamsState.INIT;
- for (int i = from; i <= chars.length; i++) {
- final char c;
- if (i == chars.length) {
- c = 0;
- } else {
- c = chars[i];
- }
- switch (state) {
- case INIT:
- if (c == ';') {
- state = ParamsState.NAME;
- } else if (c == '.' || c == '/' || c == 0) {
- invalid = true;
- return i;
- }
- break;
-
- case NAME:
- if (c == '=') {
- state = ParamsState.EQUALS;
- } else if (c == '.' || c == '/' || c == 0) {
- invalid = true;
- return i;
- } else if (c == ';') {
- resetCurrentParameter();
- } else {
- name.append(c);
- }
- break;
-
- case EQUALS:
- if (c == '\'') {
- state = ParamsState.QUOTED_VALUE;
- } else if (c == '.' || c == '/' || c == 0) {
- addParameter(); // empty one
- return i;
- } else if (c == ';') {
- state = ParamsState.NAME; // empty one
- addParameter();
- } else {
- state = ParamsState.VALUE;
- value.append(c);
- }
- break;
-
- case QUOTED_VALUE:
- if (c == '\'') {
- state = ParamsState.QUOTE_END;
- addParameter();
- } else if (c == 0) {
- invalid = true;
- return i;
- } else {
- value.append(c);
- }
- break;
-
- case VALUE:
- if (c == ';') {
- state = ParamsState.NAME;
- addParameter();
- } else if ((c == '.' && !dotAllowed) || c == '/' || c == 0) {
- addParameter();
- return i;
- } else {
- value.append(c);
- }
- break;
-
- case QUOTE_END:
- if (c == ';') {
- state = ParamsState.NAME;
- } else {
- return i;
- }
- }
- }
-
- return chars.length;
- }
-
- /**
- * @return Parsed parameters.
- */
- public Map<String, String> getParameters() {
- return parameters;
- }
-
- /**
- * @return True if the {@link #parseParameters(char[], int, boolean)} method failed.
- */
- public boolean isInvalid() {
- return invalid;
- }
-
- private void resetCurrentParameter() {
- name = new StringBuilder();
- value = new StringBuilder();
- }
-
- private void addParameter() {
- parameters.put(name.toString(), value.toString());
- name = new StringBuilder();
- value = new StringBuilder();
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/params/ParsedParameters.java b/src/main/java/org/apache/sling/resourceresolver/impl/params/ParsedParameters.java
deleted file mode 100644
index dea21d8..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/params/ParsedParameters.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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 SF 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.resourceresolver.impl.params;
-
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * Parses path looking for semicolon-separated parameters. Parameters are extracted and exposed as an
- * immutable map. The path without parameters is available as raw path.
- *
- * Parameters should be added immedietaly before or after selectors and extension:
- * {@code /content/test;v='1.0'.html} or {@code /content/test.html;v=1.0}. Quotes can be used to escape the
- * parameter value (it is necessary if the value contains dot and parameter is added before extension).
- */
-public class ParsedParameters {
-
- private final Map<String, String> parameters;
-
- private final String parametersString;
-
- private final String path;
-
- /**
- * Parse path and create parameters object.
- *
- * @param fullPath Path to parse.
- */
- public ParsedParameters(final String fullPath) {
- final PathParser parser = new PathParser();
- parser.parse(fullPath);
-
- parametersString = parser.getParametersString();
- parameters = Collections.unmodifiableMap(parser.getParameters());
- path = parser.getPath();
- }
-
- /**
- * @return Path with no parameters.
- */
- public String getRawPath() {
- return path;
- }
-
- /**
- * @return Path's substring containing parameters
- */
- public String getParametersString() {
- return parametersString;
- }
-
- /**
- * @return Map of the parameters.
- */
- public Map<String, String> getParameters() {
- return parameters;
- }
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/params/PathParser.java b/src/main/java/org/apache/sling/resourceresolver/impl/params/PathParser.java
deleted file mode 100644
index 96469df..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/params/PathParser.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.resourceresolver.impl.params;
-
-import java.util.Collections;
-import java.util.Map;
-
-class PathParser {
-
- /**
- * List of states. V1 and V2 prefixes means variant 1 and 2. In V1, the parameters are added after
- * selectors and extension: {@code /content/test.sel.html;v=1.0}. In V2 parameters are added before
- * selectors and extension: {@code /content/test;v='1.0'.sel.html}
- */
- private enum ParserState {
- INIT, V1_EXTENSION, V1_PARAMS, V2_PARAMS, V2_EXTENSION, SUFFIX, INVALID
- }
-
- private String rawPath;
-
- private String parametersString;
-
- private Map<String, String> parameters;
-
- /**
- * @return Path with no parameters.
- */
- public String getPath() {
- return rawPath;
- }
-
- /**
- * @return Path's substring containing parameters
- */
- public String getParametersString() {
- return parametersString;
- }
-
- /**
- * @return Parsed parameters.
- */
- public Map<String, String> getParameters() {
- return parameters;
- }
-
- /**
- * Parses path containing parameters. Results will be available in {@link #rawPath} and {@link parameters}.
- *
- * @param path
- */
- public void parse(String path) {
- this.rawPath = path;
- this.parameters = Collections.emptyMap();
-
- if (path == null) {
- return;
- }
-
- // indexOf shortcut for the most common case
- final int di = path.indexOf('.');
- final int si = path.indexOf(';');
- if (di == -1 && si == -1) {
- return;
- }
-
- final char[] chars = path.toCharArray();
- final ParametersParser parametersParser = new ParametersParser();
-
- ParserState state = ParserState.INIT;
- int paramsStart = -1, paramsEnd = -1;
-
- int i = (di != -1) ? ((si != -1) ? Math.min(di, si) : di) : si;
- for (; i <= chars.length; i++) {
- final char c;
- if (i == chars.length) {
- c = 0;
- } else {
- c = chars[i];
- }
-
- switch (state) {
- case INIT:
- if (c == '.') {
- state = ParserState.V1_EXTENSION;
- } else if (c == ';') {
- paramsStart = i;
- i = parametersParser.parseParameters(chars, i, false);
- paramsEnd = i--;
- state = parametersParser.isInvalid() ? ParserState.INVALID : ParserState.V2_PARAMS;
- }
- break;
-
- case V1_EXTENSION:
- if (c == '/') {
- state = ParserState.SUFFIX;
- } else if (c == ';') {
- paramsStart = i;
- i = parametersParser.parseParameters(chars, i, true);
- paramsEnd = i--;
- state = parametersParser.isInvalid() ? ParserState.INVALID : ParserState.V1_PARAMS;
- }
- break;
-
- case V1_PARAMS:
- if (c == '/') {
- state = ParserState.SUFFIX;
- } else if (c == '.') {
- state = ParserState.INVALID; // no dots after params
- }
- break;
-
- case V2_PARAMS:
- if (c == '/') {
- state = ParserState.INVALID; // there was no extension, so no suffix is allowed
- } else if (c == '.') {
- state = ParserState.V2_EXTENSION;
- }
- break;
-
- case V2_EXTENSION:
- if (c == '/') {
- state = ParserState.SUFFIX;
- }
- break;
-
- case SUFFIX:
- case INVALID:
- break;
- }
- }
-
- if (state == ParserState.INVALID) {
- paramsStart = paramsEnd = -1;
- } else {
- cutPath(path, paramsStart, paramsEnd);
- parameters = parametersParser.getParameters();
- }
- }
-
- private void cutPath(String path, int from, int to) {
- if (from == -1) {
- rawPath = path;
- parametersString = null;
- } else if (to == -1) {
- rawPath = path.substring(0, from);
- parametersString = path.substring(from);
- } else {
- rawPath = path.substring(0, from) + path.substring(to);
- parametersString = path.substring(from, to);
- }
- }
-
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ProviderContextImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/ProviderContextImpl.java
deleted file mode 100644
index 02dd079..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ProviderContextImpl.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers;
-
-import org.apache.sling.api.resource.path.PathSet;
-import org.apache.sling.spi.resource.provider.ObservationReporter;
-import org.apache.sling.spi.resource.provider.ProviderContext;
-
-/**
- * Provider context implementation
- */
-public class ProviderContextImpl implements ProviderContext {
-
- private volatile ObservationReporter observationReporter;
-
- private volatile PathSet excludedPaths;
-
- public void update(final ObservationReporter observationReporter, PathSet excludedPaths) {
- this.observationReporter = observationReporter;
- this.excludedPaths = excludedPaths;
- }
-
- @Override
- public ObservationReporter getObservationReporter() {
- return observationReporter;
- }
-
- @Override
- public PathSet getExcludedPaths() {
- return excludedPaths;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderHandler.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderHandler.java
deleted file mode 100644
index 73090f7..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderHandler.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers;
-
-import org.apache.sling.resourceresolver.impl.providers.tree.Pathable;
-import org.apache.sling.spi.resource.provider.ProviderContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.osgi.framework.BundleContext;
-
-/**
- * Holder for a resource provider service.
- */
-public class ResourceProviderHandler implements Comparable<ResourceProviderHandler>, Pathable {
-
- /** The bundle context to get the provider. */
- private volatile BundleContext bundleContext;
-
- /** The provider context. */
- private volatile ProviderContextImpl context = new ProviderContextImpl();
-
- /** The resource provider info. */
- private volatile ResourceProviderInfo info;
-
- /** The resource provider. Only available if the provider is active. */
- private volatile ResourceProvider<Object> provider;
-
- /** Flag to indicate whether the service has been used. */
- private volatile boolean isUsed = false;
-
- /**
- * Create a new handler
- * @param bc Bundle context to get the service.
- * @param info Resource provider info.
- */
- public ResourceProviderHandler(final BundleContext bc, final ResourceProviderInfo info) {
- this.info = info;
- this.bundleContext = bc;
- }
-
- /**
- * Get the resource provider info
- * @return The resource provider info or {@code null} if this handler has been deactivated.
- */
- public ResourceProviderInfo getInfo() {
- return this.info;
- }
-
- /**
- * Activate this handler.
- * Get the resource provider service from the service registry.
- * @return {@code true} if the provider could be activated, {@code false} otherwise.
- */
- @SuppressWarnings("unchecked")
- public boolean activate() {
- if ( this.provider == null ) {
- this.provider = (ResourceProvider<Object>) this.bundleContext.getService(this.info.getServiceReference());
- if ( this.provider != null ) {
- this.provider.start(context);
- }
- this.isUsed = false;
- }
- return this.provider != null;
- }
-
- /**
- * Deactivate this handler.
- * Unget the provider service.
- */
- public void deactivate() {
- if ( this.provider != null ) {
- this.provider.stop();
- this.provider = null;
- this.context.update(null, null);
- this.bundleContext.ungetService(this.info.getServiceReference());
- }
- }
-
- /**
- * Clear all references.
- */
- public void dispose() {
- this.info = null;
- this.bundleContext = null;
- this.context = null;
- this.isUsed = false;
- }
-
- /**
- * Get the resource provider.
- * @return The resource provider or {@code null} if it is not active.
- */
- public ResourceProvider<Object> getResourceProvider() {
- return this.provider;
- }
-
- /**
- * Get the resource provider and mark it as used.
- * @return The resource provider or {@code null} if it is not active.
- */
- public ResourceProvider<Object> useResourceProvider() {
- this.isUsed = true;
- return this.provider;
- }
-
- /**
- * Check whether this provider has been used.
- * @return
- */
- public boolean isUsed() {
- return this.isUsed;
- }
-
- @Override
- public int compareTo(final ResourceProviderHandler o) {
- if ( this.getInfo() == null ) {
- if ( o.getInfo() == null ) {
- return 0;
- }
- return 1;
- }
- if ( o.getInfo() == null ) {
- return -1;
- }
- return this.getInfo().compareTo(o.getInfo());
- }
-
- /**
- * Get the path where the provider is mounted.
- * @return The mount path.
- */
- @Override
- public String getPath() {
- return this.getInfo().getPath();
- }
-
- /**
- * Update the provider
- */
- public void update() {
- if ( this.provider != null ) {
- this.provider.update(ProviderContext.EXCLUDED_PATHS_CHANGED + ProviderContext.OBSERVATION_LISTENER_CHANGED);
- }
- }
-
- /**
- * Get the provider context.
- * @return The provider context
- */
- public ProviderContextImpl getProviderContext() {
- return this.context;
- }
-
- @Override
- public String toString() {
- return "[" + getClass().getSimpleName() +"# provider: " + provider + " ]";
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderInfo.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderInfo.java
deleted file mode 100644
index 0900e5e..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderInfo.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers;
-
-import org.apache.sling.api.resource.runtime.dto.AuthType;
-import org.apache.sling.commons.osgi.PropertiesUtil;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.osgi.framework.ServiceReference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Information about a registered resource provider
- */
-public class ResourceProviderInfo implements Comparable<ResourceProviderInfo> {
-
- private static final Logger logger = LoggerFactory.getLogger(ResourceProviderInfo.class);
-
- private final ServiceReference ref;
-
- private final String path;
-
- private final String name;
-
- private final boolean useResourceAccessSecurity;
-
- private final AuthType authType;
-
- private final boolean modifiable;
-
- private final boolean adaptable;
-
- private final boolean refreshable;
-
- private final boolean attributable;
-
- public ResourceProviderInfo(final ServiceReference ref) {
- this.ref = ref;
- this.path = PropertiesUtil.toString(ref.getProperty(ResourceProvider.PROPERTY_ROOT), "");
- this.name = PropertiesUtil.toString(ref.getProperty(ResourceProvider.PROPERTY_NAME), null);
- this.useResourceAccessSecurity = PropertiesUtil.toBoolean(ref.getProperty(ResourceProvider.PROPERTY_USE_RESOURCE_ACCESS_SECURITY), false);
- final String authType = PropertiesUtil.toString(ref.getProperty(ResourceProvider.PROPERTY_AUTHENTICATE), AuthType.no.name());
- AuthType aType = null;
- try {
- aType = AuthType.valueOf(authType);
- } catch ( final IllegalArgumentException iae) {
- logger.error("Illegal auth type {} for resource provider {}", authType, name);
- }
- this.authType = aType;
- this.modifiable = PropertiesUtil.toBoolean(ref.getProperty(ResourceProvider.PROPERTY_MODIFIABLE), false);
- this.adaptable = PropertiesUtil.toBoolean(ref.getProperty(ResourceProvider.PROPERTY_ADAPTABLE), false);
- this.refreshable = PropertiesUtil.toBoolean(ref.getProperty(ResourceProvider.PROPERTY_REFRESHABLE), false);
- this.attributable = PropertiesUtil.toBoolean(ref.getProperty(ResourceProvider.PROPERTY_ATTRIBUTABLE), false);
- }
-
- public boolean isValid() {
- // TODO - do real path check
- if ( !path.startsWith("/") ) {
- logger.debug("ResourceProvider path does not start with /, invalid: {}", path);
- return false;
- }
- if ( this.authType == null ) {
- logger.debug("ResourceProvider has null authType, invalid");
- return false;
- }
- return true;
- }
-
- public ServiceReference getServiceReference() {
- return this.ref;
- }
-
- public String getPath() {
- return this.path;
- }
-
- @Override
- public int compareTo(final ResourceProviderInfo o) {
- int result = path.compareTo(o.path);
- if ( result == 0 ) {
- result = o.ref.compareTo(ref);
- }
- return result;
- }
-
- @Override
- public String toString() {
- return "ResourceProviderInfo [ref=" + ref + ", path=" + path + ", useResourceAccessSecurity="
- + useResourceAccessSecurity + ", authType=" + authType + ", modifiable=" + modifiable + "]";
- }
-
- public AuthType getAuthType() {
- return this.authType;
- }
-
- public boolean isModifiable() {
- return this.modifiable;
- }
-
- public boolean isAdaptable() {
- return adaptable;
- }
-
- public boolean isRefreshable() {
- return refreshable;
- }
-
- public boolean isAttributable() {
- return attributable;
- }
-
- public String getName() {
- return this.name;
- }
-
- public boolean getUseResourceAccessSecurity() {
- return this.useResourceAccessSecurity;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorage.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorage.java
deleted file mode 100644
index dac3616..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorage.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.sling.api.resource.runtime.dto.AuthType;
-import org.apache.sling.resourceresolver.impl.providers.tree.PathTree;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-
-/**
- * The resource provider storage contains all available handlers
- * and keeps a list of handlers for specific categories to avoid
- * iterating over all handlers for the different use cases.
- */
-public class ResourceProviderStorage {
-
- private final List<ResourceProviderHandler> allHandlers;
-
- private final List<ResourceProviderHandler> authRequiredHandlers;
-
- private final List<ResourceProviderHandler> adaptableHandlers;
-
- private final List<ResourceProviderHandler> attributableHandlers;
-
- private final List<ResourceProviderHandler> languageQueryableHandlers;
-
- private final PathTree<ResourceProviderHandler> handlersTree;
-
- public ResourceProviderStorage(List<ResourceProviderHandler> handlers) {
- this.allHandlers = handlers;
- this.authRequiredHandlers = new ArrayList<ResourceProviderHandler>();
- this.adaptableHandlers = new ArrayList<ResourceProviderHandler>();
- this.attributableHandlers = new ArrayList<ResourceProviderHandler>();
- this.languageQueryableHandlers = new ArrayList<ResourceProviderHandler>();
- for (ResourceProviderHandler h : allHandlers) {
- ResourceProviderInfo info = h.getInfo();
- if (info.getAuthType() == AuthType.required) {
- this.authRequiredHandlers.add(h);
- }
- if (info.isAdaptable()) {
- this.adaptableHandlers.add(h);
- }
- if (info.isAttributable()) {
- this.attributableHandlers.add(h);
- }
- final ResourceProvider<Object> rp = h.getResourceProvider();
- if (rp != null && rp.getQueryLanguageProvider() != null) {
- this.languageQueryableHandlers.add(h);
- }
- }
- this.handlersTree = new PathTree<ResourceProviderHandler>(handlers);
- }
-
- public List<ResourceProviderHandler> getAllHandlers() {
- return allHandlers;
- }
-
- public List<ResourceProviderHandler> getAuthRequiredHandlers() {
- return authRequiredHandlers;
- }
-
- public List<ResourceProviderHandler> getAdaptableHandlers() {
- return adaptableHandlers;
- }
-
- public List<ResourceProviderHandler> getAttributableHandlers() {
- return attributableHandlers;
- }
-
- public List<ResourceProviderHandler> getLanguageQueryableHandlers() {
- return languageQueryableHandlers;
- }
-
- public PathTree<ResourceProviderHandler> getTree() {
- return handlersTree;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorageProvider.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorageProvider.java
deleted file mode 100644
index 887af12..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderStorageProvider.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers;
-
-/**
- * Interface which allows access to a ResourceProviderStorage object.
- */
-public interface ResourceProviderStorageProvider {
-
- ResourceProviderStorage getResourceProviderStorage();
-
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java
deleted file mode 100644
index 6cf6946..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.sling.api.SlingConstants;
-import org.apache.sling.api.resource.observation.ResourceChange;
-import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
-import org.apache.sling.api.resource.path.Path;
-import org.apache.sling.api.resource.path.PathSet;
-import org.apache.sling.api.resource.runtime.dto.AuthType;
-import org.apache.sling.api.resource.runtime.dto.FailureReason;
-import org.apache.sling.api.resource.runtime.dto.ResourceProviderDTO;
-import org.apache.sling.api.resource.runtime.dto.ResourceProviderFailureDTO;
-import org.apache.sling.api.resource.runtime.dto.RuntimeDTO;
-import org.apache.sling.resourceresolver.impl.legacy.LegacyResourceProviderWhiteboard;
-import org.apache.sling.spi.resource.provider.ObservationReporter;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This service keeps track of all resource providers.
- */
-public class ResourceProviderTracker implements ResourceProviderStorageProvider {
-
- public interface ObservationReporterGenerator {
-
- ObservationReporter create(final Path path, final PathSet excludes);
-
- ObservationReporter createProviderReporter();
- }
-
- public interface ChangeListener {
-
- void providerAdded();
-
- void providerRemoved(String name, String pid, boolean stateful, boolean used);
- }
-
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- private final Map<ServiceReference, ResourceProviderInfo> infos = new ConcurrentHashMap<ServiceReference, ResourceProviderInfo>();
-
- private volatile BundleContext bundleContext;
-
- private volatile ServiceTracker tracker;
-
- private final Map<String, List<ResourceProviderHandler>> handlers = new HashMap<String, List<ResourceProviderHandler>>();
-
- private final Map<ResourceProviderInfo, FailureReason> invalidProviders = new ConcurrentHashMap<ResourceProviderInfo, FailureReason>();
-
- private volatile EventAdmin eventAdmin;
-
- private volatile ObservationReporterGenerator reporterGenerator;
-
- private volatile ResourceProviderStorage storage;
-
- private volatile ObservationReporter providerReporter;
-
- private volatile ChangeListener listener;
-
- public void activate(final BundleContext bundleContext, final EventAdmin eventAdmin, final ChangeListener listener) {
- this.bundleContext = bundleContext;
- this.eventAdmin = eventAdmin;
- this.listener = listener;
- this.tracker = new ServiceTracker(bundleContext,
- ResourceProvider.class.getName(),
- new ServiceTrackerCustomizer() {
-
- @Override
- public void removedService(final ServiceReference reference, final Object service) {
- final ServiceReference ref = (ServiceReference)service;
- final ResourceProviderInfo info = infos.remove(ref);
- if ( info != null ) {
- Object pid = ref.getProperty(Constants.SERVICE_PID);
- if ( pid != null && !(pid instanceof String) ) {
- pid = null;
- }
- unregister(info, (String)pid);
- }
- }
-
- @Override
- public void modifiedService(final ServiceReference reference, final Object service) {
- removedService(reference, service);
- addingService(reference);
- }
-
- @Override
- public Object addingService(final ServiceReference reference) {
- final ResourceProviderInfo info = new ResourceProviderInfo(reference);
- infos.put(reference, info);
- register(info);
- return reference;
- }
- });
- this.tracker.open();
- }
-
- public void deactivate() {
- this.listener = null;
- this.eventAdmin = null;
- this.providerReporter = null;
- if ( this.tracker != null ) {
- this.tracker.close();
- this.tracker = null;
- }
- this.infos.clear();
- this.handlers.clear();
- this.invalidProviders.clear();
- }
-
- public void setObservationReporterGenerator(final ObservationReporterGenerator generator) {
- this.providerReporter = generator.createProviderReporter();
- synchronized ( this.handlers ) {
- this.reporterGenerator = generator;
- for (List<ResourceProviderHandler> list : handlers.values()) {
- final ResourceProviderHandler h = list.get(0);
- if (h != null) {
- updateProviderContext(h);
- h.update();
- }
- }
- }
- }
-
- /**
- * Try to register a new resource provider.
- * @param info The resource provider info.
- */
- private void register(final ResourceProviderInfo info) {
- if ( info.isValid() ) {
- logger.debug("Registering new resource provider {}", info);
- final List<ProviderEvent> events = new ArrayList<ResourceProviderTracker.ProviderEvent>();
- boolean providerAdded = false;
- ResourceProviderHandler deactivateHandler = null;
-
- synchronized ( this.handlers ) {
- List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
- if ( matchingHandlers == null ) {
- matchingHandlers = new ArrayList<ResourceProviderHandler>();
- this.handlers.put(info.getPath(), matchingHandlers);
- }
- final ResourceProviderHandler handler = new ResourceProviderHandler(bundleContext, info);
- matchingHandlers.add(handler);
- Collections.sort(matchingHandlers);
- if ( matchingHandlers.get(0) == handler ) {
- if ( !this.activate(handler) ) {
- matchingHandlers.remove(handler);
- if ( matchingHandlers.isEmpty() ) {
- this.handlers.remove(info.getPath());
- }
- } else {
- providerAdded = true;
- events.add(new ProviderEvent(true, info));
- if ( matchingHandlers.size() > 1 ) {
- deactivateHandler = matchingHandlers.get(1);
- }
- storage = null;
- }
- }
- }
- final ChangeListener cl = this.listener;
- if ( providerAdded && cl != null ) {
- cl.providerAdded();
- }
- // we have to check for deactivated handlers
- if ( deactivateHandler != null ) {
- final ResourceProviderInfo handlerInfo = deactivateHandler.getInfo();
- if ( cl != null ) {
- Object pid = handlerInfo.getServiceReference().getProperty(Constants.SERVICE_PID);
- if ( pid != null && !(pid instanceof String) ) {
- pid = null;
- }
- cl.providerRemoved(handlerInfo.getName(), (String)pid,
- handlerInfo.getAuthType() != AuthType.no,
- deactivateHandler.isUsed());
- }
- synchronized ( this.handlers ) {
- this.deactivate(deactivateHandler);
- events.add(new ProviderEvent(false, handlerInfo));
- storage = null;
- }
- }
- this.postEvents(events);
- } else {
- logger.warn("Ignoring invalid resource provider {}", info);
- this.invalidProviders.put(info, FailureReason.invalid);
- }
- }
-
- /**
- * Unregister a resource provider.
- * @param info The resource provider info.
- */
- private void unregister(final ResourceProviderInfo info, final String pid) {
- final boolean isInvalid;
- synchronized ( this.invalidProviders ) {
- isInvalid = this.invalidProviders.remove(info) != null;
- }
-
- if ( !isInvalid ) {
- logger.debug("Unregistering resource provider {}", info);
- final List<ProviderEvent> events = new ArrayList<ResourceProviderTracker.ProviderEvent>();
- ResourceProviderHandler deactivateHandler = null;
- synchronized (this.handlers) {
- final List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
- if ( matchingHandlers != null ) {
- final ResourceProviderHandler firstHandler = matchingHandlers.get(0);
- if ( firstHandler.getInfo() == info ) {
- deactivateHandler = firstHandler;
-
- }
- }
- }
- if ( deactivateHandler != null ) {
- final ChangeListener cl = this.listener;
- if ( cl != null ) {
- cl.providerRemoved(info.getName(), pid,
- info.getAuthType() != AuthType.no,
- deactivateHandler.isUsed());
- }
- boolean providerAdded = false;
- synchronized ( this.handlers ) {
- this.deactivate(deactivateHandler);
- storage = null;
-
- final List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
- if ( matchingHandlers != null && !matchingHandlers.isEmpty() ) {
- final ResourceProviderHandler firstHandler = matchingHandlers.get(0);
- boolean doActivateNext = firstHandler.getInfo() == info;
-
- if (removeHandlerByInfo(info, matchingHandlers)) {
- while (doActivateNext && !matchingHandlers.isEmpty()) {
- if (this.activate(matchingHandlers.get(0))) {
- doActivateNext = false;
- events.add(new ProviderEvent(true, matchingHandlers.get(0).getInfo()));
- providerAdded = true;
- } else {
- matchingHandlers.remove(0);
- }
- }
- }
- if (matchingHandlers.isEmpty()) {
- this.handlers.remove(info.getPath());
- }
- }
- }
- if ( providerAdded && cl != null ) {
- if ( cl != null ) {
- cl.providerAdded();
- }
- }
- events.add(new ProviderEvent(false,info));
-
- }
- this.postEvents(events);
- } else {
- logger.debug("Unregistering invalid resource provider {}", info);
- }
- }
-
- /**
- * Search the info in the list of handlers.
- * @param info The provider info
- * @param infos The list of handlers
- * @return {@code true} if the info got removed.
- */
- private boolean removeHandlerByInfo(final ResourceProviderInfo info, final List<ResourceProviderHandler> infos) {
- Iterator<ResourceProviderHandler> it = infos.iterator();
- boolean removed = false;
- while (it.hasNext()) {
- final ResourceProviderHandler h = it.next();
- if (h.getInfo() == info) {
- it.remove();
- h.dispose();
- removed = true;
- break;
- }
- }
- return removed;
- }
-
- /**
- * Activate a resource provider
- * @param handler The provider handler
- */
- private boolean activate(final ResourceProviderHandler handler) {
- updateProviderContext(handler);
- if ( !handler.activate() ) {
- logger.warn("Activating resource provider {} failed", handler.getInfo());
- this.invalidProviders.put(handler.getInfo(), FailureReason.service_not_gettable);
-
- return false;
- }
- logger.debug("Activated resource provider {}", handler.getInfo());
- return true;
- }
-
- /**
- * Deactivate a resource provider
- * @param handler The provider handler
- */
- private void deactivate(final ResourceProviderHandler handler) {
- handler.deactivate();
- logger.debug("Deactivated resource provider {}", handler.getInfo());
- }
-
- /**
- * Post a change event through the event admin
- * @param event
- */
- private void postOSGiEvent(final ProviderEvent event) {
- final EventAdmin ea = this.eventAdmin;
- if ( ea != null ) {
- final Dictionary<String, Object> eventProps = new Hashtable<String, Object>();
- eventProps.put(SlingConstants.PROPERTY_PATH, event.path);
- if (event.pid != null) {
- eventProps.put(Constants.SERVICE_PID, event.pid);
- }
- ea.postEvent(new Event(event.isAdd ? SlingConstants.TOPIC_RESOURCE_PROVIDER_ADDED : SlingConstants.TOPIC_RESOURCE_PROVIDER_REMOVED,
- eventProps));
- }
- }
-
- /**
- * Post a change event for a resource provider change
- * @param type The change type
- * @param info The resource provider
- */
- private void postResourceProviderChange(final ProviderEvent event) {
- final ObservationReporter or = this.providerReporter;
- if ( or != null ) {
- final ResourceChange change = new ResourceChange(event.isAdd ? ChangeType.PROVIDER_ADDED : ChangeType.PROVIDER_REMOVED,
- event.path, false, null, null, null);
- or.reportChanges(Collections.singletonList(change), false);
- }
- }
-
- public void fill(final RuntimeDTO dto) {
- final List<ResourceProviderDTO> dtos = new ArrayList<ResourceProviderDTO>();
- final List<ResourceProviderFailureDTO> failures = new ArrayList<ResourceProviderFailureDTO>();
-
- synchronized ( this.handlers ) {
- for(final List<ResourceProviderHandler> handlers : this.handlers.values()) {
- boolean isFirst = true;
- for(final ResourceProviderHandler h : handlers) {
- final ResourceProviderDTO d;
- if ( isFirst ) {
- d = new ResourceProviderDTO();
- dtos.add(d);
- isFirst = false;
- } else {
- d = new ResourceProviderFailureDTO();
- ((ResourceProviderFailureDTO)d).reason = FailureReason.shadowed;
- failures.add((ResourceProviderFailureDTO)d);
- }
- fill(d, h);
- }
- }
- }
- synchronized ( this.invalidProviders ) {
- for(final Map.Entry<ResourceProviderInfo, FailureReason> entry : this.invalidProviders.entrySet()) {
- final ResourceProviderFailureDTO d = new ResourceProviderFailureDTO();
- fill(d, entry.getKey());
- d.reason = entry.getValue();
- failures.add(d);
- }
- }
- dto.providers = dtos.toArray(new ResourceProviderDTO[dtos.size()]);
- dto.failedProviders = failures.toArray(new ResourceProviderFailureDTO[failures.size()]);
- }
-
- @Override
- public ResourceProviderStorage getResourceProviderStorage() {
- ResourceProviderStorage result = storage;
- if (result == null) {
- synchronized (this.handlers) {
- if (storage == null) {
- final List<ResourceProviderHandler> handlerList = new ArrayList<ResourceProviderHandler>();
- for (List<ResourceProviderHandler> list : handlers.values()) {
- ResourceProviderHandler h = list.get(0);
- if (h != null) {
- handlerList.add(h);
- }
- }
- storage = new ResourceProviderStorage(handlerList);
- }
- result = storage;
- }
- }
- return result;
- }
-
- private void fill(final ResourceProviderDTO d, final ResourceProviderInfo info) {
- d.adaptable = info.isAdaptable();
- d.attributable = info.isAttributable();
- d.authType = info.getAuthType();
- d.modifiable = info.isModifiable();
- d.name = info.getName();
- d.path = info.getPath();
- d.refreshable = info.isRefreshable();
- d.serviceId = (Long)info.getServiceReference().getProperty(Constants.SERVICE_ID);
- d.supportsQueryLanguage = false;
- d.useResourceAccessSecurity = info.getUseResourceAccessSecurity();
- }
-
- private void fill(final ResourceProviderDTO d, final ResourceProviderHandler handler) {
- fill(d, handler.getInfo());
- final ResourceProvider<?> provider = handler.getResourceProvider();
- if ( provider != null ) {
- d.supportsQueryLanguage = provider.getQueryLanguageProvider() != null;
- }
- }
-
- private void updateProviderContext(final ResourceProviderHandler handler) {
- final Set<String> excludedPaths = new HashSet<String>();
- final Path handlerPath = new Path(handler.getPath());
- for(final String otherPath : handlers.keySet()) {
- if ( !handler.getPath().equals(otherPath) && handlerPath.matches(otherPath) ) {
- excludedPaths.add(otherPath);
- }
- }
- final PathSet excludedPathSet = PathSet.fromStringCollection(excludedPaths);
- handler.getProviderContext().update(
- reporterGenerator.create(handlerPath, excludedPathSet),
- excludedPathSet);
- }
-
- private void postEvents(final List<ProviderEvent> events) {
- if ( events.isEmpty() ) {
- return;
- }
- if ( this.listener == null && this.providerReporter == null ) {
- return;
- }
- final Thread t = new Thread(new Runnable() {
-
- @Override
- public void run() {
- for(final ProviderEvent e : events) {
- postOSGiEvent(e);
- postResourceProviderChange(e);
- }
- }
- });
- t.setName("Apache Sling Resource Provider Change Notifier");
- t.setDaemon(true);
-
- t.start();
- }
-
- private static final class ProviderEvent {
- public final boolean isAdd;
- public final Object pid;
- public final String path;
-
- public ProviderEvent(final boolean isAdd, final ResourceProviderInfo info) {
- this.isAdd = isAdd;
- this.path = info.getPath();
- Object pid = info.getServiceReference().getProperty(Constants.SERVICE_PID);
- if (pid == null) {
- pid = info.getServiceReference().getProperty(LegacyResourceProviderWhiteboard.ORIGINAL_SERVICE_PID);
- }
- this.pid = pid;
- }
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/RuntimeServiceImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/RuntimeServiceImpl.java
deleted file mode 100644
index c163100..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/RuntimeServiceImpl.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers;
-
-import org.apache.sling.api.resource.runtime.RuntimeService;
-import org.apache.sling.api.resource.runtime.dto.RuntimeDTO;
-
-public class RuntimeServiceImpl implements RuntimeService {
-
- private final ResourceProviderTracker tracker;
-
- public RuntimeServiceImpl(final ResourceProviderTracker tracker) {
- this.tracker = tracker;
- }
-
- @Override
- public RuntimeDTO getRuntimeDTO() {
- final RuntimeDTO dto = new RuntimeDTO();
- tracker.fill(dto);
- return dto;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java
deleted file mode 100644
index 38d27c4..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProvider.java
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers.stateful;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.security.AccessSecurityException;
-import org.apache.sling.api.security.ResourceAccessSecurity;
-import org.apache.sling.resourceresolver.impl.ResourceAccessSecurityTracker;
-import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
-import org.apache.sling.resourceresolver.impl.helper.AbstractIterator;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This {@link AuthenticatedResourceProvider} implementation keeps a resource
- * provider and the authentication information (through the {@link ResolveContext}.
- *
- * The methods are similar to {@link ResourceProvider}.
- */
-public class AuthenticatedResourceProvider {
-
- private static final Logger logger = LoggerFactory.getLogger(ResourceResolverImpl.class);
-
- public static final AuthenticatedResourceProvider UNAUTHENTICATED_PROVIDER = new AuthenticatedResourceProvider(null, false, null, null);
-
- private final ResourceProviderHandler providerHandler;
-
- private final ResolveContext<Object> resolveContext;
-
- private final ResourceAccessSecurityTracker tracker;
-
- private final boolean useRAS;
-
- public AuthenticatedResourceProvider(@Nonnull final ResourceProviderHandler providerHandler,
- final boolean useRAS,
- @Nonnull final ResolveContext<Object> resolveContext,
- @Nonnull final ResourceAccessSecurityTracker tracker) {
- this.providerHandler = providerHandler;
- this.resolveContext = resolveContext;
- this.tracker = tracker;
- this.useRAS = useRAS;
- }
-
- /**
- * Get the resolve context.
- * @return The resolve context
- */
- public @Nonnull ResolveContext<Object> getResolveContext() {
- return this.resolveContext;
- }
-
- /**
- * #see {@link ResourceProvider#refresh(ResolveContext)}
- */
- public void refresh() {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- rp.refresh(this.resolveContext);
- }
- }
-
- /**
- * #see {@link ResourceProvider#isLive(ResolveContext)}
- */
- public boolean isLive() {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- return rp.isLive(this.resolveContext);
- }
- return false;
- }
-
- /**
- * #see {@link ResourceProvider#getParent(ResolveContext, Resource)}
- */
- public Resource getParent(final Resource child) {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- return wrapResource(rp.getParent(this.resolveContext, child));
- }
- return null;
- }
-
- /**
- * #see {@link ResourceProvider#getResource(ResolveContext, String, ResourceContext, Resource)}
- */
- public Resource getResource(final String path, final Resource parent, final Map<String, String> parameters) {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp == null ) {
- return null;
- }
- final ResourceContext resourceContext;
- if ( parameters != null ) {
- resourceContext = new ResourceContext() {
-
- @Override
- public Map<String, String> getResolveParameters() {
- return parameters;
- }
- };
- } else {
- resourceContext = ResourceContext.EMPTY_CONTEXT;
- }
- return wrapResource(rp.getResource(this.resolveContext, path, resourceContext, parent));
- }
-
- /**
- * #see {@link ResourceProvider#listChildren(ResolveContext, Resource)}
- */
- public Iterator<Resource> listChildren(final Resource parent) {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- return wrapIterator(rp.listChildren(this.resolveContext, parent));
- }
- return null;
- }
-
- /**
- * #see {@link ResourceProvider#getAttributeNames(ResolveContext)}
- */
- public void getAttributeNames(final Set<String> attributeNames) {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- Collection<String> rpAttributeNames = rp.getAttributeNames(this.resolveContext);
- if (rpAttributeNames != null) {
- attributeNames.addAll(rpAttributeNames);
- }
- }
- }
-
- /**
- * #see {@link ResourceProvider#getAttribute(ResolveContext, String)}
- */
- public Object getAttribute(final String name) {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- return rp.getAttribute(this.resolveContext, name);
- }
- return null;
- }
-
- /**
- * #see {@link ResourceProvider#create(ResolveContext, String, Map)}
- */
- public Resource create(final ResourceResolver resolver,
- final String path,
- final Map<String, Object> properties)
- throws PersistenceException {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null && this.canCreate(resolver, path) ) {
- return rp.create(this.resolveContext, path, properties);
- }
- return null;
- }
-
- /**
- * #see {@link ResourceProvider#delete(ResolveContext, Resource)}
- */
- public void delete(final Resource resource) throws PersistenceException {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null && this.canDelete(resource) ) {
- rp.delete(this.resolveContext, resource);
- } else {
- throw new PersistenceException("Unable to delete resource " + resource.getPath());
- }
- }
-
- /**
- * #see {@link ResourceProvider#revert(ResolveContext)}
- */
- public void revert() {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- rp.revert(this.resolveContext);
- }
- }
-
- /**
- * #see {@link ResourceProvider#commit(ResolveContext)}
- */
- public void commit() throws PersistenceException {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- rp.commit(this.resolveContext);
- }
- }
-
- /**
- * #see {@link ResourceProvider#hasChanges(ResolveContext)}
- */
- public boolean hasChanges() {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- return rp.hasChanges(this.resolveContext);
- }
- return false;
- }
-
- /**
- * #see {@link ResourceProvider#getQueryLanguageProvider()}
- */
- private QueryLanguageProvider<Object> getQueryLanguageProvider() {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- return rp.getQueryLanguageProvider();
- }
- return null;
- }
-
- /**
- * #see {@link QueryLanguageProvider#getSupportedLanguages(ResolveContext)}
- */
- public String[] getSupportedLanguages() {
- final QueryLanguageProvider<Object> jcrQueryProvider = getQueryLanguageProvider();
- if (jcrQueryProvider == null) {
- return null;
- }
- return jcrQueryProvider.getSupportedLanguages(this.resolveContext);
- }
-
- /**
- * #see {@link QueryLanguageProvider}{@link #findResources(String, String)}
- */
- public Iterator<Resource> findResources(final String query, final String language) {
- final QueryLanguageProvider<Object> jcrQueryProvider = getQueryLanguageProvider();
- if (jcrQueryProvider == null) {
- return null;
- }
- return wrapIterator(jcrQueryProvider.findResources(this.resolveContext, transformQuery(query, language), language));
- }
-
- /**
- * #see {@link QueryLanguageProvider#queryResources(ResolveContext, String, String)}
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public Iterator<Map<String, Object>> queryResources(final String query, final String language) {
- final QueryLanguageProvider<Object> jcrQueryProvider = getQueryLanguageProvider();
- if (jcrQueryProvider == null) {
- return null;
- }
- return (Iterator) jcrQueryProvider.queryResources(this.resolveContext, transformQuery(query, language), language);
- }
-
- /**
- * #see {@link ResourceProvider#adaptTo(ResolveContext, Class)}
- */
- public <AdapterType> AdapterType adaptTo(final Class<AdapterType> type) {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- return rp.adaptTo(this.resolveContext, type);
- }
- return null;
- }
-
- /**
- * #see {@link ResourceProvider#copy(ResolveContext, String, String)}
- */
- public boolean copy(final String srcAbsPath, final String destAbsPath) throws PersistenceException {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- return rp.copy(this.resolveContext, srcAbsPath, destAbsPath);
- }
- return false;
- }
-
- /**
- * #see {@link ResourceProvider#move(ResolveContext, String, String)}
- */
- public boolean move(final String srcAbsPath, final String destAbsPath) throws PersistenceException {
- final ResourceProvider<Object> rp = this.providerHandler.getResourceProvider();
- if ( rp != null ) {
- return rp.move(this.resolveContext, srcAbsPath, destAbsPath);
- }
- return false;
- }
-
- private boolean canCreate(final ResourceResolver resolver, final String path) {
- boolean allowed = true;
- if ( this.useRAS ) {
- final ResourceAccessSecurity security = tracker.getProviderResourceAccessSecurity();
- if ( security != null ) {
- allowed = security.canCreate(path, resolver);
- } else {
- allowed = false;
- }
- }
-
- if ( allowed ) {
- final ResourceAccessSecurity security = tracker.getApplicationResourceAccessSecurity();
- if (security != null) {
- allowed = security.canCreate(path, resolver);
- }
- }
- return allowed;
- }
-
- private boolean canDelete(final Resource resource) {
- boolean allowed = true;
- if ( this.useRAS ) {
- final ResourceAccessSecurity security = tracker.getProviderResourceAccessSecurity();
- if ( security != null ) {
- allowed = security.canDelete(resource);
- } else {
- allowed = false;
- }
- }
-
- if ( allowed ) {
- final ResourceAccessSecurity security = tracker.getApplicationResourceAccessSecurity();
- if (security != null) {
- allowed = security.canDelete(resource);
- }
- }
- return allowed;
- }
-
- /**
- * applies resource access security if configured
- */
- private String transformQuery ( final String query, final String language ) {
- String returnValue = query;
-
- if (this.useRAS) {
- final ResourceAccessSecurity resourceAccessSecurity = tracker
- .getProviderResourceAccessSecurity();
- if (resourceAccessSecurity != null) {
- try {
- returnValue = resourceAccessSecurity.transformQuery(
- returnValue, language, this.resolveContext.getResourceResolver());
- } catch (AccessSecurityException e) {
- logger.error(
- "AccessSecurityException occurred while trying to transform the query {} (language {}).",
- new Object[] { query, language }, e);
- }
- }
- }
-
- final ResourceAccessSecurity resourceAccessSecurity = tracker
- .getApplicationResourceAccessSecurity();
- if (resourceAccessSecurity != null) {
- try {
- returnValue = resourceAccessSecurity.transformQuery(
- returnValue, language, this.resolveContext.getResourceResolver());
- } catch (AccessSecurityException e) {
- logger.error(
- "AccessSecurityException occurred while trying to transform the query {} (language {}).",
- new Object[] { query, language }, e);
- }
- }
-
- return returnValue;
- }
-
- /**
- * Wrap a resource with additional resource access security
- * @param rsrc The resource or {@code null}.
- * @return The wrapped resource or {@code null}
- */
- private @CheckForNull Resource wrapResource(@CheckForNull Resource rsrc) {
- Resource returnValue = null;
-
- if (useRAS && rsrc != null) {
- final ResourceAccessSecurity resourceAccessSecurity = tracker.getProviderResourceAccessSecurity();
- if (resourceAccessSecurity != null) {
- returnValue = resourceAccessSecurity.getReadableResource(rsrc);
- }
- } else {
- returnValue = rsrc;
- }
-
- if ( returnValue != null ) {
- final ResourceAccessSecurity resourceAccessSecurity = tracker.getApplicationResourceAccessSecurity();
- if (resourceAccessSecurity != null) {
- returnValue = resourceAccessSecurity.getReadableResource(returnValue);
- }
- }
-
- return returnValue;
- }
-
- private Iterator<Resource> wrapIterator(Iterator<Resource> iterator) {
- if (iterator == null) {
- return iterator;
- } else {
- return new SecureIterator(iterator);
- }
- }
-
- private class SecureIterator extends AbstractIterator<Resource> {
-
- private final Iterator<Resource> iterator;
-
- public SecureIterator(Iterator<Resource> iterator) {
- this.iterator = iterator;
- }
-
- @Override
- protected Resource seek() {
- while (iterator.hasNext()) {
- final Resource resource = wrapResource(iterator.next());
- if (resource != null) {
- return resource;
- }
- }
- return null;
- }
- }
-
- @Override
- public String toString() {
- return "[" + getClass().getSimpleName() + "# rp: " + this.providerHandler.getResourceProvider() + "]";
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/BasicResolveContext.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/BasicResolveContext.java
deleted file mode 100644
index 6b0335e..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/BasicResolveContext.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers.stateful;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.resourceresolver.impl.helper.ResourceResolverControl;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.tree.Node;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-
-/**
- * Resolve context implementation for a resource provider.
- *
- * This class is not thread safe (same as the resource resolver).
- */
-public class BasicResolveContext<T> implements ResolveContext<T> {
-
- private final ResourceResolver resolver;
-
- private final ProviderManager resolveContextManager;
-
- private final ResourceResolverControl control;
-
- private final T providerState;
-
- private final String parentPath;
-
- public BasicResolveContext(@Nonnull final ResourceResolver resolver,
- @Nonnull final ProviderManager resolveContextManager,
- @Nonnull final ResourceResolverControl control,
- @CheckForNull final T providerState,
- @Nonnull final String parentPath) {
- this.resolver = resolver;
- this.resolveContextManager = resolveContextManager;
- this.parentPath = parentPath;
- this.providerState = providerState;
- this.control = control;
- }
-
- @Override
- public ResourceResolver getResourceResolver() {
- return this.resolver;
- }
-
- @Override
- public T getProviderState() {
- return providerState;
- }
-
- @Override
- public ResolveContext<?> getParentResolveContext() {
- final Object[] providerAndContext = getParentProviderAndContext();
- return (ResolveContext<?>) (providerAndContext != null ? providerAndContext[1] : null);
- }
-
- @Override
- public ResourceProvider<?> getParentResourceProvider() {
- final Object[] providerAndContext = getParentProviderAndContext();
- return (ResourceProvider<?>) (providerAndContext != null ? providerAndContext[0] : null);
- }
-
- private Object[] getParentProviderAndContext() {
- ResourceProvider<?> parentProvider = null;
- ResolveContext<?> parentResolveContext = null;
- if ( this.parentPath != null ) {
- String path = this.parentPath;
- while ( path != null && parentProvider == null ) {
- final Node<ResourceProviderHandler> node = this.control.getResourceProviderStorage().getTree().getBestMatchingNode(path);
- if ( node != null ) {
- final ResourceProviderHandler handler = node.getValue();
- try {
- parentResolveContext = this.resolveContextManager.getOrCreateResolveContext(handler, this.control);
- if ( parentResolveContext != null ) {
- parentProvider = handler.getResourceProvider();
- }
- } catch ( final LoginException se) {
- // skip this, try next
- }
- if ( parentProvider == null ) {
- parentResolveContext = null;
- path = ResourceUtil.getParent(path);
- }
- } else {
- path = null;
- }
- }
- }
- return parentProvider != null ? new Object[] {parentProvider, parentResolveContext} : null;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ProviderManager.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ProviderManager.java
deleted file mode 100644
index 4dfcda2..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/stateful/ProviderManager.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * 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 SF 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.resourceresolver.impl.providers.stateful;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.resource.runtime.dto.AuthType;
-import org.apache.sling.resourceresolver.impl.ResourceAccessSecurityTracker;
-import org.apache.sling.resourceresolver.impl.helper.AbstractIterator;
-import org.apache.sling.resourceresolver.impl.helper.ResourceResolverControl;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Manages resolve contexts for each resource provider including
- * authentication.
- *
- * This class is not thread safe (same as the resource resolver).
- */
-public class ProviderManager {
-
- private static final Logger logger = LoggerFactory.getLogger(ProviderManager.class);
-
- private final ResourceResolver resolver;
-
- private final Map<ResourceProviderHandler, AuthenticatedResourceProvider> contextMap;
-
- /** Set of authenticated resource providers. */
- private final List<AuthenticatedResourceProvider> authenticated = new ArrayList<AuthenticatedResourceProvider>();
-
- /** Set of modifiable resource providers. */
- private final List<AuthenticatedResourceProvider> modifiable = new ArrayList<AuthenticatedResourceProvider>();
-
- /** Set of refreshable resource providers. */
- private final List<AuthenticatedResourceProvider> refreshable = new ArrayList<AuthenticatedResourceProvider>();
-
- private final ResourceAccessSecurityTracker tracker;
-
- public ProviderManager(@Nonnull final ResourceResolver resolver, @Nonnull final ResourceAccessSecurityTracker tracker) {
- this.contextMap = new IdentityHashMap<ResourceProviderHandler, AuthenticatedResourceProvider>();
- this.resolver = resolver;
- this.tracker = tracker;
- }
-
- /**
- * Get the context
- * @param handler The resource handler
- * @return The resource context or {@code null} if authentication failed previously.
- */
- public @CheckForNull AuthenticatedResourceProvider getOrCreateProvider(@Nonnull final ResourceProviderHandler handler,
- @Nonnull final ResourceResolverControl control)
- throws LoginException {
- AuthenticatedResourceProvider provider = this.contextMap.get(handler);
- if (provider == null) {
- final ResourceProvider<Object> resourceProvider = handler.useResourceProvider();
- if ( resourceProvider != null ) {
- try {
- provider = authenticate(handler, resourceProvider, control);
- this.contextMap.put(handler, provider);
- if ( handler.getInfo().getAuthType() == AuthType.lazy || handler.getInfo().getAuthType() == AuthType.required ) {
- control.registerAuthenticatedProvider(handler, provider.getResolveContext().getProviderState());
- }
- } catch ( final LoginException le) {
- logger.debug("Authentication to resource provider " + resourceProvider + " failed: " + le.getMessage(), le);
- this.contextMap.put(handler, AuthenticatedResourceProvider.UNAUTHENTICATED_PROVIDER);
-
- throw le;
- }
- } else {
- this.contextMap.put(handler, AuthenticatedResourceProvider.UNAUTHENTICATED_PROVIDER);
- }
- }
-
- return provider == AuthenticatedResourceProvider.UNAUTHENTICATED_PROVIDER ? null : provider;
- }
-
- /**
- * Get the context
- * @param handler The resource handler
- * @return The resource context or {@code null}.
- */
- public @CheckForNull ResolveContext<Object> getOrCreateResolveContext(@Nonnull final ResourceProviderHandler handler,
- @Nonnull final ResourceResolverControl control)
- throws LoginException {
- AuthenticatedResourceProvider provider = this.getOrCreateProvider(handler, control);
- return provider == null ? null : provider.getResolveContext();
- }
-
- /**
- * Authenticate all handlers
- * @param handlers List of handlers
- * @param control the resource resolver control
- * @throws LoginException If authentication fails to one provider
- */
- public void authenticateAll(@Nonnull final List<ResourceProviderHandler> handlers,
- @Nonnull final ResourceResolverControl control)
- throws LoginException {
- for (final ResourceProviderHandler h : handlers) {
- try {
- this.getOrCreateProvider(h, control);
- } catch ( final LoginException le ) {
- // authentication failed, logout from all successful handlers
- for(final Map.Entry<ResourceProviderHandler, AuthenticatedResourceProvider> entry : this.contextMap.entrySet()) {
- if ( entry.getValue() != AuthenticatedResourceProvider.UNAUTHENTICATED_PROVIDER ) {
- final ResourceProvider<Object> provider = entry.getKey().getResourceProvider();
- if ( provider != null ) {
- provider.logout(entry.getValue().getResolveContext().getProviderState());
- }
- }
- }
- this.contextMap.clear();
- control.clearAuthenticatedProviders();
- throw le;
- }
- }
- }
-
- /**
- * Authenticate a single resource provider (handler)
- * @param handler The resource provider handler
- * @param control The resource control
- * @return The resolve context
- * @throws LoginException If authentication fails
- */
- private @Nonnull AuthenticatedResourceProvider authenticate(@Nonnull final ResourceProviderHandler handler,
- @Nonnull final ResourceProvider<Object> provider,
- @Nonnull final ResourceResolverControl control) throws LoginException {
- boolean isAuthenticated = false;
- Object contextData = null;
- if ( (handler.getInfo().getAuthType() == AuthType.required || handler.getInfo().getAuthType() == AuthType.lazy) ) {
- try {
- contextData = provider.authenticate(control.getAuthenticationInfo());
- isAuthenticated = true;
- } catch ( final LoginException le ) {
- logger.debug("Unable to login into resource provider " + provider, le);
- throw le;
- }
- }
-
- final ResolveContext<Object> context = new BasicResolveContext<Object>(this.resolver,
- this,
- control,
- contextData,
- ResourceUtil.getParent(handler.getInfo().getPath()));
- final AuthenticatedResourceProvider rp = new AuthenticatedResourceProvider(handler,
- handler.getInfo().getUseResourceAccessSecurity(),
- context,
- this.tracker);
- if ( isAuthenticated ) {
- this.authenticated.add(rp);
- }
- if ( handler.getInfo().isModifiable() ) {
- this.modifiable.add(rp);
- }
- if ( handler.getInfo().isRefreshable() ) {
- this.refreshable.add(rp);
- }
-
- return rp;
- }
-
- public Collection<AuthenticatedResourceProvider> getAllAuthenticated() {
- return new ArrayList<AuthenticatedResourceProvider>(this.authenticated);
- }
-
- public Collection<AuthenticatedResourceProvider> getAllUsedModifiable() {
- return new ArrayList<AuthenticatedResourceProvider>(modifiable);
- }
-
- public Collection<AuthenticatedResourceProvider> getAllUsedRefreshable() {
- return new ArrayList<AuthenticatedResourceProvider>(refreshable);
- }
-
- public Iterable<AuthenticatedResourceProvider> getAllBestEffort(@Nonnull final List<ResourceProviderHandler> handlers,
- @Nonnull final ResourceResolverControl control) {
- final Iterator<ResourceProviderHandler> handlerIter = handlers.iterator();
- return new Iterable<AuthenticatedResourceProvider>() {
-
- @Override
- public Iterator<AuthenticatedResourceProvider> iterator() {
- return new AbstractIterator<AuthenticatedResourceProvider>() {
-
- @Override
- protected AuthenticatedResourceProvider seek() {
- AuthenticatedResourceProvider result = null;
- while ( result == null && handlerIter.hasNext() ) {
- final ResourceProviderHandler h = handlerIter.next();
- try {
- result = getOrCreateProvider(h, control);
- } catch ( final LoginException le) {
- // ignore
- }
- }
- return result;
- }
- };
- }
- };
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/Node.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/Node.java
deleted file mode 100644
index d5a834a..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/Node.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers.tree;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-public class Node<T> {
-
- private T value;
-
- private Map<String, Node<T>> children;
-
- public boolean hasChild(String name) {
- return children != null && children.containsKey(name);
- }
-
- public Node<T> getChild(String name) {
- if (children != null) {
- return children.get(name);
- } else {
- return null;
- }
- }
-
- Node<T> addChild(String name) {
- if (children == null) {
- children = new HashMap<String, Node<T>>();
- }
- Node<T> newNode = new Node<T>();
- children.put(name, newNode);
- return newNode;
- }
-
- void setValue(T value) {
- this.value = value;
- }
-
- public T getValue() {
- return value;
- }
-
- public Map<String, Node<T>> getChildren() {
- if (children == null) {
- return Collections.emptyMap();
- } else {
- return children;
- }
- }
-
- @Override
- public String toString() {
- return "[" + getClass().getSimpleName() + "# value: " + value +" ]";
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/PathSegmentIterator.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/PathSegmentIterator.java
deleted file mode 100644
index bf91dc1..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/PathSegmentIterator.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers.tree;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-public class PathSegmentIterator implements Iterator<String> {
-
- private final String path;
-
- private int index = 0;
-
- public PathSegmentIterator(String path, int index) {
- this.path = path;
- this.index = index;
- }
-
- @Override
- public boolean hasNext() {
- return index < path.length();
- }
-
- @Override
- public String next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- int nextIndex = path.indexOf('/', index);
- if (nextIndex == -1) {
- nextIndex = path.length();
- }
- String result = path.substring(index, nextIndex);
- index = nextIndex + 1;
- return result;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/PathTree.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/PathTree.java
deleted file mode 100644
index 532bf74..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/PathTree.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers.tree;
-
-import static org.apache.commons.lang.StringUtils.split;
-
-import java.util.Iterator;
-import java.util.List;
-
-public class PathTree<T extends Pathable> {
-
- private Node<T> root;
-
- public PathTree(List<T> values) {
- this.root = new Node<T>();
- for (T v : values) {
- addNewValue(v);
- }
- }
-
- private void addNewValue(T value) {
- Node<T> node = root;
- for (String segment : split(value.getPath(), '/')) {
- if (node.hasChild(segment)) {
- node = node.getChild(segment);
- } else {
- node = node.addChild(segment);
- }
- }
- node.setValue(value);
- }
-
- public Node<T> getBestMatchingNode(final String path) {
- if (path == null || path.isEmpty() || path.charAt(0) != '/') {
- return null;
- }
-
- Node<T> result = root.getValue() != null ? root : null;
-
- Node<T> node = root;
- Iterator<String> it = new PathSegmentIterator(path, 1);
- while (it.hasNext()) {
- String segment = it.next();
- node = node.getChild(segment);
- if (node == null) {
- break;
- } else {
- if (node.getValue() != null) {
- result = node;
- }
- }
- }
- return result;
- }
-
- public Node<T> getNode(String path) {
- if (path == null || path.isEmpty() || path.charAt(0) != '/') {
- return null;
- }
- Node<T> node = root;
- Iterator<String> it = new PathSegmentIterator(path, 1);
- while (it.hasNext()) {
- String segment = it.next();
- node = node.getChild(segment);
- if (node == null) {
- return null;
- }
- }
- return node;
- }
-}
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/Pathable.java b/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/Pathable.java
deleted file mode 100644
index 8c7a90d..0000000
--- a/src/main/java/org/apache/sling/resourceresolver/impl/providers/tree/Pathable.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers.tree;
-
-public interface Pathable {
-
- String getPath();
-
-}
diff --git a/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml b/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
new file mode 100644
index 0000000..a99b99f
--- /dev/null
+++ b/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
@@ -0,0 +1,33 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <goals>
+ <goal>validate</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute>
+ <runOnIncremental>true</runOnIncremental>
+ <runOnConfiguration>false</runOnConfiguration>
+ </execute>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+</lifecycleMappingMetadata>
\ No newline at end of file
diff --git a/src/main/resources/res/ui/resourceresolver.css b/src/main/resources/res/ui/resourceresolver.css
deleted file mode 100644
index 789d578..0000000
--- a/src/main/resources/res/ui/resourceresolver.css
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-
-tr.content.duplicate td.content {
- color: grey;
- text-decoration: line-through;
-}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/maven/htl/ProjectStub.java b/src/test/java/org/apache/sling/maven/htl/ProjectStub.java
new file mode 100644
index 0000000..aebef35
--- /dev/null
+++ b/src/test/java/org/apache/sling/maven/htl/ProjectStub.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.maven.htl;
+
+import java.io.File;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
+
+public class ProjectStub extends MavenProjectStub {
+
+ public ProjectStub(File pomFile) {
+ readModel(pomFile);
+ setPomFile(pomFile);
+ Model model = getModel();
+ setGroupId(model.getGroupId());
+ setArtifactId(model.getArtifactId());
+ setVersion(model.getVersion());
+ }
+}
diff --git a/src/test/java/org/apache/sling/maven/htl/ValidateMojoTest.java b/src/test/java/org/apache/sling/maven/htl/ValidateMojoTest.java
new file mode 100644
index 0000000..86d14eb
--- /dev/null
+++ b/src/test/java/org/apache/sling/maven/htl/ValidateMojoTest.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * 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.maven.htl;
+
+import java.io.File;
+import java.util.List;
+
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.testing.MojoRule;
+import org.apache.maven.plugin.testing.SilentLog;
+import org.apache.maven.project.MavenProject;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonatype.plexus.build.incremental.DefaultBuildContext;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class ValidateMojoTest {
+
+ public static final String ERROR_SLY = "src/main/resources/apps/projects/error.sly";
+ public static final String WARNING_SLY = "src/main/resources/apps/projects/warning.sly";
+ public static final String SCRIPT_HTML = "src/main/resources/apps/projects/script.html";
+ public static final String TEST_PROJECT = "test-project";
+ public static final String EXPLICIT_INCLUDES_POM = "explicit-includes.pom.xml";
+ public static final String EXPLICIT_EXCLUDES_POM = "explicit-excludes.pom.xml";
+ public static final String FAIL_ON_WARNINGS_POM = "fail-on-warnings.pom.xml";
+
+ @Rule
+ public MojoRule mojoRule = new MojoRule() {
+ @Override
+ protected void before() throws Throwable {
+ super.before();
+ /**
+ * Make sure the base directory is initialised properly for this test
+ */
+ System.setProperty("basedir", new File("src" + File.separator + "test" + File.separator + "resources" + File
+ .separator + TEST_PROJECT).getAbsolutePath());
+ }
+ };
+
+ @Test
+ public void testExplicitIncludes() throws Exception {
+ File baseDir = new File(System.getProperty("basedir"));
+ ValidateMojo validateMojo = getMojo(baseDir, EXPLICIT_INCLUDES_POM);
+ try {
+ validateMojo.execute();
+ } catch (MojoFailureException e) {
+ List<File> processedFiles = validateMojo.getProcessedFiles();
+ assertEquals("Expected 2 files to process.", 2, processedFiles.size());
+ assertTrue("Expected error.sly to be one of the processed files.", processedFiles.contains(new File(baseDir, ERROR_SLY)));
+ assertTrue("Expected warning.sly to be one of the processed files.", processedFiles.contains(new File(baseDir, WARNING_SLY)));
+ assertEquals("Expected compilation errors.", true, validateMojo.hasErrors());
+ assertEquals("Expected compilation warnings.", true, validateMojo.hasWarnings());
+ }
+ }
+
+ @Test
+ public void testExplicitExcludes() throws Exception {
+ File baseDir = new File(System.getProperty("basedir"));
+ ValidateMojo validateMojo = getMojo(baseDir, EXPLICIT_EXCLUDES_POM);
+ validateMojo.execute();
+ List<File> processedFiles = validateMojo.getProcessedFiles();
+ assertEquals("Expected 1 file to process.", 1, processedFiles.size());
+ assertTrue("Expected script.html to be the only processed file.", processedFiles.contains(new File(baseDir, SCRIPT_HTML)));
+ assertEquals("Did not expect compilation errors.", false, validateMojo.hasErrors());
+ assertEquals("Did not expect compilation warnings.", false, validateMojo.hasWarnings());
+ }
+
+ @Test
+ public void testFailOnWarnings() throws Exception {
+ File baseDir = new File(System.getProperty("basedir"));
+ ValidateMojo validateMojo = getMojo(baseDir, FAIL_ON_WARNINGS_POM);
+ Exception exception = null;
+ try {
+ validateMojo.execute();
+ } catch (MojoFailureException e) {
+ exception = e;
+ }
+ List<File> processedFiles = validateMojo.getProcessedFiles();
+ assertNotNull("Expected a MojoFailureException.", exception);
+ assertEquals("Expected 1 file to process.", 1, processedFiles.size());
+ assertTrue("Expected warning.sly to be one of the processed files.", processedFiles.contains(new File(baseDir, WARNING_SLY)));
+ assertEquals("Expected compilation warnings.", true, validateMojo.hasWarnings());
+ }
+
+ private ValidateMojo getMojo(File baseDir, String pomFile) throws Exception {
+ SilentLog log = new SilentLog();
+ DefaultBuildContext buildContext = new DefaultBuildContext();
+
+ File pom = new File(baseDir, pomFile);
+ ValidateMojo validateMojo = new ValidateMojo();
+ mojoRule.configureMojo(validateMojo, mojoRule.extractPluginConfiguration("htl-maven-plugin", pom));
+ MavenProject mavenProject = new ProjectStub(pom);
+ mojoRule.setVariableValueToObject(validateMojo, "project", mavenProject);
+ validateMojo.setLog(log);
+ buildContext.enableLogging(log);
+ validateMojo.setBuildContext(buildContext);
+ return validateMojo;
+ }
+
+
+}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/FactoryPreconditionsTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/FactoryPreconditionsTest.java
deleted file mode 100644
index 7d0d275..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/FactoryPreconditionsTest.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderInfo;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-public class FactoryPreconditionsTest {
-
- @Test public void testNoRequiredProviders() {
- final ResourceProviderTracker tracker = Mockito.mock(ResourceProviderTracker.class);
- final ResourceProviderStorage storage = Mockito.mock(ResourceProviderStorage.class);
- Mockito.when(tracker.getResourceProviderStorage()).thenReturn(storage);
-
- FactoryPreconditions conditions = new FactoryPreconditions();
- conditions.activate(null, null, null, tracker);
-
- assertTrue(conditions.checkPreconditions(null, null));
-
- conditions = new FactoryPreconditions();
- conditions.activate(null, new String[0], new String[0], tracker);
-
- assertTrue(conditions.checkPreconditions(null, null));
- }
-
- @Test public void testDeactivated() {
- final ResourceProviderTracker tracker = Mockito.mock(ResourceProviderTracker.class);
- final ResourceProviderStorage storage = Mockito.mock(ResourceProviderStorage.class);
- Mockito.when(tracker.getResourceProviderStorage()).thenReturn(storage);
-
- FactoryPreconditions conditions = new FactoryPreconditions();
- conditions.activate(null, null, null, tracker);
-
- assertTrue(conditions.checkPreconditions(null, null));
-
- conditions.deactivate();
-
- assertFalse(conditions.checkPreconditions(null, null));
- }
-
- private List<ResourceProviderHandler> getResourceProviderHandlers(String[] pids) {
- final List<ResourceProviderHandler> result = new ArrayList<ResourceProviderHandler>();
-
- for(final String p : pids) {
- final ResourceProviderHandler handler = Mockito.mock(ResourceProviderHandler.class);
- final ResourceProviderInfo info = Mockito.mock(ResourceProviderInfo.class);
- final ServiceReference ref = Mockito.mock(ServiceReference.class);
-
- Mockito.when(handler.getInfo()).thenReturn(info);
- Mockito.when(info.getServiceReference()).thenReturn(ref);
- Mockito.when(ref.getProperty(Constants.SERVICE_PID)).thenReturn(p);
-
- result.add(handler);
- }
- return result;
- }
-
- private List<ResourceProviderHandler> getResourceProviderHandlersWithNames(String[] names) {
- final List<ResourceProviderHandler> result = new ArrayList<ResourceProviderHandler>();
-
- for(final String n : names) {
- final ResourceProviderHandler handler = Mockito.mock(ResourceProviderHandler.class);
- final ResourceProviderInfo info = Mockito.mock(ResourceProviderInfo.class);
- Mockito.when(info.getName()).thenReturn(n);
- final ServiceReference ref = Mockito.mock(ServiceReference.class);
-
- Mockito.when(handler.getInfo()).thenReturn(info);
- Mockito.when(info.getServiceReference()).thenReturn(ref);
-
- result.add(handler);
- }
- return result;
- }
-
- @Test public void testPIDs() {
- final ResourceProviderTracker tracker = Mockito.mock(ResourceProviderTracker.class);
- final ResourceProviderStorage storage = Mockito.mock(ResourceProviderStorage.class);
- Mockito.when(tracker.getResourceProviderStorage()).thenReturn(storage);
-
- FactoryPreconditions conditions = new FactoryPreconditions();
- conditions.activate(null, new String[] {"pid1", "pid3"}, null, tracker);
-
- final List<ResourceProviderHandler> handlers1 = getResourceProviderHandlers(new String[] {"pid2"});
- Mockito.when(storage.getAllHandlers()).thenReturn(handlers1);
- assertFalse(conditions.checkPreconditions(null, null));
-
- final List<ResourceProviderHandler> handlers2 = getResourceProviderHandlers(new String[] {"pid1", "pid2", "pid3"});
- Mockito.when(storage.getAllHandlers()).thenReturn(handlers2);
- assertTrue(conditions.checkPreconditions(null, null));
-
- final List<ResourceProviderHandler> handlers3 = getResourceProviderHandlers(new String[] {"pid1"});
- Mockito.when(storage.getAllHandlers()).thenReturn(handlers3);
- assertFalse(conditions.checkPreconditions(null, null));
- }
-
- @Test public void testNames() {
- final ResourceProviderTracker tracker = Mockito.mock(ResourceProviderTracker.class);
- final ResourceProviderStorage storage = Mockito.mock(ResourceProviderStorage.class);
- Mockito.when(tracker.getResourceProviderStorage()).thenReturn(storage);
-
- FactoryPreconditions conditions = new FactoryPreconditions();
- conditions.activate(null, null, new String[] {"n1", "n2"}, tracker);
-
- final List<ResourceProviderHandler> handlers1 = getResourceProviderHandlersWithNames(new String[] {"n2"});
- Mockito.when(storage.getAllHandlers()).thenReturn(handlers1);
- assertFalse(conditions.checkPreconditions(null, null));
-
- final List<ResourceProviderHandler> handlers2 = getResourceProviderHandlersWithNames(new String[] {"n1", "n2", "n3"});
- Mockito.when(storage.getAllHandlers()).thenReturn(handlers2);
- assertTrue(conditions.checkPreconditions(null, null));
-
- final List<ResourceProviderHandler> handlers3 = getResourceProviderHandlersWithNames(new String[] {"n1"});
- Mockito.when(storage.getAllHandlers()).thenReturn(handlers3);
- assertFalse(conditions.checkPreconditions(null, null));
- }
-
- @Test public void testUnregisteringService() {
- final ResourceProviderTracker tracker = Mockito.mock(ResourceProviderTracker.class);
- final ResourceProviderStorage storage = Mockito.mock(ResourceProviderStorage.class);
- Mockito.when(tracker.getResourceProviderStorage()).thenReturn(storage);
-
- FactoryPreconditions conditions = new FactoryPreconditions();
- conditions.activate(null, new String[] {"pid1", "pid3"}, null, tracker);
-
- final List<ResourceProviderHandler> handlers2 = getResourceProviderHandlers(new String[] {"pid1", "pid2", "pid3"});
- Mockito.when(storage.getAllHandlers()).thenReturn(handlers2);
- assertTrue(conditions.checkPreconditions(null, null));
-
- assertTrue(conditions.checkPreconditions(null, "pid2"));
-
- assertFalse(conditions.checkPreconditions(null, "pid1"));
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/Fixture.java b/src/test/java/org/apache/sling/resourceresolver/impl/Fixture.java
deleted file mode 100644
index d73563d..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/Fixture.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Map;
-
-import org.apache.sling.api.resource.runtime.dto.AuthType;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderInfo;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-/**
- * The <tt>Fixture</tt> holds reusable, shared, test setup code
- */
-public class Fixture {
-
- private final BundleContext bc;
- private final Map<ResourceProviderInfo, ServiceRegistration> providerRegistrations = new HashMap<ResourceProviderInfo, ServiceRegistration>();
-
- public Fixture(BundleContext bc) {
- this.bc = bc;
- }
-
- public ResourceProviderInfo registerResourceProvider(ResourceProvider<?> rp, String root, AuthType authType) throws InvalidSyntaxException {
-
- Dictionary<String, String> props = new Hashtable<String, String>();
- props.put(ResourceProvider.PROPERTY_ROOT, root);
- props.put(ResourceProvider.PROPERTY_AUTHENTICATE, authType.name());
- props.put(ResourceProvider.PROPERTY_MODIFIABLE, Boolean.TRUE.toString());
-
- ServiceRegistration registration = bc.registerService(ResourceProvider.class.getName(), rp, props);
-
- ServiceReference sr = bc.getServiceReferences(ResourceProvider.class.getName(),
- "(" + ResourceProvider.PROPERTY_ROOT + "=" + root + ")")[0];
-
- ResourceProviderInfo providerInfo = new ResourceProviderInfo(sr);
-
- providerRegistrations.put(providerInfo, registration);
-
- return providerInfo;
- }
-
- public void unregisterResourceProvider(ResourceProviderInfo info) {
-
- ServiceRegistration registration = providerRegistrations.remove(info);
- if ( registration == null ) {
- throw new IllegalArgumentException("No " + ServiceRegistration.class.getSimpleName() + " found for " + info);
- }
-
- registration.unregister();
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/MockedResourceResolverImplTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/MockedResourceResolverImplTest.java
deleted file mode 100644
index bd4ad1a..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/MockedResourceResolverImplTest.java
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * 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 SF 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.resourceresolver.impl;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.sling.api.resource.LoginException;
-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.ResourceResolverFactory;
-import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.api.wrappers.ValueMapDecorator;
-import org.apache.sling.resourceresolver.impl.observation.ResourceChangeListenerWhiteboard;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderInfo;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
-import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.component.ComponentContext;
-
-/**
- * This tests the ResourceResolver using mocks. The Unit test is in addition to
- * ResourceResolverImplTest which covers API conformance more than it covers all
- * code paths.
- */
-// TODO: Configure mapping to react correctly.
-// TODO: test external redirect.
-// TODO: Map to URI
-// TODO: Statresource
-public class MockedResourceResolverImplTest {
-
- private static final List<Resource> EMPTY_RESOURCE_LIST = new ArrayList<Resource>();
- private static final String FAKE_QUERY_LANGUAGE = "fake";
- private static final String PATH = "path";
-
- private ResourceResolverFactoryActivator activator;
-
- private List<ResourceProviderHandler> handlers = new ArrayList<ResourceProviderHandler>();
-
- @Mock
- private ComponentContext componentContext;
-
- @Mock
- private BundleContext bundleContext;
-
- @Mock
- private Bundle usingBundle;
-
- @Mock
- private BundleContext usingBundleContext;
-
- @Mock
- private ResourceProviderTracker resourceProviderTracker;
-
- @Mock
- private ResourceChangeListenerWhiteboard resourceChangeListenerWhiteboard;
-
- @SuppressWarnings("rawtypes")
- @Mock
- private QueryLanguageProvider queryProvider;
-
- private Map<String, Object> services = new HashMap<String, Object>();
-
- private Map<String, Object> serviceProperties = new HashMap<String, Object>();
-
- private ResourceResolverFactoryImpl resourceResolverFactory;
-
- @Mock
- private ResourceProvider<?> resourceProvider;
-
- /**
- * deals with /etc resolution.
- */
- @Mock
- private ResourceProvider<?> mappingResourceProvider;
-
- /**
- * deals with /apps and /libs resolution.
- */
- @Mock
- private ResourceProvider<?> appsResourceProvider;
-
- /**
- * QueriableResourceProviders
- */
- @Mock
- private ResourceProvider<?> queriableResourceProviderA;
-
-
- public MockedResourceResolverImplTest() {
- MockitoAnnotations.initMocks(this);
- }
-
- @SuppressWarnings("unchecked")
- @Before
- public void before() throws LoginException {
- activator = new ResourceResolverFactoryActivator();
-
- Mockito.when(componentContext.getProperties()).thenReturn(buildBundleProperties());
- Mockito.when(componentContext.getBundleContext()).thenReturn(
- bundleContext);
-
- activator.resourceAccessSecurityTracker = new ResourceAccessSecurityTracker();
- activator.resourceProviderTracker = resourceProviderTracker;
- activator.changeListenerWhiteboard = resourceChangeListenerWhiteboard;
-
- handlers.add(createRPHandler(resourceProvider, "org.apache.sling.resourceresolver.impl.DummyTestProvider", 10L, "/single"));
-
- // setup mapping resources at /etc/map to exercise vanity etc.
- // hmm, can't provide the resolver since its not up and ready.
- // mapping almost certainly work properly until this can be setup correctly.
- buildMappingResource("/etc/map", mappingResourceProvider, null);
-
- handlers.add(createRPHandler(mappingResourceProvider, "org.apache.sling.resourceresolver.impl.MapProvider", 11L, "/etc"));
- handlers.add(createRPHandler(appsResourceProvider, "org.apache.sling.resourceresolver.impl.AppsProvider", 12L, "/libs"));
- handlers.add(createRPHandler(appsResourceProvider, "org.apache.sling.resourceresolver.impl.AppsProvider", 13L, "/apps"));
- handlers.add(createRPHandler(queriableResourceProviderA, "org.apache.sling.resourceresolver.impl.QueriableResourceProviderA", 14L, "/searchA"));
- Mockito.when(queriableResourceProviderA.getQueryLanguageProvider()).thenReturn(queryProvider);
-
- ResourceProviderStorage storage = new ResourceProviderStorage(handlers);
-
- Mockito.when(resourceProviderTracker.getResourceProviderStorage()).thenReturn(storage);
-
- // activate the components.
- activator.activate(componentContext);
-
- // configure using Bundle
- Mockito.when(usingBundle.getBundleContext()).thenReturn(usingBundleContext);
- Mockito.when(usingBundleContext.getBundle()).thenReturn(usingBundle);
-
- // extract any services that were registered into a map.
- ArgumentCaptor<String> classesCaptor = ArgumentCaptor.forClass(String.class);
- ArgumentCaptor<Object> serviceCaptor = ArgumentCaptor.forClass(Object.class);
- @SuppressWarnings("rawtypes")
- ArgumentCaptor<Dictionary> propertiesCaptor = ArgumentCaptor.forClass(Dictionary.class);
- Mockito.verify(bundleContext, Mockito.atLeastOnce()).registerService(
- classesCaptor.capture(), serviceCaptor.capture(),
- propertiesCaptor.capture());
-
- int si = 0;
- List<Object> serviceList = serviceCaptor.getAllValues();
- @SuppressWarnings({ "unused", "rawtypes" })
- List<Dictionary> servicePropertiesList = propertiesCaptor.getAllValues();
- for (String serviceName : classesCaptor.getAllValues()) {
- services.put(serviceName, serviceList.get(si));
- serviceProperties.put(serviceName, serviceProperties.get(si));
- si++;
- }
- // verify that a ResourceResolverFactoryImpl was created and registered.
- Assert.assertNotNull(services.get(ResourceResolverFactory.class.getName()));
- Object rrf = services.get(ResourceResolverFactory.class.getName());
- if (rrf instanceof ServiceFactory) {
- rrf = ((ServiceFactory) rrf).getService(usingBundle, null);
- }
- Assert.assertTrue(rrf instanceof ResourceResolverFactoryImpl);
- resourceResolverFactory = (ResourceResolverFactoryImpl) rrf;
- }
-
- public static ResourceProviderHandler createRPHandler(ResourceProvider<?> rp, String pid, long ranking,
- String path) {
- ServiceReference ref = Mockito.mock(ServiceReference.class);
- BundleContext bc = Mockito.mock(BundleContext.class);
- Mockito.when(bc.getService(Mockito.eq(ref))).thenReturn(rp);
- Mockito.when(ref.getProperty(Mockito.eq(Constants.SERVICE_ID))).thenReturn(new Random().nextLong());
- Mockito.when(ref.getProperty(Mockito.eq(Constants.SERVICE_PID))).thenReturn(pid);
- Mockito.when(ref.getProperty(Mockito.eq(Constants.SERVICE_RANKING))).thenReturn(ranking);
- Mockito.when(ref.getProperty(Mockito.eq(ResourceProvider.PROPERTY_ROOT))).thenReturn(path);
- Mockito.when(ref.getProperty(Mockito.eq(ResourceProvider.PROPERTY_MODIFIABLE))).thenReturn(true);
- Mockito.when(ref.getProperty(Mockito.eq(ResourceProvider.PROPERTY_ATTRIBUTABLE))).thenReturn(true);
- Mockito.when(ref.getProperty(Mockito.eq(ResourceProvider.PROPERTY_ADAPTABLE))).thenReturn(true);
-
- ResourceProviderInfo info = new ResourceProviderInfo(ref);
- final ResourceProviderHandler handler = new ResourceProviderHandler(bc, info);
- handler.activate();
- return handler;
- }
-
- @SuppressWarnings("unchecked")
- private Resource buildMappingResource(String path,
- ResourceProvider<?> provider, ResourceResolver resourceResolver) {
- List<Resource> localHostAnyList = new ArrayList<Resource>();
- localHostAnyList.add(buildResource(path+"/http/example.com.80/cgi-bin", EMPTY_RESOURCE_LIST, resourceResolver, provider, "sling:internalRedirect", "/scripts" ));
- localHostAnyList.add(buildResource(path+"/http/example.com.80/gateway", EMPTY_RESOURCE_LIST, resourceResolver, provider,"sling:internalRedirect", "http://gbiv.com"));
- localHostAnyList.add(buildResource(path+"/http/example.com.80/stories", EMPTY_RESOURCE_LIST, resourceResolver, provider,"sling:internalRedirect", "/anecdotes/$1"));
-
- List<Resource> mappingChildren = new ArrayList<Resource>();
- mappingChildren.add(buildResource(path+"/http/example.com.80", EMPTY_RESOURCE_LIST, resourceResolver, provider,"sling:redirect", "http://www.example.com/"));
- mappingChildren.add(buildResource(path+"/http/www.example.com.80", EMPTY_RESOURCE_LIST, resourceResolver, provider,"sling:internalRedirect", "/example"));
- mappingChildren.add(buildResource(path+"/http/any_example.com.80", EMPTY_RESOURCE_LIST, resourceResolver, provider,"sling:match", ".+\\.example\\.com\\.80", "sling:redirect", "http://www.example.com/"));
- mappingChildren.add(buildResource(path+"/http/localhost_any", localHostAnyList, resourceResolver, provider,"sling:match", "localhost\\.\\d*", "sling:internalRedirect", "/content"));
-
- Resource etcMapResource = buildResource(path+"/http", mappingChildren);
- Mockito.when(provider.getResource(Mockito.any(ResolveContext.class), Mockito.eq(path), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(etcMapResource);
- return etcMapResource;
- }
-
- @After
- public void after() {
- handlers.clear();
- }
-
- /**
- * build child resources as an iterable of resources.
- * @param parent
- * @return
- */
- private Iterable<Resource> buildChildResources(String parent) {
- List<Resource> mappingResources = new ArrayList<Resource>();
- for ( int i = 0; i < 5; i++ ) {
- mappingResources.add(buildResource(parent+"/m"+i, EMPTY_RESOURCE_LIST));
- }
- return mappingResources;
- }
- /**
- * Build a resource based on path and children.
- * @param fullpath
- * @param children
- * @return
- */
- private Resource buildResource(String fullpath, Iterable<Resource> children) {
- return buildResource(fullpath, children, null, null, new String[0]);
- }
-
- /** Build a List of ValueMap */
- private List<ValueMap> buildValueMapCollection(int howMany, String pathPrefix) {
- final List<ValueMap> result = new ArrayList<ValueMap>();
- for(int i=0; i < howMany; i++) {
- final Map<String, Object> m = new HashMap<String, Object>();
- m.put(PATH, pathPrefix + i);
- result.add(new ValueMapDecorator(m));
- }
- return result;
- }
-
- /**
- * Build a resource with path, children and resource resolver.
- * @param fullpath
- * @param children
- * @param resourceResolver
- * @return
- */
- @SuppressWarnings("unchecked")
- private Resource buildResource(String fullpath, Iterable<Resource> children, ResourceResolver resourceResolver, ResourceProvider<?> provider, String ... properties) {
- Resource resource = Mockito.mock(Resource.class);
- Mockito.when(resource.getName()).thenReturn(getName(fullpath));
- Mockito.when(resource.getPath()).thenReturn(fullpath);
- ResourceMetadata resourceMetadata = new ResourceMetadata();
- Mockito.when(resource.getResourceMetadata()).thenReturn(resourceMetadata);
- Mockito.when(resource.listChildren()).thenReturn(children.iterator());
- Mockito.when(resource.getResourceResolver()).thenReturn(resourceResolver);
-
- // register the resource with the provider
- if ( provider != null ) {
- Mockito.when(provider.listChildren(Mockito.any(ResolveContext.class), Mockito.eq(resource))).thenReturn(children.iterator());
- Mockito.when(provider.getResource(Mockito.any(ResolveContext.class), Mockito.eq(fullpath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(resource);
- }
- if ( properties != null ) {
- ValueMap vm = new SimpleValueMapImpl();
- for ( int i=0; i < properties.length; i+=2) {
- resourceMetadata.put(properties[i], properties[i+1]);
- vm.put(properties[i], properties[i+1]);
- }
- Mockito.when(resource.getValueMap()).thenReturn(vm);
- Mockito.when(resource.adaptTo(Mockito.eq(ValueMap.class))).thenReturn(vm);
- } else {
- Mockito.when(resource.getValueMap()).thenReturn(ValueMapDecorator.EMPTY);
- Mockito.when(resource.adaptTo(Mockito.eq(ValueMap.class))).thenReturn(ValueMapDecorator.EMPTY);
- }
-
- return resource;
- }
-
-
- /**
- * extract the name from a path.
- * @param fullpath
- * @return
- */
- private String getName(String fullpath) {
- int n = fullpath.lastIndexOf("/");
- return fullpath.substring(n+1);
- }
-
- /**
- * build a properties for a resource resolver bundle.
- * @return
- */
- private Dictionary<String, Object> buildBundleProperties() {
- Dictionary<String, Object> properties = new Hashtable<String, Object>();
- properties.put("resource.resolver.virtual", new String[] { "/:/" });
- properties.put("resource.resolver.mapping", new String[] { "/:/",
- "/content/:/", "/system/docroot/:/", "/content.html-/$" });
- properties.put("resource.resolver.allowDirect", true);
- properties.put("resource.resolver.searchpath", new String[] { "/apps",
- "/libs" });
- properties.put("resource.resolver.manglenamespaces", true);
- properties.put("resource.resolver.map.location", "/etc/map");
- properties.put("resource.resolver.default.vanity.redirect.status", 302);
- properties.put(
- "resource.resolver.required.providers",
- new String[] { "org.apache.sling.resourceresolver.impl.DummyTestProvider" });
- properties.put(Constants.SERVICE_VENDOR, "Apache");
- properties.put(Constants.SERVICE_DESCRIPTION, "Testing");
- return properties;
- }
-
- /**
- * Test getting a resolver.
- * @throws LoginException
- */
- @Test
- public void testGetResolver() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getResourceResolver(null);
- Assert.assertNotNull(resourceResolver);
- Map<String, Object> authenticationInfo = new HashMap<String, Object>();
- resourceResolver = resourceResolverFactory.getAdministrativeResourceResolver(authenticationInfo);
- Assert.assertNotNull(resourceResolver);
- }
-
- /**
- * Misceleneous coverage.
- * @throws LoginException
- */
- @Test
- public void testResolverMisc() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getResourceResolver(null);
- try {
- resourceResolver.getAttribute(null);
- Assert.fail("Should have thrown a NPE");
- } catch ( NullPointerException e) {
- // this is expected.
- }
- Assert.assertArrayEquals(new String[]{"/apps/","/libs/"}, resourceResolver.getSearchPath());
- }
-
- /**
- * Test various administrative resource resolvers.
- * @throws LoginException
- */
- @Test
- public void testGetAuthenticatedResolve() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getAdministrativeResourceResolver(null);
- Assert.assertNotNull(resourceResolver);
- Map<String, Object> authenticationInfo = new HashMap<String, Object>();
-
- resourceResolver = resourceResolverFactory.getAdministrativeResourceResolver(authenticationInfo);
- Assert.assertNotNull(resourceResolver);
- }
-
- /**
- * Test getResource for a resource provided by a resource provider.
- * @throws LoginException
- */
- @Test
- public void testGetResource() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getResourceResolver(null);
- Assert.assertNotNull(resourceResolver);
- Resource singleResource = buildResource("/single/test", EMPTY_RESOURCE_LIST, resourceResolver, resourceProvider);
- Resource resource = resourceResolver.getResource("/single/test");
- Assert.assertEquals(singleResource, resource);
- }
-
- /**
- * Test getResource where path contains intermediate . verifying fix for SLING-864
- * @throws LoginException
- */
- @Test
- public void testGetResourceSLING864() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getResourceResolver(null);
- Assert.assertNotNull(resourceResolver);
- Resource singleResource = buildResource("/single/test.with/extra.dots/inthepath", EMPTY_RESOURCE_LIST,resourceResolver, resourceProvider);
- Resource resource = resourceResolver.getResource("/single/test.with/extra.dots/inthepath");
- Assert.assertEquals(singleResource, resource);
- }
-
-
- /**
- * Test search paths
- * @throws LoginException
- */
- @Test
- public void testRelativeResource() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getResourceResolver(null);
- Assert.assertNotNull(resourceResolver);
- Resource appResource = buildResource("/apps/store/inventory", EMPTY_RESOURCE_LIST, resourceResolver, appsResourceProvider);
- Resource libResource = buildResource("/libs/store/catalog", EMPTY_RESOURCE_LIST, resourceResolver, appsResourceProvider);
- Resource testResource = resourceResolver.getResource("store/inventory");
- Assert.assertEquals(appResource, testResource);
- testResource = resourceResolver.getResource("store/catalog");
- Assert.assertEquals(libResource, testResource);
- }
-
- /**
- * Basic test of mapping functionality, at the moment needs more
- * configuration in the virtual /etc/map.
- *
- * @throws LoginException
- */
- @Test
- public void testMapping() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getResourceResolver(null);
- buildResource("/single/test", EMPTY_RESOURCE_LIST, resourceResolver, resourceProvider);
- HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
- Mockito.when(request.getScheme()).thenReturn("http");
- Mockito.when(request.getServerPort()).thenReturn(80);
- Mockito.when(request.getServerName()).thenReturn("localhost");
- String path = resourceResolver.map(request,"/single/test?q=123123");
- Assert.assertEquals("/single/test?q=123123", path);
- path = resourceResolver.map(request,"/single/test");
- Assert.assertEquals("/single/test", path);
-
- // test path mapping without a request.
- path = resourceResolver.map("/single/test");
- Assert.assertEquals("/single/test", path);
-
- buildResource("/content", EMPTY_RESOURCE_LIST, resourceResolver, resourceProvider);
- path = resourceResolver.map("/content.html");
- Assert.assertEquals("/content.html", path);
-
- }
-
-
- /**
- * Tests list children via the resource (NB, this doesn't really test the
- * resource resolver at all, but validates this unit test.)
- *
- * @throws LoginException
- */
- @Test
- public void testListChildren() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getResourceResolver(null);
- buildResource("/single/test/withchildren", buildChildResources("/single/test/withchildren"), resourceResolver, resourceProvider );
-
-
- Resource resource = resourceResolver.getResource("/single/test/withchildren");
- Assert.assertNotNull(resource);
-
- // test via the resource list children itself, this really just tests this test case.
- Iterator<Resource> resourceIterator = resource.listChildren();
- Assert.assertNotNull(resourceResolver);
- int i = 0;
- while(resourceIterator.hasNext()) {
- Assert.assertEquals("m"+i, resourceIterator.next().getName());
- i++;
- }
- Assert.assertEquals(5, i);
- }
-
- /**
- * Test listing children via the resource resolver listChildren call.
- * @throws LoginException
- */
- @Test
- public void testResourceResolverListChildren() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getResourceResolver(null);
- buildResource("/single/test/withchildren", buildChildResources("/single/test/withchildren"), resourceResolver, resourceProvider);
-
-
- Resource resource = resourceResolver.getResource("/single/test/withchildren");
- Assert.assertNotNull(resource);
-
- // test via the resource list children itself, this really just tests this test case.
- Iterator<Resource> resourceIterator = resourceResolver.listChildren(resource);
- Assert.assertNotNull(resourceResolver);
- int i = 0;
- while(resourceIterator.hasNext()) {
- Assert.assertEquals("m"+i, resourceIterator.next().getName());
- i++;
- }
- Assert.assertEquals(5,i);
- }
-
- /**
- * Tests listing children via the resource resolver getChildren call.
- * @throws LoginException
- */
- @Test
- public void testResourceResolverGetChildren() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getResourceResolver(null);
- buildResource("/single/test/withchildren", buildChildResources("/single/test/withchildren"), resourceResolver, resourceProvider);
-
-
- Resource resource = resourceResolver.getResource("/single/test/withchildren");
- Assert.assertNotNull(resource);
-
- // test via the resource list children itself, this really just tests this test case.
- Iterable<Resource> resourceIterator = resourceResolver.getChildren(resource);
- Assert.assertNotNull(resourceResolver);
- int i = 0;
- for(Resource r : resourceIterator) {
- Assert.assertEquals("m"+i, r.getName());
- i++;
- }
- Assert.assertEquals(5,i);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void testQueryResources() throws LoginException {
- final int n = 3;
- String[] languages = new String[] {FAKE_QUERY_LANGUAGE};
- Mockito.when(queryProvider.getSupportedLanguages(Mockito.any(ResolveContext.class))).thenReturn(languages);
- Mockito.when(queryProvider.queryResources(Mockito.any(ResolveContext.class), Mockito.any(String.class), Mockito.any(String.class)))
- .thenReturn(buildValueMapCollection(n, "A_").iterator());
-
- final ResourceResolver rr = resourceResolverFactory.getResourceResolver(null);
- buildResource("/search/test/withchildren", buildChildResources("/search/test/withchildren"), rr, resourceProvider);
- final Iterator<Map<String, Object>> it = rr.queryResources("/search", FAKE_QUERY_LANGUAGE);
- final Set<String> toFind = new HashSet<String>();
- for(int i=0; i < n; i++) {
- toFind.add("A_" + i);
- }
-
- assertTrue("Expecting non-empty result (" + n + ")", it.hasNext());
- while(it.hasNext()) {
- final Map<String, Object> m = it.next();
- toFind.remove(m.get(PATH));
- }
- assertTrue("Expecting no leftovers (" + n + ") in" + toFind, toFind.isEmpty());
- }
-
- @Test public void test_versions() throws LoginException {
- ResourceResolver resourceResolver = resourceResolverFactory.getResourceResolver(null);
-
- Resource resource = resourceResolver.resolve("/content/test.html;v=1.0");
- Map<String, String> parameters = resource.getResourceMetadata().getParameterMap();
- assertEquals("/content/test.html", resource.getPath());
- assertEquals("test.html", resource.getName());
- assertEquals(Collections.singletonMap("v", "1.0"), parameters);
-
- resource = resourceResolver.resolve("/content/test;v='1.0'.html");
- parameters = resource.getResourceMetadata().getParameterMap();
- assertEquals("/content/test.html", resource.getPath());
- assertEquals("test.html", resource.getName());
- assertEquals(Collections.singletonMap("v", "1.0"), parameters);
-
- buildResource("/single/test/withchildren", buildChildResources("/single/test/withchildren"), resourceResolver, resourceProvider);
- resource = resourceResolver.getResource("/single/test/withchildren;v='1.0'");
- assertNotNull(resource);
- assertEquals("/single/test/withchildren", resource.getPath());
- assertEquals("withchildren", resource.getName());
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/ProviderHandlerTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/ProviderHandlerTest.java
deleted file mode 100644
index d9592c4..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/ProviderHandlerTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import static org.apache.sling.resourceresolver.impl.MockedResourceResolverImplTest.createRPHandler;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.NonExistingResource;
-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.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-public class ProviderHandlerTest {
-
- @SuppressWarnings("unchecked")
- @Test public void testServletRegistrationAndSyntheticResources() throws LoginException {
- final String servletpath = "/libs/a/b/GET.servlet";
- final Resource servletResource = Mockito.mock(Resource.class);
- Mockito.when(servletResource.getResourceMetadata()).then(new Answer<ResourceMetadata>() {
- @Override
- public ResourceMetadata answer(InvocationOnMock invocation) throws Throwable {
- return new ResourceMetadata();
- }
- });
-
- final ResourceProvider<?> leaveProvider = Mockito.mock(ResourceProvider.class);
- Mockito.when(leaveProvider.getResource(Mockito.any(ResolveContext.class), Mockito.eq(servletpath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(servletResource);
- final ResourceProviderHandler h = createRPHandler(leaveProvider, "my-pid", 0, servletpath);
- ResourceResolverFactoryActivator activator = new ResourceResolverFactoryActivator();
- activator.resourceAccessSecurityTracker = new ResourceAccessSecurityTracker();
- ResourceResolver resolver = new ResourceResolverImpl(new CommonResourceResolverFactoryImpl(activator), false, null, new ResourceProviderStorageProvider() {
-
- @Override
- public ResourceProviderStorage getResourceProviderStorage() {
- return new ResourceProviderStorage(Arrays.asList(h));
- }
- });
-
- final Resource parent = resolver.getResource(ResourceUtil.getParent(servletpath));
- assertNotNull("Parent must be available", parent);
- assertTrue("Resource should be synthetic", ResourceUtil.isSyntheticResource(parent));
-
- final Resource servlet = resolver.getResource(servletpath);
- assertNotNull("Servlet resource must not be null", servlet);
- assertEquals(servletResource, servlet);
-
- assertNotNull(resolver.getResource("/libs"));
-
- // now check when doing a resolve()
- assertTrue(resolver.resolve("/libs") instanceof NonExistingResource);
- assertTrue(resolver.resolve(ResourceUtil.getParent(servletpath)) instanceof NonExistingResource);
- assertNotNull(resolver.resolve(servletpath));
- resolver.close();
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecorationTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecorationTest.java
deleted file mode 100644
index 7d45741..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecorationTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Iterator;
-
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceWrapper;
-import org.junit.Test;
-
-/** Test ResourceDecorator handling in ResourceResolverImpl */
-public class ResourceDecorationTest extends ResourceDecoratorTestBase {
-
- private static final String DECORATED_NAME = "decorated";
-
- /** Wrap any resource so that its name is DECORATED_NAME */
- protected Resource wrapResourceForTest(Resource resource) {
- return new ResourceWrapper(resource) {
- @Override
- public String getName() {
- return DECORATED_NAME;
- }
- };
- }
-
- private void assertDecorated(Resource r) {
- assertEquals("Expecting " + r + " to be decorated", DECORATED_NAME, r.getName());
- }
-
- private void assertDecorated(Iterator<Resource> it, int expectedCount) {
- assertNotNull(it);
- assertTrue("Expecting non-empty Iterator", it.hasNext());
- int count = 0;
- while(it.hasNext()) {
- count++;
- assertDecorated(it.next());
- }
- assertEquals("Expecting " + expectedCount + " items in Iterator", expectedCount, count);
- }
-
- @Test
- public void resolveRootIsDecorated() {
- final Resource r = resolver.resolve((String)null);
- assertDecorated(r);
- assertExistent(r, true);
- }
-
- @Test
- public void getRootIsDecorated() {
- final Resource r = resolver.getResource("/");
- assertDecorated(r);
- assertExistent(r, true);
- }
-
- @Test
- public void getNonExistingIsNull() {
- assertNull(resolver.getResource("/non-existing/something"));
- }
-
- @Test
- public void existentIsDecorated() {
- final Resource r = resolver.resolve("/tmp/C");
- assertDecorated(r);
- assertExistent(r, true);
- }
-
- @Test
- public void NonExistentIsDecorated() {
- final Resource r = resolver.resolve("/foo");
- assertDecorated(r);
- assertExistent(r, false);
- }
-
- @Test
- public void childrenAreDecorated() {
- final Resource root = resolver.resolve((String)null);
- final Iterator<Resource> it = resolver.listChildren(root);
- assertTrue("Expecting root to have children", it.hasNext());
- assertDecorated(it, 2);
- }
-
- @Test
- public void listChildrenDecorates() {
- final Resource testVar = resolver.resolve("/var");
- assertDecorated(resolver.listChildren(testVar), 3);
- }
-
- @Test
- public void findDecorates() {
- assertDecorated(resolver.findResources("foo", QUERY_LANGUAGE), 4);
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecoratorReturnsNullTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecoratorReturnsNullTest.java
deleted file mode 100644
index dadd520..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecoratorReturnsNullTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.Resource;
-import org.junit.Before;
-import org.junit.Test;
-
-/** Verify what happens when ResourceDecorator returns null */
-public class ResourceDecoratorReturnsNullTest extends ResourceDecoratorTestBase {
-
- private Set<String> pathsThatReturnNull = new HashSet<String>();
-
- /** Return null for resources that have a path in pathsThatReturnNull.
- * Will cause our test ResourceDecorator to return null for these resources
- */
- protected Resource wrapResourceForTest(Resource r) {
- return isReturnNull(r) ? null : r;
- }
-
- private boolean isReturnNull(Resource r) {
- return pathsThatReturnNull.contains(r.getPath());
- }
-
- private void assertResources(Iterator<Resource> it, String ...paths) {
- assertNotNull("Expecting non-null Iterator", it);
- final List<String> actual = new ArrayList<String>();
- while(it.hasNext()) {
- final Resource r = it.next();
- assertNotNull("Expecting no null Resources in iterator", r);
- actual.add(r.getPath());
- }
- for(String path : paths) {
- assertTrue("Expecting path " + path + " in " + actual, actual.contains(path));
- }
- if(actual.size() != paths.length) {
- fail("Expecting the same number of items in " + Arrays.asList(paths) + " and " + actual);
- }
- }
-
- @Before
- public void setup() throws LoginException {
- super.setup();
- pathsThatReturnNull.add("/tmp/D");
- pathsThatReturnNull.add("/var/two");
- }
-
- @Test
- public void testResolveNotNull() {
- assertExistent(resolver.resolve("/tmp/A"), true);
- }
-
- public void testGetNotNull() {
- assertExistent(resolver.getResource("/tmp/A"), true);
- }
-
- @Test
- public void testGetNull() {
- assertExistent(resolver.getResource("/tmp/D"), true);
- }
-
- @Test
- public void testResolveNull() {
- assertExistent(resolver.resolve("/tmp/D"), true);
- }
-
- @Test
- public void testRootChildren() {
- final Resource root = resolver.resolve("/");
- assertNotNull(root);
- assertResources(resolver.listChildren(root), "/tmp", "/var");
- }
-
- @Test
- public void testVarChildren() {
- final Resource var = resolver.resolve("/var");
- assertNotNull(var);
- assertResources(resolver.listChildren(var), "/var/one", "/var/two", "/var/three");
- }
-
- @Test
- public void testFind() {
- assertResources(resolver.findResources("foo", QUERY_LANGUAGE), "/tmp/C", "/tmp/D", "/var/one", "/var/two");
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecoratorTestBase.java b/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecoratorTestBase.java
deleted file mode 100644
index e2b1d80..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceDecoratorTestBase.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.NonExistingResource;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceDecorator;
-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.ValueMap;
-import org.apache.sling.resourceresolver.impl.helper.ResourceDecoratorTracker;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorageProvider;
-import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.junit.Before;
-import org.mockito.Mockito;
-
-/** Base class for tests that involve ResourceDecorators */
-public abstract class ResourceDecoratorTestBase {
-
- protected ResourceResolver resolver;
- protected static final String QUERY_LANGUAGE = "some.funnny.language";
-
- protected abstract Resource wrapResourceForTest(Resource resource);
-
- @Before
- public void setup() throws LoginException {
- final ResourceDecorator d = new ResourceDecorator() {
- @Override
- public Resource decorate(Resource resource) {
- return ResourceDecoratorTestBase.this.wrapResourceForTest(resource);
- }
-
- @Override
- public Resource decorate(Resource resource, HttpServletRequest request) {
- throw new UnsupportedOperationException("Not supposed to be used in these tests");
- }
-
- };
-
- final ResourceDecoratorTracker t = new ResourceDecoratorTracker();
- t.bindResourceDecorator(d, null);
-
- final ResourceProvider<?> provider = new ResourceProvider<Object>() {
-
- @Override
- public QueryLanguageProvider<Object> getQueryLanguageProvider() {
- return new QueryLanguageProvider<Object>() {
-
- @Override
- public String[] getSupportedLanguages(ResolveContext<Object> ctx) {
- return new String[] { QUERY_LANGUAGE };
- }
-
- @Override
- public Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language) {
- final List<Resource> found = new ArrayList<Resource>();
- found.add(mockResource("/tmp/C"));
- found.add(mockResource("/tmp/D"));
- found.add(mockResource("/var/one"));
- found.add(mockResource("/var/two"));
- return found.iterator();
- }
-
- @Override
- public Iterator<ValueMap> queryResources(ResolveContext<Object> ctx, String query, String language) {
- return null;
- }
- };
- }
-
- @Override
- public Resource getResource(ResolveContext<Object> ctx, String path, final ResourceContext rCtx, Resource parent) {
- if(path.equals("/") || path.startsWith("/tmp") || path.startsWith("/var")) {
- return mockResource(path);
- }
- return null;
- }
-
- @Override
- public Iterator<Resource> listChildren(ResolveContext<Object> ctx, Resource parent) {
- final List<Resource> children = new ArrayList<Resource>();
- if("/".equals(parent.getPath())) {
- children.add(mockResource("/tmp"));
- children.add(mockResource("/var"));
- } else if("/var".equals(parent.getPath())) {
- children.add(mockResource("/var/one"));
- children.add(mockResource("/var/two"));
- children.add(mockResource("/var/three"));
- } else if("/tmp".equals(parent.getPath())) {
- children.add(mockResource("/tmp/A"));
- children.add(mockResource("/tmp/B"));
- children.add(mockResource("/tmp/C"));
- children.add(mockResource("/tmp/D"));
- }
- return children.iterator();
- }
-
- };
-
- ResourceResolverFactoryActivator activator = new ResourceResolverFactoryActivator();
- final CommonResourceResolverFactoryImpl crf = new CommonResourceResolverFactoryImpl(activator) {
- @Override
- public ResourceDecoratorTracker getResourceDecoratorTracker() {
- return t;
- }
-
- @Override
- public ResourceAccessSecurityTracker getResourceAccessSecurityTracker() {
- return new ResourceAccessSecurityTracker();
- }
- };
-
- final List<ResourceProviderHandler> list = Arrays.asList(MockedResourceResolverImplTest.createRPHandler(provider, "A-provider", 0L, "/"));
- resolver = new ResourceResolverImpl(crf, false, null, new ResourceProviderStorageProvider() {
-
- @Override
- public ResourceProviderStorage getResourceProviderStorage() {
- return new ResourceProviderStorage(list);
- }
- });
- }
-
- protected void assertExistent(Resource r, boolean existent) {
- assertNotNull("Expecting non-null Resource", r);
- assertEquals("Expecting " + (existent ? "existent" : "non-existent") + " resource",
- existent,
- !NonExistingResource.RESOURCE_TYPE_NON_EXISTING.equals(r.getResourceType()));
- }
-
- protected Resource mockResource(String path) {
- final Resource result = Mockito.mock(Resource.class);
- Mockito.when(result.getPath()).thenReturn(path);
- Mockito.when(result.getName()).thenReturn(ResourceUtil.getName(path));
- final ResourceMetadata m = new ResourceMetadata();
- Mockito.when(result.getResourceMetadata()).thenReturn(m);
- return result;
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceProviderEntryTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/ResourceProviderEntryTest.java
deleted file mode 100644
index 3e74a62..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceProviderEntryTest.java
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import static org.apache.sling.resourceresolver.impl.MockedResourceResolverImplTest.createRPHandler;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.sling.api.resource.AbstractResource;
-import org.apache.sling.api.resource.LoginException;
-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.SyntheticResource;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.osgi.framework.Constants;
-
-@SuppressWarnings("unchecked")
-public class ResourceProviderEntryTest {
-
- private List<ResourceProviderHandler> providers = new ArrayList<ResourceProviderHandler>();
-
- private ResourceResolver providersBasedResolver;
-
- private ResourceResolver mockedRootResolver;
-
- @Before public void setUp() throws Exception {
- this.mockedRootResolver = Mockito.mock(ResourceResolver.class);
- this.providersBasedResolver = null;
- this.providers.clear();
- final ResourceProvider<?> rootProvider = Mockito.mock(ResourceProvider.class);
- Mockito.when(rootProvider.getResource(Mockito.any(ResolveContext.class), Mockito.anyString(), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(this.mockedRootResolver));
- providers.add(createRPHandler(rootProvider, "rp0", 0, "/"));
- }
-
- @Test public void testRootProvider() throws LoginException {
- assertNull(getResource("relpath"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/rootel"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/rootel/child"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/apps/sling/sample/html.js"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/apps/sling/microsling/html.js"));
- }
-
- @Test public void testAdd1Provider() throws LoginException {
- String firstPath = "/rootel";
- final ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> first = Mockito.mock(ResourceProvider.class);
- Mockito.when(first.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(firstPath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(resolver));
-
- providers.add(createRPHandler(first, "rp1", 1, "/rootel"));
- this.providersBasedResolver = null;
-
- assertEqualsResolver(this.mockedRootResolver, getResource("/"));
- assertEqualsResolver(resolver, getResource("/rootel"));
- assertEqualsResolver(resolver, getResource("/rootel/html.js"));
- assertEqualsResolver(resolver, getResource("/rootel/child"));
- assertEqualsResolver(resolver, getResource("/rootel/child/html.js"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/apps/sling/sample/html.js"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/apps/sling/microsling/html.js"));
- }
-
- @Test public void testAdd3Providers() throws LoginException {
- String firstPath = "/rootel";
- String secondPath = firstPath + "/child";
- String thirdPath = "/apps/sling/sample";
-
- final ResourceResolver firstResolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> first = Mockito.mock(ResourceProvider.class);
- Mockito.when(first.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(firstPath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(firstResolver));
- final ResourceResolver secondResolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> second = Mockito.mock(ResourceProvider.class);
- Mockito.when(second.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(secondPath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(secondResolver));
- final ResourceResolver thirdResolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> third = Mockito.mock(ResourceProvider.class);
- Mockito.when(third.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(thirdPath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(thirdResolver));
-
- providers.add(createRPHandler(first, "rp1", 1, firstPath));
- providers.add(createRPHandler(second, "rp2", 2, secondPath));
- providers.add(createRPHandler(third, "rp3", 3, thirdPath));
- this.providersBasedResolver = null;
-
- assertEqualsResolver(this.mockedRootResolver, getResource("/"));
- assertEqualsResolver(firstResolver, getResource("/rootel"));
- assertEqualsResolver(firstResolver, getResource("/rootel/html.js"));
- assertEqualsResolver(secondResolver, getResource("/rootel/child"));
- assertEqualsResolver(secondResolver, getResource("/rootel/child/html.js"));
- assertEqualsResolver(thirdResolver, getResource("/apps/sling/sample/html.js"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/apps/sling/microsling/html.js"));
- }
-
- @Test public void testAdd3ProvidersReverse() throws LoginException {
- String firstPath = "/rootel";
- String secondPath = firstPath + "/child";
- String thirdPath = "/apps/sling/sample";
-
- final ResourceResolver firstResolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> first = Mockito.mock(ResourceProvider.class);
- Mockito.when(first.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(firstPath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(firstResolver));
- final ResourceResolver secondResolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> second = Mockito.mock(ResourceProvider.class);
- Mockito.when(second.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(secondPath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(secondResolver));
- final ResourceResolver thirdResolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> third = Mockito.mock(ResourceProvider.class);
- Mockito.when(third.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(thirdPath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(thirdResolver));
-
- providers.add(createRPHandler(first, "rp1", 1, firstPath));
- providers.add(createRPHandler(second, "rp2", 2, secondPath));
- providers.add(createRPHandler(third, "rp3", 3, thirdPath));
- this.providersBasedResolver = null;
-
- assertEqualsResolver(this.mockedRootResolver, getResource("/"));
- assertEqualsResolver(firstResolver, getResource("/rootel"));
- assertEqualsResolver(firstResolver, getResource("/rootel/html.js"));
- assertEqualsResolver(secondResolver, getResource("/rootel/child"));
- assertEqualsResolver(secondResolver, getResource("/rootel/child/html.js"));
- assertEqualsResolver(thirdResolver, getResource("/apps/sling/sample/html.js"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/apps/sling/microsling/html.js"));
- }
-
- @Test public void testRemoveProviders() throws LoginException {
- String firstPath = "/rootel";
- String thirdPath = "/apps/sling/sample";
- String secondPath = firstPath + "/child";
-
- final ResourceResolver firstResolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> first = Mockito.mock(ResourceProvider.class);
- Mockito.when(first.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(firstPath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(firstResolver));
- final ResourceResolver secondResolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> second = Mockito.mock(ResourceProvider.class);
- Mockito.when(second.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(secondPath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(secondResolver));
- final ResourceResolver thirdResolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> third = Mockito.mock(ResourceProvider.class);
- Mockito.when(third.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(thirdPath), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(thirdResolver));
-
- final Map<String, Object> firstProps = new HashMap<String, Object>();
- firstProps.put(Constants.SERVICE_ID, (long)1);
- final Map<String, Object> secondProps = new HashMap<String, Object>();
- secondProps.put(Constants.SERVICE_ID, (long)2);
- final Map<String, Object> thirdProps = new HashMap<String, Object>();
- thirdProps.put(Constants.SERVICE_ID, (long)3);
-
- ResourceProviderHandler firstH = createRPHandler(first, "rp1", 1, firstPath);
- providers.add(firstH);
- providers.add(createRPHandler(second, "rp2", 2, secondPath));
- providers.add(createRPHandler(third, "rp3", 3, thirdPath));
- this.providersBasedResolver = null;
-
- assertEqualsResolver(this.mockedRootResolver, getResource("/"));
- assertEqualsResolver(firstResolver, getResource("/rootel/html.js"));
- assertEqualsResolver(secondResolver, getResource("/rootel/child/html.js"));
-
- providers.remove(firstH);
- this.providersBasedResolver = null;
-
- assertEqualsResolver(this.mockedRootResolver, getResource("/"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/rootel/sddsf/sdfsdf/html.js"));
- assertEqualsResolver(this.mockedRootResolver, getResource("/rootel/html.js"));
- assertEqualsResolver(secondResolver, getResource("/rootel/child/html.js"));
-
- providers.add(firstH);
- this.providersBasedResolver = null;
-
- assertEqualsResolver(this.mockedRootResolver, getResource("/"));
- assertEqualsResolver(firstResolver, getResource("/rootel/html.js"));
- assertEqualsResolver(secondResolver, getResource("/rootel/child/html.js"));
- }
-
- @Test public void testRemoveTheOnlyProvider() throws LoginException {
- long counter = 1;
-
- providers.clear();
- for(String path : new String[] { "/foo", "/", "/foo/bar" }) {
- final ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
- final ResourceProvider<?> p = Mockito.mock(ResourceProvider.class);
- Mockito.when(p.getResource(Mockito.any(ResolveContext.class), Mockito.startsWith(path), Mockito.any(ResourceContext.class), Mockito.any(Resource.class))).thenReturn(new TestResource(resolver));
-
- ++counter;
-
- ResourceProviderHandler h = createRPHandler(p, "rp"+counter, counter, path);
- providers.add(h);
- this.providersBasedResolver = null;
- {
- final Resource r = getResource(path);
- assertEqualsResolver(resolver, r);
- assertFalse(r instanceof SyntheticResource);
- }
-
- providers.remove(h);
- this.providersBasedResolver = null;
- {
- final Resource r = getResource(path);
- // If our provider is indeed gone, we should get one of the following conditions
- if(r == null) {
- //fine
- } else if(!p.equals(r.getResourceResolver())) {
- //fine
- } else {
- fail("Expecting inactive provider after removing it for " + path);
- }
- }
- }
- }
-
- private void assertEqualsResolver(final ResourceResolver resolver, final Resource res) {
- assertEquals(resolver, res.getResourceResolver());
- }
-
- private Resource getResource(String path) throws LoginException {
- return getResolver().getResource(path);
- }
-
- private ResourceResolver getResolver() throws LoginException {
- if (providersBasedResolver == null) {
- final ResourceResolverFactoryActivator activator = new ResourceResolverFactoryActivator();
- activator.resourceAccessSecurityTracker = new ResourceAccessSecurityTracker();
- providersBasedResolver = new ResourceResolverImpl(new CommonResourceResolverFactoryImpl(activator), false, null,
- new ResourceProviderStorageProvider() {
-
- @Override
- public ResourceProviderStorage getResourceProviderStorage() {
- return new ResourceProviderStorage(providers);
- }
- });
- }
- return providersBasedResolver;
- }
-
- private static class TestResource extends AbstractResource {
-
- private final ResourceResolver resourceResolver;
-
- public TestResource(ResourceResolver resourceResolver) {
- this.resourceResolver = resourceResolver;
- }
-
- @Override
- public String getPath() {
- return null;
- }
-
- @Override
- public ResourceMetadata getResourceMetadata() {
- return new ResourceMetadata();
- }
-
- @Override
- public ResourceResolver getResourceResolver() {
- return resourceResolver;
- }
-
- @Override
- public String getResourceType() {
- return null;
- }
-
- @Override
- public String getResourceSuperType() {
- return null;
- }
-
- @Override
- public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
- return null;
- }
-
- @Override
- public boolean hasChildren() {
- return false;
- }
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryTest.java
deleted file mode 100644
index 57234f0..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
-import org.junit.Before;
-import org.junit.Test;
-
-public class ResourceResolverFactoryTest {
-
- private CommonResourceResolverFactoryImpl commonFactory;
-
- @Before public void setup() {
- ResourceResolverFactoryActivator activator = new ResourceResolverFactoryActivator();
- activator.resourceProviderTracker = new ResourceProviderTracker();
- commonFactory = new CommonResourceResolverFactoryImpl(activator);
- }
-
- @Test public void testSingleThreadLocal() throws Exception {
- assertNull(this.commonFactory.getThreadResourceResolver());
- // create first resolver
- final ResourceResolver rr1 = this.commonFactory.getResourceResolver(null);
- assertNotNull(rr1);
- assertEquals(rr1, this.commonFactory.getThreadResourceResolver());
- rr1.close();
-
- assertNull(this.commonFactory.getThreadResourceResolver());
- }
-
- @Test public void testNestedThreadLocal() throws Exception {
- assertNull(this.commonFactory.getThreadResourceResolver());
- // create first resolver
- final ResourceResolver rr1 = this.commonFactory.getResourceResolver(null);
- assertNotNull(rr1);
- assertEquals(rr1, this.commonFactory.getThreadResourceResolver());
-
- // create second resolver
- final ResourceResolver rr2 = this.commonFactory.getResourceResolver(null);
- assertNotNull(rr2);
- assertEquals(rr2, this.commonFactory.getThreadResourceResolver());
-
- rr2.close();
- assertEquals(rr1, this.commonFactory.getThreadResourceResolver());
-
- rr1.close();
- assertNull(this.commonFactory.getThreadResourceResolver());
- }
-
- @Test public void testNestedUnorderedCloseThreadLocal() throws Exception {
- assertNull(this.commonFactory.getThreadResourceResolver());
- // create three resolver
- final ResourceResolver rr1 = this.commonFactory.getResourceResolver(null);
- final ResourceResolver rr2 = this.commonFactory.getResourceResolver(null);
- final ResourceResolver rr3 = this.commonFactory.getResourceResolver(null);
-
- assertEquals(rr3, this.commonFactory.getThreadResourceResolver());
-
- rr2.close();
- assertEquals(rr3, this.commonFactory.getThreadResourceResolver());
-
- rr3.close();
- assertEquals(rr1, this.commonFactory.getThreadResourceResolver());
-
- rr1.close();
- assertNull(this.commonFactory.getThreadResourceResolver());
- }
-
- @Test public void testThreadLocalWithAdmin() throws Exception {
- assertNull(this.commonFactory.getThreadResourceResolver());
- final ResourceResolver rr1 = this.commonFactory.getResourceResolver(null);
- final ResourceResolver admin = this.commonFactory.getAdministrativeResourceResolver(null);
-
- assertEquals(rr1, this.commonFactory.getThreadResourceResolver());
-
- rr1.close();
- assertNull(this.commonFactory.getThreadResourceResolver());
-
- admin.close();
- assertNull(this.commonFactory.getThreadResourceResolver());
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverImplTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverImplTest.java
deleted file mode 100644
index dfa79e9..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverImplTest.java
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import static java.util.Arrays.asList;
-import static org.apache.sling.resourceresolver.impl.MockedResourceResolverImplTest.createRPHandler;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.Session;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.sling.api.SlingException;
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.NonExistingResource;
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.api.resource.SyntheticResource;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.internal.util.reflection.Whitebox;
-
-public class ResourceResolverImplTest {
-
- private CommonResourceResolverFactoryImpl commonFactory;
-
- private ResourceResolver resResolver;
-
- private ResourceResolverFactoryImpl resFac;
-
- private ResourceProviderTracker resourceProviderTracker;
-
- @Before public void setup() throws LoginException {
- ResourceProvider<?> rp = new ResourceProvider<Object>() {
-
- @Override
- public Resource getResource(ResolveContext<Object> ctx, String path, ResourceContext rCtx, Resource parent) {
- return null;
- }
-
- @Override
- public Iterator<Resource> listChildren(ResolveContext<Object> ctx, Resource parent) {
- return null;
- }
- };
-
- List<ResourceProviderHandler> handlers = asList(createRPHandler(rp, "rp1", 0, "/"));
- resourceProviderTracker = mock(ResourceProviderTracker.class);
- ResourceProviderStorage storage = new ResourceProviderStorage(handlers);
- when(resourceProviderTracker.getResourceProviderStorage()).thenReturn(storage);
- ResourceResolverFactoryActivator activator = new ResourceResolverFactoryActivator();
- activator.resourceProviderTracker = resourceProviderTracker;
- activator.resourceAccessSecurityTracker = new ResourceAccessSecurityTracker();
- commonFactory = new CommonResourceResolverFactoryImpl(activator);
- resFac = new ResourceResolverFactoryImpl(commonFactory, /* TODO: using Bundle */ null, null);
- resResolver = resFac.getAdministrativeResourceResolver(null);
- }
-
- @SuppressWarnings("deprecation")
- @Test public void testClose() throws Exception {
- final ResourceResolver rr = new ResourceResolverImpl(commonFactory, false, null, resourceProviderTracker);
- assertTrue(rr.isLive());
- rr.close();
- assertFalse(rr.isLive());
- // close is always allowed to be called
- rr.close();
- assertFalse(rr.isLive());
- // now check all public method - they should all throw!
- try {
- rr.adaptTo(Session.class);
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.clone(null);
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.findResources("a", "b");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getAttribute("a");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getAttributeNames();
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getResource(null);
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getResource(null, "/a");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getSearchPath();
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getUserID();
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.listChildren(null);
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.map("/somepath");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.map(null, "/somepath");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.queryResources("a", "b");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.resolve((HttpServletRequest)null);
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.resolve("/path");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.resolve(null, "/path");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testCloseWithStackTraceLogging() throws Exception {
- ResourceResolverFactoryActivator rrfa = spy(new ResourceResolverFactoryActivator());
- Whitebox.setInternalState(rrfa, "logResourceResolverClosing", true);
- CommonResourceResolverFactoryImpl crrfi = new CommonResourceResolverFactoryImpl(rrfa);
- final ResourceResolver rr = new ResourceResolverImpl(crrfi, false, null, resourceProviderTracker);
- assertTrue(rr.isLive());
- rr.close();
- assertFalse(rr.isLive());
- // close is always allowed to be called
- rr.close();
- assertFalse(rr.isLive());
- // now check all public method - they should all throw!
- try {
- rr.adaptTo(Session.class);
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.clone(null);
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.findResources("a", "b");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getAttribute("a");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getAttributeNames();
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getResource(null);
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getResource(null, "/a");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getSearchPath();
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.getUserID();
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.listChildren(null);
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.map("/somepath");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.map(null, "/somepath");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.queryResources("a", "b");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.resolve((HttpServletRequest)null);
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.resolve("/path");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- try {
- rr.resolve(null, "/path");
- fail();
- } catch (final IllegalStateException ise) {
- // expected
- }
- }
-
- @SuppressWarnings("deprecation")
- @Test public void testBasicAPIAssumptions() throws Exception {
-
- // null resource is accessing /, which exists of course
- final Resource res00 = resResolver.resolve((String) null);
- assertNotNull(res00);
- assertTrue("Resource must be NonExistingResource",
- res00 instanceof NonExistingResource);
- assertEquals("Null path is expected to return root", "/",
- res00.getPath());
-
- // relative paths are treated as if absolute
- final String path01 = "relPath/relPath";
- final Resource res01 = resResolver.resolve(path01);
- assertNotNull(res01);
- assertEquals("Expecting absolute path for relative path", "/" + path01,
- res01.getPath());
- assertTrue("Resource must be NonExistingResource",
- res01 instanceof NonExistingResource);
-
- final String no_resource_path = "/no_resource/at/this/location";
- final Resource res02 = resResolver.resolve(no_resource_path);
- assertNotNull(res02);
- assertEquals("Expecting absolute path for relative path",
- no_resource_path, res02.getPath());
- assertTrue("Resource must be NonExistingResource",
- res01 instanceof NonExistingResource);
-
- try {
- resResolver.resolve((HttpServletRequest) null);
- fail("Expected NullPointerException trying to resolve null request");
- } catch (NullPointerException npe) {
- // expected
- }
-
- final Resource res0 = resResolver.resolve(null, no_resource_path);
- assertNotNull("Expecting resource if resolution fails", res0);
- assertTrue("Resource must be NonExistingResource",
- res0 instanceof NonExistingResource);
- assertEquals("Path must be the original path", no_resource_path,
- res0.getPath());
-
- final HttpServletRequest req1 = mock(HttpServletRequest.class);
- when(req1.getProtocol()).thenReturn("http");
- when(req1.getServerName()).thenReturn("localhost");
- when(req1.getPathInfo()).thenReturn(no_resource_path);
-
- final Resource res1 = resResolver.resolve(req1);
- assertNotNull("Expecting resource if resolution fails", res1);
- assertTrue("Resource must be NonExistingResource",
- res1 instanceof NonExistingResource);
- assertEquals("Path must be the original path", no_resource_path,
- res1.getPath());
-
- final HttpServletRequest req2 = mock(HttpServletRequest.class);
- when(req2.getProtocol()).thenReturn("http");
- when(req2.getServerName()).thenReturn("localhost");
- when(req2.getPathInfo()).thenReturn(null);
- final Resource res2 = resResolver.resolve(req2);
- assertNotNull("Expecting resource if resolution fails", res2);
- assertTrue("Resource must be NonExistingResource",
- res2 instanceof NonExistingResource);
- assertEquals("Path must be the the root path", "/", res2.getPath());
-
- final Resource res3 = resResolver.getResource(null);
- assertNull("Expected null resource for null path", res3);
-
- final Resource res4 = resResolver.getResource(null, null);
- assertNull("Expected null resource for null path", res4);
-
- final Resource res5 = resResolver.getResource(res01, null);
- assertNull("Expected null resource for null path", res5);
- }
-
- @Test public void test_clone_based_on_anonymous() throws Exception {
- final ResourceResolver anon0 = resFac.getResourceResolver((Map<String, Object>) null);
- // no session
- final Session anon0Session = anon0.adaptTo(Session.class);
- assertNull("Session should not be available", anon0Session);
- // no user information, so user id is null
- assertEquals(null, anon0.getUserID());
-
- // same user and workspace
- final ResourceResolver anon1 = anon0.clone(null);
- final Session anon1Session = anon1.adaptTo(Session.class);
- assertEquals(anon0.getUserID(), anon1.getUserID());
- assertNull("Session should not be available", anon1Session);
- anon1.close();
-
- // same workspace but admin user
- final Map<String, Object> admin0Cred = new HashMap<String, Object>();
- admin0Cred.put(ResourceResolverFactory.USER, "admin");
- admin0Cred.put(ResourceResolverFactory.PASSWORD, "admin".toCharArray());
- final ResourceResolver admin0 = anon0.clone(admin0Cred);
- assertEquals("admin", admin0.getUserID());
- admin0.close();
-
- anon0.close();
- }
-
- @Test public void test_clone_based_on_admin() throws Exception {
- final ResourceResolver admin0 = resFac.getAdministrativeResourceResolver((Map<String, Object>) null);
- // no user information, so user id is null
- assertEquals(null, admin0.getUserID());
-
- // same user and workspace
- final ResourceResolver admin1 = admin0.clone(null);
- assertEquals(admin0.getUserID(), admin1.getUserID());
- admin1.close();
-
- // same workspace but anonymous user
- final Map<String, Object> anon0Cred = new HashMap<String, Object>();
- anon0Cred.put(ResourceResolverFactory.USER, "anonymous");
- final ResourceResolver anon0 = admin0.clone(anon0Cred);
- assertEquals("anonymous", anon0.getUserID());
- anon0.close();
-
- admin0.close();
- }
-
- @Test public void test_attributes_from_authInfo() throws Exception {
- final Map<String, Object> authInfo = new HashMap<String, Object>();
- authInfo.put(ResourceResolverFactory.USER, "admin");
- authInfo.put(ResourceResolverFactory.PASSWORD, "admin".toCharArray());
- authInfo.put("testAttributeString", "AStringValue");
- authInfo.put("testAttributeNumber", 999);
- final ResourceResolver rr = resFac.getResourceResolver(authInfo);
-
- assertEquals("AStringValue", rr.getAttribute("testAttributeString"));
- assertEquals(999, rr.getAttribute("testAttributeNumber"));
- assertEquals("admin", rr.getAttribute(ResourceResolverFactory.USER));
- assertNull(rr.getAttribute(ResourceResolverFactory.PASSWORD));
-
- final HashSet<String> validNames = new HashSet<String>();
- validNames.add(ResourceResolverFactory.USER);
- validNames.add("testAttributeString");
- validNames.add("testAttributeNumber");
- final Iterator<String> names = rr.getAttributeNames();
- assertTrue(validNames.remove(names.next()));
- assertTrue(validNames.remove(names.next()));
- assertTrue(validNames.remove(names.next()));
- assertFalse("Expect no more names", names.hasNext());
- assertTrue("Expect validNames set to be empty now",
- validNames.isEmpty());
-
- rr.close();
- }
-
- @Test public void testBasicCrud() throws Exception {
- final Resource r = mock(Resource.class);
- when(r.getPath()).thenReturn("/some");
- try {
- this.resResolver.create(null, "a", null);
- fail("Null parent resource should throw NPE");
- } catch (final NullPointerException npe) {
- // correct
- }
- try {
- this.resResolver.create(r, null, null);
- fail("Null name should throw NPE");
- } catch (final NullPointerException npe) {
- // correct
- }
- try {
- this.resResolver.create(r, "a/b", null);
- fail("Slash in name should throw illegal argument exception");
- } catch (final IllegalArgumentException pe) {
- // correct
- }
- try {
- this.resResolver.create(r, "a", null);
- fail("This should be unsupported.");
- } catch (final PersistenceException uoe) {
- // correct
- }
- }
-
- @Test public void test_getResourceSuperType() {
- final PathBasedResourceResolverImpl resolver = getPathBasedResourceResolver();
-
- // the resources to test
- final Resource r = resolver.add(new SyntheticResource(resolver, "/a", "a:b"));
- final Resource r2 = resolver.add(new SyntheticResource(resolver, "/a2", "a:c"));
- resolver.add(new SyntheticResourceWithSupertype(resolver, "/a/b", "x:y", "t:c"));
-
- assertEquals("t:c", resolver.getParentResourceType(r.getResourceType()));
- assertNull(resolver.getParentResourceType(r2.getResourceType()));
- }
-
- @Test public void testIsResourceType() {
- final PathBasedResourceResolverImpl resolver = getPathBasedResourceResolver();
-
- final Resource r = resolver.add(new SyntheticResourceWithSupertype(resolver, "/a", "a:b", "d:e"));
- resolver.add(new SyntheticResourceWithSupertype(resolver, "/d/e", "x:y", "t:c"));
-
- assertTrue(resolver.isResourceType(r, "a:b"));
- assertTrue(resolver.isResourceType(r, "d:e"));
- assertFalse(resolver.isResourceType(r, "x:y"));
- assertTrue(resolver.isResourceType(r, "t:c"));
- assertFalse(resolver.isResourceType(r, "h:p"));
- }
-
- @Test public void testIsResourceTypeWithPaths() {
- final PathBasedResourceResolverImpl resolver = getPathBasedResourceResolver();
-
- /**
- * prepare resource type hierarchy
- * /types/1
- * +- /types/2
- * +- /types/3
- */
- resolver.add(new SyntheticResourceWithSupertype(resolver, "/types/1", "/types/component", "/types/2"));
- resolver.add(new SyntheticResourceWithSupertype(resolver, "/types/2", "/types/component", "/types/3"));
- resolver.add(new SyntheticResource(resolver, "/types/3", "/types/component"));
-
- Resource resourceT1 = resolver.add(new SyntheticResource(resolver, "/resourceT1", "/types/1"));
- Resource resourceT2 = resolver.add(new SyntheticResource(resolver, "/resourceT2", "/types/2"));
- Resource resourceT3 = resolver.add(new SyntheticResource(resolver, "/resourceT3", "/types/3"));
-
- assertTrue(resolver.isResourceType(resourceT1, "/types/1"));
- assertTrue(resolver.isResourceType(resourceT1, "/types/2"));
- assertTrue(resolver.isResourceType(resourceT1, "/types/3"));
- assertFalse(resolver.isResourceType(resourceT1, "/types/component"));
- assertFalse(resolver.isResourceType(resourceT1, "/types/unknown"));
-
- assertFalse(resolver.isResourceType(resourceT2, "/types/1"));
- assertTrue(resolver.isResourceType(resourceT2, "/types/2"));
- assertTrue(resolver.isResourceType(resourceT2, "/types/3"));
- assertFalse(resolver.isResourceType(resourceT2, "/types/component"));
- assertFalse(resolver.isResourceType(resourceT2, "/types/unknown"));
-
- assertFalse(resolver.isResourceType(resourceT3, "/types/1"));
- assertFalse(resolver.isResourceType(resourceT3, "/types/2"));
- assertTrue(resolver.isResourceType(resourceT3, "/types/3"));
- assertFalse(resolver.isResourceType(resourceT3, "/types/component"));
- assertFalse(resolver.isResourceType(resourceT3, "/types/unknown"));
- }
-
- @Test(expected=SlingException.class) public void testIsResourceCyclicHierarchyDirect() {
- final PathBasedResourceResolverImpl resolver = getPathBasedResourceResolver();
-
- /**
- * prepare resource type hierarchy
- * /types/1 <---+
- * +- /types/2 -+
- */
- resolver.add(new SyntheticResourceWithSupertype(resolver, "/types/1", "/types/component", "/types/2"));
- resolver.add(new SyntheticResourceWithSupertype(resolver, "/types/2", "/types/component", "/types/1"));
-
- Resource resource = resolver.add(new SyntheticResource(resolver, "/resourceT1", "/types/1"));
-
- assertTrue(resolver.isResourceType(resource, "/types/1"));
- assertTrue(resolver.isResourceType(resource, "/types/2"));
-
- // this should throw a SlingException when detecting the cyclic hierarchy
- resolver.isResourceType(resource, "/types/unknown");
- }
-
- @Test(expected=SlingException.class) public void testIsResourceCyclicHierarchyIndirect() {
- final PathBasedResourceResolverImpl resolver = getPathBasedResourceResolver();
-
- /**
- * prepare resource type hierarchy
- * /types/1 <----+
- * +- /types/2 |
- * +- /types/3 -+
- */
- resolver.add(new SyntheticResourceWithSupertype(resolver, "/types/1", "/types/component", "/types/2"));
- resolver.add(new SyntheticResourceWithSupertype(resolver, "/types/2", "/types/component", "/types/3"));
- resolver.add(new SyntheticResourceWithSupertype(resolver, "/types/3", "/types/component", "/types/1"));
-
- Resource resource = resolver.add(new SyntheticResource(resolver, "/resourceT1", "/types/1"));
-
- assertTrue(resolver.isResourceType(resource, "/types/1"));
- assertTrue(resolver.isResourceType(resource, "/types/2"));
- assertTrue(resolver.isResourceType(resource, "/types/3"));
-
- // this should throw a SlingException when detecting the cyclic hierarchy
- resolver.isResourceType(resource, "/types/unknown");
- }
-
- private PathBasedResourceResolverImpl getPathBasedResourceResolver() {
- try {
- final List<ResourceResolver> resolvers = new ArrayList<ResourceResolver>();
- final PathBasedResourceResolverImpl resolver = new PathBasedResourceResolverImpl(resolvers, resourceProviderTracker);
- resolvers.add(resolver);
- return resolver;
- }
- catch (LoginException ex) {
- throw new RuntimeException(ex);
- }
- }
-
- private static class PathBasedResourceResolverImpl extends ResourceResolverImpl {
-
- private final Map<String, Resource> resources = new HashMap<String, Resource>();
-
- public PathBasedResourceResolverImpl(final List<ResourceResolver> resolvers, final ResourceProviderTracker resourceProviderTracker) throws LoginException {
- this(new CommonResourceResolverFactoryImpl(new ResourceResolverFactoryActivator()) {
- @Override
- public ResourceResolver getAdministrativeResourceResolver(
- Map<String, Object> authenticationInfo) throws LoginException {
- return resolvers.get(0);
- }
- }, resourceProviderTracker);
- }
-
- public PathBasedResourceResolverImpl(CommonResourceResolverFactoryImpl factory, ResourceProviderTracker resourceProviderTracker) throws LoginException {
- super(factory, false, null, resourceProviderTracker);
- }
-
- public Resource add(final Resource r) {
- this.resources.put(r.getPath(), r);
- return r;
- }
-
- @Override
- public String[] getSearchPath() {
- return new String[] {""};
- }
-
- @Override
- public Resource getResource(final String path) {
- final String p = (path.startsWith("/") ? path : "/" + path);
- return this.resources.get(p);
- }
- }
-
- private static class SyntheticResourceWithSupertype extends SyntheticResource {
-
- private final String resourceSuperType;
-
- public SyntheticResourceWithSupertype(ResourceResolver resourceResolver, String path,
- String resourceType, String resourceSuperType) {
- super(resourceResolver, path, resourceType);
- this.resourceSuperType = resourceSuperType;
- }
-
- @Override
- public String getResourceSuperType() {
- return this.resourceSuperType;
- }
-
- }
-
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverMangleNamespacesTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverMangleNamespacesTest.java
deleted file mode 100644
index f994979..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/ResourceResolverMangleNamespacesTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.resourceresolver.impl;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.Arrays;
-import java.util.Iterator;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.commons.collections.IteratorUtils;
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-/** Test ResourceResolverImpl.mangleNamespaces methods */
-public class ResourceResolverMangleNamespacesTest {
- private ResourceResolverImpl rr;
-
- @Mock
- private Session mockedSession;
-
- private Session activeSession;
-
- public static final String NS_PREFIX = "testNS";
- public static final String NS_URL = "http://example.com/namespaces/testNS";
-
- @Before
- public void setup() throws RepositoryException, LoginException {
- MockitoAnnotations.initMocks(this);
- activeSession = mockedSession;
-
- // Setup a ResourceResolverImpl with namespace mangling and unmangling
- final ResourceResolverFactoryActivator act = new ResourceResolverFactoryActivator() {
- @Override
- public boolean isMangleNamespacePrefixes() {
- return true;
- }
- };
-
- Mockito.when(mockedSession.getNamespacePrefix(NS_PREFIX)).thenReturn(NS_URL);
-
- final ResourceProvider<?> rp = new ResourceProvider<Object>() {
-
- @SuppressWarnings("unchecked")
- @Override
- public @CheckForNull <AdapterType> AdapterType adaptTo(final @Nonnull ResolveContext<Object> ctx,
- final @Nonnull Class<AdapterType> type) {
- if (type.equals(Session.class)) {
- return (AdapterType) activeSession;
- } else {
- return null;
- }
- }
-
- @Override
- public Resource getResource(ResolveContext<Object> ctx, String path, ResourceContext rCtx, Resource parent) {
- return null;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public Iterator<Resource> listChildren(ResolveContext<Object> ctx, Resource parent) {
- return IteratorUtils.emptyIterator();
- }
- };
-
- final CommonResourceResolverFactoryImpl fac = new CommonResourceResolverFactoryImpl(act);
-
- rr = new ResourceResolverImpl(fac, false, null, new ResourceProviderStorageProvider() {
-
- @Override
- public ResourceProviderStorage getResourceProviderStorage() {
- return new ResourceProviderStorage(Arrays.asList(MockedResourceResolverImplTest.createRPHandler(rp, "rp1", 0, "/")));
- }
- });
- }
-
- @Test
- public void testUrlWithPath() {
- assertEquals("http://example.com/some/path", rr.map("http://example.com/some/path"));
- }
-
- @Test
- public void testMangleHttp() {
- assertEquals("http://example.com/path/_with_colon", rr.map("http://example.com/path/with:colon"));
- }
-
- @Test
- public void testUnmangleHttp() {
- final Resource r = rr.resolve(null, "http://example.com/path/_with_mangling");
- assertEquals("/http://example.com/path/with:mangling", r.getPath());
- }
-
- @Test
- public void testUnmangleNoSession() {
- activeSession = null;
- final Resource r = rr.resolve(null, "http://example.com/path/_with_mangling");
- assertEquals("/http://example.com/path/_with_mangling", r.getPath());
- }
-
- @Test
- public void testManglePath() {
- assertEquals("/example.com/path/_with_colon", rr.map("/example.com/path/with:colon"));
- }
-
- @Test
- public void testUnmanglePath() {
- final Resource r = rr.resolve(null, "/example.com/path/_with_mangling");
- assertEquals("/example.com/path/with:mangling", r.getPath());
- }
-
- @Test
- public void testUrlNoPath() {
- assertEquals("http://withSlash.com/", rr.map("http://withSlash.com/"));
- assertEquals("http://noSlash.com", rr.map("http://noSlash.com"));
- assertEquals("http://nosuffix", rr.map("http://nosuffix"));
- }
-
- @Test
- public void testWeirdCases() {
- assertEquals("http://foo", rr.map("http://foo"));
- assertEquals("http://", rr.map("http://"));
- assertEquals("http:/", rr.map("http:/"));
- assertEquals("http:", rr.map("http:"));
- assertEquals("http", rr.map("http"));
-
- assertEquals("gopher://foo", rr.map("gopher://foo"));
- assertEquals("gopher://", rr.map("gopher://"));
- assertEquals("gopher:/", rr.map("gopher:/"));
- assertEquals("gopher:", rr.map("gopher:"));
- assertEquals("gopher", rr.map("gopher"));
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/SimpleValueMapImpl.java b/src/test/java/org/apache/sling/resourceresolver/impl/SimpleValueMapImpl.java
deleted file mode 100644
index f1ed9c1..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/SimpleValueMapImpl.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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 SF 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.resourceresolver.impl;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.sling.api.resource.ValueMap;
-
-public class SimpleValueMapImpl implements ValueMap {
-
- private Map<String, Object> delegate;
-
- public SimpleValueMapImpl() {
- delegate = new HashMap<String, Object>();
- }
-
- public void clear() {
- delegate.clear();
- }
-
- public boolean containsKey(Object key) {
- return delegate.containsKey(key);
- }
-
- public boolean containsValue(Object value) {
- return delegate.containsValue(value);
- }
-
- public Set<java.util.Map.Entry<String, Object>> entrySet() {
- return delegate.entrySet();
- }
-
- public Object get(Object key) {
- return delegate.get(key);
- }
-
- public boolean isEmpty() {
- return delegate.isEmpty();
- }
-
- public Set<String> keySet() {
- return delegate.keySet();
- }
-
- public Object put(String key, Object value) {
- return delegate.put(key, value);
- }
-
- public void putAll(Map<? extends String, ? extends Object> m) {
- delegate.putAll(m);
- }
-
- public Object remove(Object key) {
- return delegate.remove(key);
- }
-
- public int size() {
- return delegate.size();
- }
-
- public Collection<Object> values() {
- return delegate.values();
- }
-
- @SuppressWarnings("unchecked")
- public <T> T get(String name, Class<T> type) {
- Object o = delegate.get(name);
- if ( type.equals(String[].class) && ! ( o instanceof String[])) {
- o = new String[] { String.valueOf(o) };
- }
- return (T) o;
- }
-
- @SuppressWarnings("unchecked")
- public <T> T get(String name, T defaultValue) {
- if ( delegate.containsKey(name)) {
- return (T) delegate.get(name);
- }
- return defaultValue;
- }
-
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/helper/RedirectResourceTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/helper/RedirectResourceTest.java
deleted file mode 100644
index 2c6292d..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/helper/RedirectResourceTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.Map;
-
-import org.apache.sling.api.resource.PersistableValueMap;
-import org.apache.sling.api.resource.ValueMap;
-import org.junit.Test;
-
-@SuppressWarnings("deprecation")
-public class RedirectResourceTest {
-
- @Test public void testRedirectResource() {
-
- final String path = "/redir/path";
- final String target = "/redir/target";
- final int status = 999;
- final RedirectResource res = new RedirectResource(null, path, target,
- status);
-
- assertEquals(path, res.getPath());
- assertEquals(RedirectResource.RT_SLING_REDIRECT, res.getResourceType());
-
- final Map<?, ?> map = res.adaptTo(Map.class);
- assertNotNull("Expected Map adapter", map);
- assertEquals(target, map.get(RedirectResource.PROP_SLING_TARGET));
- assertEquals(status, ((Integer) map.get(RedirectResource.PROP_SLING_STATUS)).intValue());
-
- final ValueMap valueMap = res.adaptTo(ValueMap.class);
- assertNotNull("Expected ValueMap adapter", valueMap);
- assertEquals(target, valueMap.get(RedirectResource.PROP_SLING_TARGET));
- assertEquals(status, ((Integer) valueMap.get(RedirectResource.PROP_SLING_STATUS)).intValue());
- assertEquals(status, valueMap.get(RedirectResource.PROP_SLING_STATUS, Integer.class).intValue());
-
- final PersistableValueMap persistableValueMap = res.adaptTo(PersistableValueMap.class);
- assertNull("Unexpected PersistableValueMap adapter",
- persistableValueMap);
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourcePathIteratorTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourcePathIteratorTest.java
deleted file mode 100644
index d70ffd7..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourcePathIteratorTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-import org.junit.Test;
-
-public class ResourcePathIteratorTest {
-
- @Test public void testNull() {
- ResourcePathIterator rpi = new ResourcePathIterator(null);
- assertFinished(rpi);
- }
-
- @Test public void testEmpty() {
- ResourcePathIterator rpi = new ResourcePathIterator("");
- assertFinished(rpi);
- }
-
- @Test public void testRoot() {
- ResourcePathIterator rpi = new ResourcePathIterator("/");
- assertNext("/", rpi);
- assertFinished(rpi);
- }
-
- @Test public void testSlashed() {
- ResourcePathIterator rpi = new ResourcePathIterator("/root/child");
- assertNext("/root/child", rpi);
- assertFinished(rpi);
- }
-
- @Test public void testSlashedTrailingSlash1() {
- ResourcePathIterator rpi = new ResourcePathIterator("/root/child/");
- assertNext("/root/child", rpi);
- assertFinished(rpi);
- }
-
- @Test public void testSlashedTrailingSlash2() {
- ResourcePathIterator rpi = new ResourcePathIterator("/root/child//");
- assertNext("/root/child", rpi);
- assertFinished(rpi);
- }
-
- @Test public void testDotted() {
- ResourcePathIterator rpi = new ResourcePathIterator("/root.child");
- assertNext("/root.child", rpi);
- assertNext("/root", rpi);
- assertFinished(rpi);
- }
-
- @Test public void testMixed() {
- ResourcePathIterator rpi = new ResourcePathIterator(
- "/root/child.print.a4.html/with/suffix");
- assertNext("/root/child.print.a4.html/with/suffix", rpi);
- assertNext("/root/child.print.a4", rpi);
- assertNext("/root/child.print", rpi);
- assertNext("/root/child", rpi);
- assertFinished(rpi);
- }
-
- @Test public void testNoSeparators() {
- final Iterator<String> rpi = new ResourcePathIterator(
- "MickeyMouseWasHere");
- assertNext("MickeyMouseWasHere", rpi);
- assertFinished(rpi);
- }
-
- @Test public void testGetA() {
- final Iterator<String> rpi = new ResourcePathIterator(
- "/some/stuff/more.a4.html");
- assertNext("/some/stuff/more.a4.html", rpi);
- assertNext("/some/stuff/more.a4", rpi);
- assertNext("/some/stuff/more", rpi);
- assertFinished(rpi);
- }
-
- @Test public void testGetB() {
- final Iterator<String> rpi = new ResourcePathIterator(
- "/some/stuff/more.html");
- assertNext("/some/stuff/more.html", rpi);
- assertNext("/some/stuff/more", rpi);
- assertFinished(rpi);
- }
-
- @Test public void testHeadB() {
- final Iterator<String> rpi = new ResourcePathIterator(
- "/some/stuff/more.html");
- assertNext("/some/stuff/more.html", rpi);
- assertNext("/some/stuff/more", rpi);
- assertFinished(rpi);
- }
-
- @Test public void testGetC() {
- final Iterator<String> it = new ResourcePathIterator("/some/stuff/more");
- assertNext("/some/stuff/more", it);
- assertFinished(it);
- }
-
- @Test public void testGetD() {
- final Iterator<String> it = new ResourcePathIterator(
- "/some/stuff.print/more.html");
- assertNext("/some/stuff.print/more.html", it);
- assertNext("/some/stuff.print/more", it);
- assertNext("/some/stuff", it);
- assertFinished(it);
- }
-
- @Test public void testRelativePathGet() {
- final Iterator<String> it = new ResourcePathIterator("some/stuff.print");
- assertNext("some/stuff.print", it);
- assertNext("some/stuff", it);
- assertFinished(it);
- }
-
- private void assertNext(String expected, Iterator<String> iterator) {
- assertTrue("Iterator must have next", iterator.hasNext());
- assertEquals("Incorrect next value", expected, iterator.next());
- }
-
- private void assertFinished(Iterator<String> iterator) {
-
- assertFalse("Iterator must not have next", iterator.hasNext());
-
- try {
- iterator.next();
- fail("Iterator should throw NoSuchElementException");
- } catch (NoSuchElementException nsee) {
- // expected
- }
-
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControlTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControlTest.java
deleted file mode 100644
index 40dc392..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/helper/ResourceResolverControlTest.java
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.hasEntry;
-import static org.hamcrest.Matchers.not;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.hamcrest.Matchers.nullValue;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.PersistenceException;
-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.ValueMap;
-import org.apache.sling.api.resource.runtime.dto.AuthType;
-import org.apache.sling.resourceresolver.impl.Fixture;
-import org.apache.sling.resourceresolver.impl.ResourceAccessSecurityTracker;
-import org.apache.sling.resourceresolver.impl.SimpleValueMapImpl;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderInfo;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorageProvider;
-import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.apache.sling.testing.mock.osgi.MockOsgi;
-import org.hamcrest.Matchers;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.osgi.framework.BundleContext;
-
-@SuppressWarnings("unchecked")
-public class ResourceResolverControlTest {
-
- // query language names
- private static final String QL_MOCK = "MockQueryLanguage";
- private static final String QL_ANOTHER_MOCK = "AnotherMockQueryLanguage";
- private static final String QL_NOOP = "NoopQueryLanguage";
-
- // query definitions
- private static final String QUERY_MOCK_FIND_ALL = "FIND ALL";
-
- private ResourceResolverControl crp;
- private List<ResourceProviderHandler> handlers;
- private ResourceProvider<Object> subProvider;
- private Map<String, Object> authInfo;
- private ResourceProvider<Object> rootProvider;
- private Resource subProviderResource;
- private Resource somethingResource;
- private ResourceResolverContext context;
-
- @Before
- public void prepare() throws Exception {
-
- BundleContext bc = MockOsgi.newBundleContext();
-
- Fixture fixture = new Fixture(bc);
-
- // sub-provider
- subProvider = Mockito.mock(ResourceProvider.class);
- ResourceProviderInfo info = fixture.registerResourceProvider(subProvider, "/some/path", AuthType.required);
- ResourceProviderHandler handler = new ResourceProviderHandler(bc, info);
- when(subProvider.getQueryLanguageProvider()).thenReturn(new SimpleQueryLanguageProvider(QL_MOCK, QL_ANOTHER_MOCK) {
- @Override
- public Iterator<ValueMap> queryResources(ResolveContext<Object> ctx, String query, String language) {
- if ( query.equals(QUERY_MOCK_FIND_ALL) && language.equals(QL_MOCK)) {
- SimpleValueMapImpl valueMap = new SimpleValueMapImpl();
- valueMap.put("key", "value");
- return Collections.<ValueMap> singletonList(valueMap).iterator();
- }
-
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language) {
-
- if ( query.equals(QUERY_MOCK_FIND_ALL) && language.equals(QL_MOCK)) {
- return Collections.<Resource> singletonList(newMockResource("/some/path/object")).iterator();
- }
-
- throw new UnsupportedOperationException();
-
- }
- });
- handler.activate();
-
- rootProvider = mock(ResourceProvider.class);
- ResourceProviderInfo rootInfo = fixture.registerResourceProvider(rootProvider, "/", AuthType.required);
- ResourceProviderHandler rootHandler = new ResourceProviderHandler(bc, rootInfo);
- when(rootProvider.getQueryLanguageProvider()).thenReturn(new SimpleQueryLanguageProvider(QL_NOOP));
- rootHandler.activate();
-
- // configure mock resources
- Resource root = configureResourceAt(rootProvider, "/");
- somethingResource = configureResourceAt(rootProvider, "/something");
- subProviderResource = configureResourceAt(subProvider, "/some/path/object");
-
- // configure query at '/'
- when(rootProvider.listChildren((ResolveContext<Object>) Mockito.anyObject(), Mockito.eq(root))).thenReturn(Collections.singleton(somethingResource).iterator());
-
- ResourceResolver rr = mock(ResourceResolver.class);
- ResourceAccessSecurityTracker securityTracker = Mockito.mock(ResourceAccessSecurityTracker.class);
- authInfo = Collections.emptyMap();
-
- handlers = Arrays.asList(rootHandler, handler);
- final ResourceProviderStorage storage = new ResourceProviderStorage(handlers);
-
- crp = new ResourceResolverControl(false, authInfo, new ResourceProviderStorageProvider() {
-
- @Override
- public ResourceProviderStorage getResourceProviderStorage() {
- return storage;
- }
- });
- context = new ResourceResolverContext(rr, securityTracker);
- }
-
- /**
- * Configures the provider to return a mock resource for the specified path
- * @return
- */
- private <T> Resource configureResourceAt(ResourceProvider<T> provider, String path) {
-
- Resource mockResource = newMockResource(path);
-
- when(provider.getResource((ResolveContext<T>) Mockito.any(), Mockito.eq(path), (ResourceContext) Mockito.any(), (Resource) Mockito.any()))
- .thenReturn(mockResource);
-
- return mockResource;
- }
-
- private Resource newMockResource(String path) {
-
- Resource mockResource = mock(Resource.class);
- when(mockResource.getPath()).thenReturn(path);
- when(mockResource.getName()).thenReturn(ResourceUtil.getName(path));
- when(mockResource.getResourceMetadata()).thenReturn(mock(ResourceMetadata.class));
- when(mockResource.getChildren()).thenReturn(Collections.<Resource> emptyList());
-
- return mockResource;
- }
-
- /**
- * Verifies that login and logout calls are invoked as expected on
- * ResourceProviders with authType = {@link AuthType#required}
- */
- @Test
- public void loginLogout() throws LoginException {
-
- context.getProviderManager().authenticateAll(handlers, crp);
-
- verify(subProvider).authenticate(authInfo);
-
- crp.close();
-
- verify(subProvider).logout(mockContext());
- }
-
- private ResolveContext<Object> mockContext() {
- return (ResolveContext<Object>) Mockito.any();
- }
-
- /**
- * Verifies that a synthetic resource is returned for a path which holds no
- * actual resource but is an ancestor of another resource provider
- */
- @Test
- public void getResource_synthetic() {
-
- Resource resource = crp.getResource(context, "/some", null, null, false);
-
- assertTrue("Not a syntethic resource : " + resource, ResourceUtil.isSyntheticResource(resource));
- }
-
- /**
- * Verifies that a getResource call for a missing resource returns null
- */
- @Test
- public void getResource_missing() {
- assertThat(crp.getResource(context, "/nothing", null, null, false), nullValue());
- }
-
- /**
- * Verifies that a resource is returned when it should be
- */
- @Test
- public void getResource_found() {
- assertThat(crp.getResource(context, "/something", null, null, false), not(nullValue()));
- assertThat(crp.getResource(context, "/some/path/object", null, null, false), not(nullValue()));
- }
-
-
- /**
- * Verifies that the existing parent of a resource is found
- */
- @Test
- public void getParent_found() {
- Resource parent = crp.getParent(context, ResourceUtil.getParent(somethingResource.getPath()), somethingResource);
- assertThat(parent, notNullValue());
- assertThat("parent.path", parent.getPath(), equalTo("/"));
- }
-
-
-
- /**
- * Verifies that a synthetic parent is returned for a resource without an actual parent
- */
- @Test
- public void getParent_synthetic() {
- Resource parent = crp.getParent(context, ResourceUtil.getParent(subProviderResource.getPath()), subProviderResource);
- assertThat(parent, notNullValue());
- assertTrue("parent is a synthetic resource", ResourceUtil.isSyntheticResource(parent));
- }
-
- /**
- * Test parent from a different provider
- */
- @Test
- public void getParent_differentProviders() {
- final Resource childResource = mock(Resource.class);
- when(childResource.getPath()).thenReturn("/some/path");
- when(subProvider.getResource((ResolveContext<Object>) Mockito.anyObject(), Mockito.eq("/some/path"), (ResourceContext) Mockito.anyObject(), (Resource)Mockito.eq(null))).thenReturn(childResource);
-
- final Resource parentResource = mock(Resource.class);
- when(parentResource.getPath()).thenReturn("/some");
- when(rootProvider.getResource((ResolveContext<Object>) Mockito.anyObject(), Mockito.eq("/some"), (ResourceContext) Mockito.anyObject(), (Resource)Mockito.eq(null))).thenReturn(parentResource);
-
- Resource child = crp.getResource(context, "/some/path", null, null, false);
- assertNotNull(child);
- assertTrue(childResource == child);
-
- Resource parent = crp.getParent(context, ResourceUtil.getParent(child.getPath()), child);
- assertNotNull(parent);
- assertTrue(parentResource == parent);
- }
-
- /**
- * Verifies that listing the children at root lists both the synthetic and the 'real' children
- */
- @Test
- public void listChildren_root() {
- Resource root = crp.getResource(context, "/", null, null, false);
- Iterator<Resource> children = crp.listChildren(context, root);
-
- Map<String, Resource> all = new HashMap<String, Resource>();
- while ( children.hasNext() ) {
- Resource child = children.next();
- all.put(child.getPath(), child);
- }
-
- assertThat(all.entrySet(), Matchers.hasSize(2));
- assertThat("Resource at /something", all.get("/something"), not(nullValue()));
- assertThat("Resource at /some", all.get("/some"), not(nullValue()));
- }
-
- /**
- * Verifies listing the children at a level below the root
- */
- @Test
- public void listChildren_lowerLevel() {
-
- Resource root = crp.getResource(context, "/some", null, null, false);
- Iterator<Resource> children = crp.listChildren(context, root);
- Map<String, Resource> all = new HashMap<String, Resource>();
-
- while ( children.hasNext() ) {
- Resource child = children.next();
- all.put(child.getPath(), child);
- }
-
- assertThat(all.entrySet(), Matchers.hasSize(1));
- assertThat("Resource at /some/path", all.get("/some/path"), not(nullValue()));
-
- }
-
- /**
- * Verifies copying resources between the same ResourceProvider
- *
- * @throws PersistenceException persistence exception
- */
- @Test
- public void copy_sameProvider() throws PersistenceException {
-
- when(subProvider.copy(mockContext(), Mockito.eq("/some/path/object"), Mockito.eq("/some/path/new")))
- .thenReturn(true);
- configureResourceAt(subProvider, "/some/path/new/object");
- configureResourceAt(subProvider, "/some/path/new");
-
- Resource resource = crp.copy(context, "/some/path/object", "/some/path/new");
-
-
- assertThat(resource, not(nullValue()));
- }
-
- /**
- * Verifies copying resources between different ResourceProviders
- *
- * @throws PersistenceException persistence exception
- */
- @Test
- public void copy_differentProvider() throws PersistenceException {
-
- Resource newRes = newMockResource("/object");
- when(rootProvider.create(mockContext(), Mockito.eq("/object"), Mockito.anyMap()))
- .thenReturn(newRes);
-
- Resource resource = crp.copy(context, "/some/path/object", "/");
-
- assertThat(resource, not(nullValue()));
- }
-
- /**
- * Verifies moving resources between the same ResourceProvider
- *
- * @throws PersistenceException persistence exception
- */
- @Test
- public void move_sameProvider() throws PersistenceException {
-
- when(subProvider.move(mockContext(), Mockito.eq("/some/path/object"), Mockito.eq("/some/path/new")))
- .thenReturn(true);
- configureResourceAt(subProvider, "/some/path/new/object");
- configureResourceAt(subProvider, "/some/path/new");
-
- Resource resource = crp.move(context, "/some/path/object", "/some/path/new");
-
- assertThat(resource, not(nullValue()));
- }
-
- /**
- * Verifies moving resources between different ResourceProviders
- *
- * @throws PersistenceException persistence exception
- */
- @Test
- public void move_differentProvider() throws PersistenceException {
-
- Resource newRes = newMockResource("/object");
- when(rootProvider.create(mockContext(), Mockito.eq("/object"), Mockito.anyMap())).thenReturn(newRes);
-
- Resource resource = crp.move(context, "/some/path/object", "/");
-
- assertThat(resource, not(nullValue()));
-
- verify(subProvider).delete(mockContext(), Mockito.eq(subProviderResource));
- }
-
- /**
- * Verifies listing the query languages
- */
- @Test
- public void queryLanguages() throws PersistenceException {
-
- assertThat(crp.getSupportedLanguages(context), arrayContainingInAnyOrder(QL_NOOP, QL_MOCK, QL_ANOTHER_MOCK));
- }
-
- /**
- * Verifies running a query
- */
- @Test
- public void queryResources() throws PersistenceException {
-
- Iterator<Map<String, Object>> queryResources = crp.queryResources(context, QUERY_MOCK_FIND_ALL, QL_MOCK);
-
- int count = 0;
-
- while ( queryResources.hasNext() ) {
- assertThat("ValueMap returned from query", queryResources.next(), hasEntry("key", (Object) "value"));
- count++;
- }
-
- assertThat("query result count", count, Matchers.equalTo(1));
- }
-
- /**
- * Verifies finding resources
- */
- @Test
- public void findResource() throws PersistenceException {
-
- Iterator<Resource> resources = crp.findResources(context, QUERY_MOCK_FIND_ALL, QL_MOCK);
-
- int count = 0;
-
- while ( resources.hasNext() ) {
- assertThat("resources[0].path", resources.next().getPath(), equalTo("/some/path/object"));
- count++;
- }
-
- assertThat("query result count", count, Matchers.equalTo(1));
- }
-
- /**
- * Simple test-only QueryLanguageProvider
- *
- */
- private static class SimpleQueryLanguageProvider implements QueryLanguageProvider<Object> {
-
- private final String[] queryLanguages;
-
- public SimpleQueryLanguageProvider(String... queryLanguages) {
- this.queryLanguages = queryLanguages;
- }
-
- @Override
- public String[] getSupportedLanguages(ResolveContext<Object> ctx) {
- return queryLanguages;
- }
-
- @Override
- public Iterator<ValueMap> queryResources(ResolveContext<Object> ctx, String query, String language) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Iterator<Resource> findResources(ResolveContext<Object> ctx, String query, String language) {
- throw new UnsupportedOperationException();
- }
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/helper/StarResourceTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/helper/StarResourceTest.java
deleted file mode 100644
index 72c2689..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/helper/StarResourceTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.resourceresolver.impl.helper;
-
-import static org.junit.Assert.assertEquals;
-
-import org.apache.sling.api.resource.ResourceMetadata;
-import org.junit.Test;
-
-/** Test the StarResource */
-public class StarResourceTest {
-
- private void assertSplit(String requestPath, String path, String pathInfo) {
- final ResourceMetadata rm = StarResource.getResourceMetadata(requestPath);
- assertEquals("For requestPath=" + requestPath + ", path matches", path, rm.getResolutionPath());
- assertEquals("For requestPath=" + requestPath + ", pathInfo matches", pathInfo, rm.getResolutionPathInfo());
- }
-
- @Test public void testSimplePath() {
- assertSplit("/foo/*.html", "/foo/*", ".html");
- }
-
- @Test public void testNoExtension() {
- assertSplit("/foo/*", "/foo/*", "");
- }
-
- @Test public void testNoStar() {
- assertSplit("/foo/bar.html", "/foo/bar.html", null);
- }
-
- @Test public void testTwoStars() {
- assertSplit("/foo/*.html/*.txt", "/foo/*", ".html/*.txt");
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/helper/URI2Test.java b/src/test/java/org/apache/sling/resourceresolver/impl/helper/URI2Test.java
deleted file mode 100644
index 432feae..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/helper/URI2Test.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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 SF 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.resourceresolver.impl.helper;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * Unit test to cover areas not already covered by the URI test from HttpClient.
- */
-public class URI2Test {
-
- @Test
- public void testCreate() {
- URI u = new URI("http","//localhost:8080/to/a/resource", "fragment");
- Assert.assertEquals("http://localhost:8080/to/a/resource", u.toString());
- u = new URI("http://localhost:8080/to/a/r%20e%20s%20o%20u%20r%20c%20e", true, "UTF-8");
- Assert.assertEquals("http://localhost:8080/to/a/r%20e%20s%20o%20u%20r%20c%20e", u.toString());
- u = new URI("http://localhost:8080/to/a/r e s o u r c e", false, "UTF-8");
- Assert.assertEquals("http://localhost:8080/to/a/r%20e%20s%20o%20u%20r%20c%20e", u.toString());
- Assert.assertEquals("r%20e%20s%20o%20u%20r%20c%20e", new String(u.getRawName()));
- Assert.assertEquals("/to/a/r%20e%20s%20o%20u%20r%20c%20e", new String(u.getRawPathQuery()));
-
- }
-
- @Test
- public void testClone() throws CloneNotSupportedException {
- URI url = new URI("http://jakarta.apache.org", false);
- URI uriClone = (URI) url.clone();
- Assert.assertEquals(url,uriClone);
- Assert.assertEquals(url.hashCode(),uriClone.hashCode());
- }
-
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/helper/URITest.java b/src/test/java/org/apache/sling/resourceresolver/impl/helper/URITest.java
deleted file mode 100644
index e94e358..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/helper/URITest.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * $HeadURL$
- * $Revision$
- * $Date$
- *
- * ====================================================================
- *
- * 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.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-/*
- * This class was taken from the ASF repo at http://svn.apache.org/viewvc/httpcomponents/oac.hc3x/tags/HTTPCLIENT_3_1/src/test/org/apache/commons/httpclient/TestURI.java?revision=567248&view=co
- * to provide coverage for the URI class from the same source that is embedded in this bundle.
- *
- * It has minor modifications to eliminate dependencies on other parts of the HttpClient 3.1 package.
- */
-package org.apache.sling.resourceresolver.impl.helper;
-
-
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Simple tests for the URI class.
- *
- * @author Michael Becke
- */
-public class URITest extends TestCase {
-
- /**
- * Constructor for TestURI.
- * @param testName
- */
- public URITest(String testName) {
- super(testName);
- }
-
- public static Test suite() {
- return new TestSuite(URITest.class);
- }
-
- public void testIPv4Address() throws URIException {
-
- URI base = new URI("http://10.0.1.10:8830", false);
-
- URI uri = base;
- assertTrue("Should be an IPv4 address", uri.isIPv4address());
-
- uri = new URI(base, "/04-1.html", false);
- assertTrue("Should be an IPv4 address", uri.isIPv4address());
-
- uri = new URI("/04-1.html", false);
- assertFalse("Should NOT be an IPv4 address", uri.isIPv4address());
-
- uri = new URI(base, "http://10.0.1.10:8830/04-1.html", false);
- assertTrue("Should be an IPv4 address", uri.isIPv4address());
-
- uri = new URI("http://10.0.1.10:8830/04-1.html", false);
- assertTrue("Should be an IPv4 address", uri.isIPv4address());
-
- uri = new URI(base, "http://host.org/04-1.html", false);
- assertFalse("Should NOT be an IPv4 address", uri.isIPv4address());
-
- uri = new URI("http://host.org/04-1.html", false);
- assertFalse("Should NOT be an IPv4 address", uri.isIPv4address());
-
- }
-
- public void testUrl() throws URIException {
- URI url = new URI("http://jakarta.apache.org", false);
- assertEquals(-1, url.getPort()); // URI itself has no knowledge of default ports.
- assertEquals("http", url.getScheme());
-
- url = new URI("https://jakarta.apache.org", false);
- assertEquals(-1, url.getPort()); // URI itself has no knowledge of default ports.
- assertEquals("https", url.getScheme());
- }
-
- /**
- * Tests the URI(URI, String) constructor. This tests URIs ability to
- * resolve relative URIs.
- */
- public void testRelativeURIConstructor() {
-
- URI baseURI = null;
-
- try {
- baseURI = new URI("http://a/b/c/d;p?q", false);
- } catch ( URIException e ) {
- fail( "unable to create base URI: " + e );
- }
-
- // the following is an array of arrays in the following order
- // relative URI, scheme, host(authority), path, query, fragment, abs. URI
- //
- // these examples were taken from rfc 2396
- String[][] testRelativeURIs = {
- { "g:h", "g", null, "h", null, null, "g:h" },
- { "g", "http", "a", "/b/c/g", null, null, "http://a/b/c/g" },
- { "./g", "http", "a", "/b/c/g", null, null, "http://a/b/c/g" },
- { "g/", "http", "a", "/b/c/g/", null, null, "http://a/b/c/g/" },
- { "/g", "http", "a", "/g", null, null, "http://a/g" },
- { "//g", "http", "g", null, null, null, "http://g" },
- { "?y", "http", "a", "/b/c/d;p", "y", null, "http://a/b/c/d;p?y" },
- { "g?y", "http", "a", "/b/c/g", "y", null, "http://a/b/c/g?y" },
- { "#s", "http", "a", "/b/c/d;p", "q", "s", "http://a/b/c/d;p?q#s" },
- { "#", "http", "a", "/b/c/d;p", "q", "", "http://a/b/c/d;p?q#" },
- { "", "http", "a", "/b/c/d;p", "q", null, "http://a/b/c/d;p?q" },
- { "g#s", "http", "a", "/b/c/g", null, "s", "http://a/b/c/g#s" },
- { "g?y#s","http", "a", "/b/c/g", "y", "s", "http://a/b/c/g?y#s" },
- { ";x", "http", "a", "/b/c/;x", null, null, "http://a/b/c/;x" },
- { "g;x", "http", "a", "/b/c/g;x", null, null, "http://a/b/c/g;x" },
- { "g;x?y#s", "http", "a", "/b/c/g;x", "y", "s", "http://a/b/c/g;x?y#s" },
- { ".", "http", "a", "/b/c/", null, null, "http://a/b/c/" },
- { "./", "http", "a", "/b/c/", null, null, "http://a/b/c/" },
- { "..", "http", "a", "/b/", null, null, "http://a/b/" },
- { "../", "http", "a", "/b/", null, null, "http://a/b/" },
- { "../g", "http", "a", "/b/g", null, null, "http://a/b/g" },
- { "../..", "http", "a", "/", null, null, "http://a/" },
- { "../../", "http", "a", "/", null, null, "http://a/" },
- { "../../g", "http", "a", "/g", null, null, "http://a/g" },
- { "../../../g", "http", "a", "/g", null, null, "http://a/g" },
- { "../../../../g", "http", "a", "/g", null, null, "http://a/g" },
- { "/./g", "http", "a", "/g", null, null, "http://a/g" },
- { "/../g", "http", "a", "/g", null, null, "http://a/g" },
- { "g.", "http", "a", "/b/c/g.", null, null, "http://a/b/c/g." },
- { ".g", "http", "a", "/b/c/.g", null, null, "http://a/b/c/.g" },
- { "g..", "http", "a", "/b/c/g..", null, null, "http://a/b/c/g.." },
- { "..g", "http", "a", "/b/c/..g", null, null, "http://a/b/c/..g" },
- { "./../g", "http", "a", "/b/g", null, null, "http://a/b/g" },
- { "./g/.", "http", "a", "/b/c/g/", null, null, "http://a/b/c/g/" },
- { "g/./h", "http", "a", "/b/c/g/h", null, null, "http://a/b/c/g/h" },
- { "g/../h", "http", "a", "/b/c/h", null, null, "http://a/b/c/h" },
- { "g;x=1/./y", "http", "a", "/b/c/g;x=1/y", null, null, "http://a/b/c/g;x=1/y" },
- { "g;x=1/../y", "http", "a", "/b/c/y", null, null, "http://a/b/c/y" },
- { "g?y/./x", "http", "a", "/b/c/g", "y/./x", null, "http://a/b/c/g?y/./x" },
- { "g?y/../x", "http", "a", "/b/c/g", "y/../x", null, "http://a/b/c/g?y/../x" },
- { "g#s/./x", "http", "a", "/b/c/g", null, "s/./x", "http://a/b/c/g#s/./x" },
- { "g#s/../x", "http", "a", "/b/c/g", null, "s/../x", "http://a/b/c/g#s/../x" },
- { ":g", "http", "a", "/b/c/:g", null, null, "http://a/b/c/:g" }, // see issue #35148
- { "//a/b/c", "http", "a", "/b/c", null, null, "http://a/b/c" } // see HTTPCLIENT-580
- };
- for (int i = 0; i < testRelativeURIs.length; i++) {
- URI testURI = null;
-
- try {
- testURI = new URI( baseURI, testRelativeURIs[i][0], false );
- } catch ( URIException e ) {
- e.printStackTrace();
- fail(
- "unable to create URI with relative value("
- + testRelativeURIs[i][0] + "): " + e
- );
- }
-
- try {
- assertEquals("array index "+i, testRelativeURIs[i][1], testURI.getScheme());
- assertEquals("array index "+i, testRelativeURIs[i][2], testURI.getAuthority());
- assertEquals("array index "+i, testRelativeURIs[i][3], testURI.getPath());
- assertEquals("array index "+i, testRelativeURIs[i][4], testURI.getQuery());
- assertEquals("array index "+i, testRelativeURIs[i][5], testURI.getFragment());
- assertEquals("array index "+i, testRelativeURIs[i][6], testURI.getURIReference());
- } catch ( URIException e ) {
- fail( "error getting URI property: " + e );
- }
- }
-
- }
-
- public void testTestURIAuthorityString() throws Exception {
- URI url = new URI("ftp", "user:password", "localhost", -1, "/");
- assertEquals("ftp://user:password@localhost/", url.toString());
- assertEquals("user:password@localhost", url.getAuthority());
- }
-
-
-
-
- public void testVariousCharacters() throws Exception {
- verifyInvalidURI("http://authority:123/path/path?query&name=val ue");
- verifyInvalidURI("http://authority:123/path/path?query&na me=value");
- verifyInvalidURI("http://authority:123/path/path?qu ery&name=value");
- verifyInvalidURI("http://authority:123/path/pa th?query&name=value");
- verifyInvalidURI("http://authority:123/pa th/path?query&name=value");
- verifyInvalidURI("http://authority:12 3/path/path?query&name=value");
- verifyInvalidURI("http://autho rity:123/path/path?query&name=value");
- verifyInvalidURI("htt p://authority:123/path/path?query&name=value");
- }
-
- private void verifyInvalidURI(String uri) {
- try {
- new URI(uri, true);
- fail("should have thrown URIException");
- } catch(URIException e) {
- /* expected */
- }
- }
-
- /**
- * Verify proper handling of relative URIs which have a scheme.
- * See bug http://issues.apache.org/jira/browse/HTTPCLIENT-587
- *
- * @throws Exception
- */
- public void testRelativeWithScheme() throws Exception {
- URI base = new URI("http://www.example.com/some/path", true);
- URI rel1 = new URI("http:", true);
- URI rel2 = new URI("http:foo", true);
- URI rel3 = new URI("http:../../bar", true);
- URI derel1 = new URI(base, rel1);
- assertEquals("http://www.example.com/some/path",derel1.toString());
- URI derel2 = new URI(base, rel2);
- assertEquals("http://www.example.com/some/foo",derel2.toString());
- URI derel3 = new URI(base,rel3);
- assertEquals("http://www.example.com/bar",derel3.toString());
- }
-
- /**
- * Verify proper handling of relative URIs with embedded double-slashes,
- * like "foo//bar//baz".
- * See bug http://issues.apache.org/jira/browse/HTTPCLIENT-588
- *
- * @throws Exception
- */
- public void testRelativeWithDoubleSlash() throws Exception {
- URI rel = new URI("foo//bar//baz",true);
- assertEquals("foo//bar//baz",rel.toString());
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/BloomFilterUtilsTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/BloomFilterUtilsTest.java
deleted file mode 100644
index 69bf67a..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/BloomFilterUtilsTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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.resourceresolver.impl.mapping;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import java.math.BigInteger;
-import java.util.HashSet;
-import java.util.Random;
-import org.junit.Test;
-
-/**
- * Test the bloom filter utility class.
- */
-public class BloomFilterUtilsTest {
-
- /**
- * Program to calculate the best shift and multiply constants.
- */
- public static void main(String... args) {
- Random random = new Random(1);
- HashSet<String> inSet = new HashSet<String>();
- while (inSet.size() < 100) {
- inSet.add(randomString(random));
- }
- Object[] in = inSet.toArray();
- HashSet<String> notSet = new HashSet<String>();
- while (notSet.size() < 10000) {
- String k = randomString(random);
- if (!inSet.contains(k)) {
- notSet.add(k);
- }
- }
- Object[] not = notSet.toArray();
- int best = Integer.MAX_VALUE;
- for (int mul = 1; mul < 100000; mul += 2) {
- if (!BigInteger.valueOf(mul).isProbablePrime(10)) {
- continue;
- }
- for (int shift = 0; shift < 32; shift++) {
- byte[] bloom = BloomFilterUtils.createFilter(100, 64);
- for (Object k : in) {
- int h1 = hash(k.hashCode(), mul, shift), h2 = hash(h1, mul, shift);
- add(bloom, h1, h2);
- }
- int falsePositives = 0;
- for (Object k : not) {
- int h1 = hash(k.hashCode(), mul, shift), h2 = hash(h1, mul, shift);
- if (probablyContains(bloom, h1, h2)) {
- falsePositives++;
- // short false positives are bad
- if (k.toString().length() < 4) {
- falsePositives += 5;
- }
- if (falsePositives > best) {
- break;
- }
- }
- }
- if (falsePositives < best) {
- best = falsePositives;
- System.out.println("mul: " + mul + " shift: "
- + shift + " falsePositives: " + best);
- }
- }
- }
- }
-
- private static String randomString(Random r) {
- if (r.nextInt(5) == 0) {
- return randomName(r);
- }
- int length = 1 + Math.abs((int) r.nextGaussian() * 5);
- if (r.nextBoolean()) {
- length += r.nextInt(10);
- }
- char[] chars = new char[length];
- for (int i = 0; i < length; i++) {
- chars[i] = randomChar(r);
- }
- return new String(chars);
- }
-
- private static char randomChar(Random r) {
- switch (r.nextInt(101) / 100) {
- case 0:
- case 1:
- // 20% ascii
- return (char) (32 + r.nextInt(127 - 32));
- case 2:
- case 3:
- case 4:
- case 5:
- // 40% a-z
- return (char) ('a' + r.nextInt('z' - 'a'));
- case 6:
- // 10% A-Z
- return (char) ('A' + r.nextInt('Z' - 'A'));
- case 7:
- case 8:
- // 20% 0-9
- return (char) ('0' + r.nextInt('9' - '0'));
- case 9:
- // 10% aeiou
- return "aeiou".charAt(r.nextInt("aeiou".length()));
- }
- // 1% unicode
- return (char) r.nextInt(65535);
- }
-
- private static String randomName(Random r) {
- int i = r.nextInt(1000);
- // like TPC-C lastName, but lowercase
- String[] n = {
- "bar", "ought", "able", "pri", "pres", "ese", "anti",
- "cally", "ation", "eing" };
- StringBuilder buff = new StringBuilder();
- buff.append(n[i / 100]);
- buff.append(n[(i / 10) % 10]);
- buff.append(n[i % 10]);
- return buff.toString();
- }
-
-
- private static int hash(int oldHash, int mul, int shift) {
- return oldHash ^ ((oldHash * mul) >> shift);
- }
-
- private static void add(byte[] bloom, int h1, int h2) {
- int len = bloom.length;
- if (len > 0) {
- bloom[(h1 >>> 3) % len] |= 1 << (h1 & 7);
- bloom[(h2 >>> 3) % len] |= 1 << (h2 & 7);
- }
- }
-
- private static boolean probablyContains(byte[] bloom, int h1, int h2) {
- int len = bloom.length;
- if (len == 0) {
- return true;
- }
- int x = bloom[(h1 >>> 3) % len] & (1 << (h1 & 7));
- if (x != 0) {
- x = bloom[(h2 >>> 3) % len] & (1 << (h2 & 7));
- }
- return x != 0;
- }
-
- @Test
- public void size() {
- byte[] bloom = BloomFilterUtils.createFilter(100, 64);
- assertEquals(64, bloom.length);
- bloom = BloomFilterUtils.createFilter(10, 64);
- assertEquals(11, bloom.length);
- bloom = BloomFilterUtils.createFilter(0, 64);
- assertEquals(0, bloom.length);
- bloom = BloomFilterUtils.createFilter(1, 64);
- assertEquals(1, bloom.length);
- }
-
- @Test
- public void probability() {
- byte[] bloom = BloomFilterUtils.createFilter(20, 64);
- System.out.println(bloom.length);
- Random random = new Random(1);
- random.setSeed(1);
- for (int i = 0; i < 20; i++) {
- BloomFilterUtils.add(bloom, random.nextInt());
- }
- random.setSeed(1);
- for (int i = 0; i < 20; i++) {
- assertTrue(BloomFilterUtils.probablyContains(bloom, random.nextInt()));
- }
- int falsePositives = 0;
- for (int i = 20; i < 100000; i++) {
- if (BloomFilterUtils.probablyContains(bloom, random.nextInt())) {
- falsePositives++;
- }
- }
- assertEquals(4594, falsePositives);
- }
- @Test
- public void negativeHashCode() {
- BloomFilterUtils.add(new byte[0], new Object() {
- @Override
- public int hashCode() {
- return -1;
- }
- });
- }
-
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
deleted file mode 100644
index 54af3be..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
+++ /dev/null
@@ -1,1885 +0,0 @@
-/*
- * 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.resourceresolver.impl.mapping;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceUtil;
-import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.api.wrappers.ValueMapDecorator;
-import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider.VanityPathConfig;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.event.EventAdmin;
-
-public class MapEntriesTest {
-
- private MapEntries mapEntries;
-
- File vanityBloomFilterFile;
-
- @Mock
- private MapConfigurationProvider resourceResolverFactory;
-
- @Mock
- private BundleContext bundleContext;
-
- @Mock
- private ResourceResolver resourceResolver;
-
- @Mock
- private EventAdmin eventAdmin;
-
- @SuppressWarnings("deprecation")
- @Before
- public void setup() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- final List<VanityPathConfig> configs = new ArrayList<MapConfigurationProvider.VanityPathConfig>();
- configs.add(new VanityPathConfig("/libs/", false));
- configs.add(new VanityPathConfig("/libs/denied", true));
- configs.add(new VanityPathConfig("/foo/", false));
- configs.add(new VanityPathConfig("/baa/", false));
- configs.add(new VanityPathConfig("/justVanityPath", false));
- configs.add(new VanityPathConfig("/justVanityPath2", false));
- configs.add(new VanityPathConfig("/badVanityPath", false));
- configs.add(new VanityPathConfig("/redirectingVanityPath", false));
- configs.add(new VanityPathConfig("/redirectingVanityPath301", false));
- configs.add(new VanityPathConfig("/vanityPathOnJcrContent", false));
-
- Collections.sort(configs);
- vanityBloomFilterFile = new File("src/main/resourcesvanityBloomFilter.txt");
- when(bundleContext.getDataFile("vanityBloomFilter.txt")).thenReturn(vanityBloomFilterFile);
- when(resourceResolverFactory.getAdministrativeResourceResolver(null)).thenReturn(resourceResolver);
- when(resourceResolverFactory.isVanityPathEnabled()).thenReturn(true);
- when(resourceResolverFactory.getVanityPathConfig()).thenReturn(configs);
- when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(true);
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenReturn(
- Collections.<Resource> emptySet().iterator());
-
- mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin);
- Field field0 = MapEntries.class.getDeclaredField("mapRoot");
- field0.setAccessible(true);
- field0.set(mapEntries, MapEntries.DEFAULT_MAP_ROOT);
-
- Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries");
- field1.setAccessible(true);
- field1.set(mapEntries, -1);
-
- Field field2 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntriesStartup");
- field2.setAccessible(true);
- field2.set(mapEntries, true);
-
- }
-
- @After
- public void tearDown() throws Exception {
- vanityBloomFilterFile.delete();
- }
-
- @Test
- public void test_simple_alias_support() {
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
-
- final Resource result = mock(Resource.class);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent/child");
- when(result.getName()).thenReturn("child");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:alias")) {
- return Collections.singleton(result).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- mapEntries.doInit();
-
- Map<String, String> aliasMap = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMap);
- assertTrue(aliasMap.containsKey("alias"));
- assertEquals("child", aliasMap.get("alias"));
- }
-
- @Test
- public void test_that_duplicate_alias_doesnt_replace_first_alias() {
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
-
- final Resource result = mock(Resource.class);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent/child");
- when(result.getName()).thenReturn("child");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- final Resource secondResult = mock(Resource.class);
- when(secondResult.getParent()).thenReturn(parent);
- when(secondResult.getPath()).thenReturn("/parent/child2");
- when(secondResult.getName()).thenReturn("child2");
- when(secondResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:alias")) {
- return Arrays.asList(result, secondResult).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- mapEntries.doInit();
-
- Map<String, String> aliasMap = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMap);
- assertTrue(aliasMap.containsKey("alias"));
- assertEquals("child", aliasMap.get("alias"));
- }
-
- @Test
- public void test_vanity_path_registration() throws Exception {
- // specifically making this a weird value because we want to verify that
- // the configuration value is being used
- int DEFAULT_VANITY_STATUS = 333333;
-
- when(resourceResolverFactory.getDefaultVanityPathRedirectStatus()).thenReturn(DEFAULT_VANITY_STATUS);
-
- final List<Resource> resources = new ArrayList<Resource>();
-
- Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
- resources.add(justVanityPath);
-
- Resource badVanityPath = mock(Resource.class, "badVanityPath");
- when(badVanityPath.getPath()).thenReturn("/badVanityPath");
- when(badVanityPath.getName()).thenReturn("badVanityPath");
- when(badVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/content/mypage/en-us-{132"));
- resources.add(badVanityPath);
-
-
- Resource redirectingVanityPath = mock(Resource.class, "redirectingVanityPath");
- when(redirectingVanityPath.getPath()).thenReturn("/redirectingVanityPath");
- when(redirectingVanityPath.getName()).thenReturn("redirectingVanityPath");
- when(redirectingVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/redirectingVanityPath", "sling:redirect", true));
- resources.add(redirectingVanityPath);
-
- Resource redirectingVanityPath301 = mock(Resource.class, "redirectingVanityPath301");
- when(redirectingVanityPath301.getPath()).thenReturn("/redirectingVanityPath301");
- when(redirectingVanityPath301.getName()).thenReturn("redirectingVanityPath301");
- when(redirectingVanityPath301.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/redirectingVanityPath301", "sling:redirect", true, "sling:redirectStatus", 301));
- resources.add(redirectingVanityPath301);
-
- Resource vanityPathOnJcrContentParent = mock(Resource.class, "vanityPathOnJcrContentParent");
- when(vanityPathOnJcrContentParent.getPath()).thenReturn("/vanityPathOnJcrContent");
- when(vanityPathOnJcrContentParent.getName()).thenReturn("vanityPathOnJcrContent");
-
- Resource vanityPathOnJcrContent = mock(Resource.class, "vanityPathOnJcrContent");
- when(vanityPathOnJcrContent.getPath()).thenReturn("/vanityPathOnJcrContent/jcr:content");
- when(vanityPathOnJcrContent.getName()).thenReturn("jcr:content");
- when(vanityPathOnJcrContent.getParent()).thenReturn(vanityPathOnJcrContentParent);
- when(vanityPathOnJcrContent.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContent"));
- resources.add(vanityPathOnJcrContent);
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return resources.iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- mapEntries.doInit();
- mapEntries.initializeVanityPaths();
-
- List<MapEntry> entries = mapEntries.getResolveMaps();
- assertEquals(8, entries.size());
- for (MapEntry entry : entries) {
- if (entry.getPattern().contains("/target/redirectingVanityPath301")) {
- assertEquals(301, entry.getStatus());
- assertFalse(entry.isInternal());
- } else if (entry.getPattern().contains("/target/redirectingVanityPath")) {
- assertEquals(DEFAULT_VANITY_STATUS, entry.getStatus());
- assertFalse(entry.isInternal());
- } else if (entry.getPattern().contains("/target/justVanityPath")) {
- assertTrue(entry.isInternal());
- } else if (entry.getPattern().contains("/target/vanityPathOnJcrContent")) {
- for (String redirect : entry.getRedirect()) {
- assertFalse(redirect.contains("jcr:content"));
- }
- }
- }
-
- Field field = MapEntries.class.getDeclaredField("vanityTargets");
- field.setAccessible(true);
- @SuppressWarnings("unchecked")
- Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries);
- assertEquals(4, vanityTargets.size());
-
- }
-
- private ValueMap buildValueMap(Object... string) {
- final Map<String, Object> data = new HashMap<String, Object>();
- for (int i = 0; i < string.length; i = i + 2) {
- data.put((String) string[i], string[i+1]);
- }
- return new ValueMapDecorator(data);
- }
-
- private Resource getVanityPathResource(final String path) {
- Resource rsrc = mock(Resource.class);
- when(rsrc.getPath()).thenReturn(path);
- when(rsrc.getName()).thenReturn(ResourceUtil.getName(path));
- when(rsrc.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/vanity" + path));
- return rsrc;
- }
-
- @Test
- public void test_vanity_path_registration_include_exclude() throws IOException {
- final String[] validPaths = {"/libs/somewhere", "/libs/a/b", "/foo/a", "/baa/a"};
- final String[] invalidPaths = {"/libs/denied/a", "/libs/denied/b/c", "/nowhere"};
-
- final List<Resource> resources = new ArrayList<Resource>();
- for(final String val : validPaths) {
- resources.add(getVanityPathResource(val));
- }
- for(final String val : invalidPaths) {
- resources.add(getVanityPathResource(val));
- }
-
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return resources.iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- mapEntries.doInit();
- mapEntries.initializeVanityPaths();
-
- List<MapEntry> entries = mapEntries.getResolveMaps();
- // each valid resource results in 2 entries
- assertEquals(validPaths.length * 2, entries.size());
-
- final Set<String> resultSet = new HashSet<String>();
- for(final String p : validPaths) {
- resultSet.add(p + "$1");
- resultSet.add(p + ".html");
- }
- for (final MapEntry entry : entries) {
- assertTrue(resultSet.remove(entry.getRedirect()[0]));
- }
- }
-
- @Test
- public void test_getActualContentPath() throws Exception {
-
- Method method = MapEntries.class.getDeclaredMethod("getActualContentPath", String.class);
- method.setAccessible(true);
-
- String actualContent = (String) method.invoke(mapEntries, "/content");
- assertEquals("/content", actualContent);
-
- actualContent = (String) method.invoke(mapEntries, "/content/jcr:content");
- assertEquals("/content", actualContent);
- }
-
- @Test
- public void test_getMapEntryRedirect() throws Exception {
-
- Method method = MapEntries.class.getDeclaredMethod("getMapEntryRedirect", MapEntry.class);
- method.setAccessible(true);
-
- MapEntry mapEntry = new MapEntry("/content", -1, false, 0, "/content");
- String actualContent = (String) method.invoke(mapEntries, mapEntry);
- assertEquals("/content", actualContent);
-
- mapEntry = new MapEntry("/content", -1, false, 0, "/content$1");
- actualContent = (String) method.invoke(mapEntries, mapEntry);
- assertEquals("/content", actualContent);
-
- mapEntry = new MapEntry("/content", -1, false, 0, "/content.html");
- actualContent = (String) method.invoke(mapEntries, mapEntry);
- assertEquals("/content", actualContent);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doAddVanity() throws Exception {
- List<MapEntry> entries = mapEntries.getResolveMaps();
- assertEquals(0, entries.size());
- Field field = MapEntries.class.getDeclaredField("vanityTargets");
- field.setAccessible(true);
- Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries);
- assertEquals(0, vanityTargets.size());
-
- Method method = MapEntries.class.getDeclaredMethod("doAddVanity", String.class);
- method.setAccessible(true);
-
- Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
- method.invoke(mapEntries, "/justVanityPath");
-
- entries = mapEntries.getResolveMaps();
- assertEquals(2, entries.size());
-
- Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(2, counter.longValue());
-
- //bad vanity
- Resource badVanityPath = mock(Resource.class, "badVanityPath");
- when(resourceResolver.getResource("/badVanityPath")).thenReturn(badVanityPath);
- when(badVanityPath.getPath()).thenReturn("/badVanityPath");
- when(badVanityPath.getName()).thenReturn("badVanityPath");
- when(badVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/content/mypage/en-us-{132"));
-
- method.invoke(mapEntries, "/badVanityPath");
-
-
- assertEquals(2, entries.size());
-
- vanityTargets = (Map<String, List<String>>) field.get(mapEntries);
- assertEquals(1, vanityTargets.size());
-
- //vanity under jcr:content
- Resource vanityPathOnJcrContentParent = mock(Resource.class, "vanityPathOnJcrContentParent");
- when(vanityPathOnJcrContentParent.getPath()).thenReturn("/vanityPathOnJcrContent");
- when(vanityPathOnJcrContentParent.getName()).thenReturn("vanityPathOnJcrContent");
-
- Resource vanityPathOnJcrContent = mock(Resource.class, "vanityPathOnJcrContent");
- when(resourceResolver.getResource("/vanityPathOnJcrContent/jcr:content")).thenReturn(vanityPathOnJcrContent);
- when(vanityPathOnJcrContent.getPath()).thenReturn("/vanityPathOnJcrContent/jcr:content");
- when(vanityPathOnJcrContent.getName()).thenReturn("jcr:content");
- when(vanityPathOnJcrContent.getParent()).thenReturn(vanityPathOnJcrContentParent);
- when(vanityPathOnJcrContent.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContent"));
-
- method.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content");
-
- entries = mapEntries.getResolveMaps();
- assertEquals(4, entries.size());
-
- counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(4, counter.longValue());
-
- vanityTargets = (Map<String, List<String>>) field.get(mapEntries);
- assertEquals(2, vanityTargets.size());
-
- assertNull(vanityTargets.get("/vanityPathOnJcrContent/jcr:content"));
- assertNotNull(vanityTargets.get("/vanityPathOnJcrContent"));
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doAddVanity_1() throws Exception {
- Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries");
- field1.setAccessible(true);
- field1.set(mapEntries, 10);
-
- List<MapEntry> entries = mapEntries.getResolveMaps();
- assertEquals(0, entries.size());
- Field field = MapEntries.class.getDeclaredField("vanityTargets");
- field.setAccessible(true);
- Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries);
- assertEquals(0, vanityTargets.size());
-
- Method method = MapEntries.class.getDeclaredMethod("doAddVanity", String.class);
- method.setAccessible(true);
-
- Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
- method.invoke(mapEntries, "/justVanityPath");
-
- entries = mapEntries.getResolveMaps();
- assertEquals(2, entries.size());
-
- Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(2, counter.longValue());
-
- //bad vanity
- Resource badVanityPath = mock(Resource.class, "badVanityPath");
- when(resourceResolver.getResource("/badVanityPath")).thenReturn(badVanityPath);
- when(badVanityPath.getPath()).thenReturn("/badVanityPath");
- when(badVanityPath.getName()).thenReturn("badVanityPath");
- when(badVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/content/mypage/en-us-{132"));
-
- method.invoke(mapEntries, "/badVanityPath");
-
-
- assertEquals(2, entries.size());
-
- vanityTargets = (Map<String, List<String>>) field.get(mapEntries);
- assertEquals(1, vanityTargets.size());
-
- //vanity under jcr:content
- Resource vanityPathOnJcrContentParent = mock(Resource.class, "vanityPathOnJcrContentParent");
- when(vanityPathOnJcrContentParent.getPath()).thenReturn("/vanityPathOnJcrContent");
- when(vanityPathOnJcrContentParent.getName()).thenReturn("vanityPathOnJcrContent");
-
- Resource vanityPathOnJcrContent = mock(Resource.class, "vanityPathOnJcrContent");
- when(resourceResolver.getResource("/vanityPathOnJcrContent/jcr:content")).thenReturn(vanityPathOnJcrContent);
- when(vanityPathOnJcrContent.getPath()).thenReturn("/vanityPathOnJcrContent/jcr:content");
- when(vanityPathOnJcrContent.getName()).thenReturn("jcr:content");
- when(vanityPathOnJcrContent.getParent()).thenReturn(vanityPathOnJcrContentParent);
- when(vanityPathOnJcrContent.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContent"));
-
- method.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content");
-
- entries = mapEntries.getResolveMaps();
- assertEquals(4, entries.size());
-
- counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(4, counter.longValue());
-
- vanityTargets = (Map<String, List<String>>) field.get(mapEntries);
- assertEquals(2, vanityTargets.size());
-
- assertNull(vanityTargets.get("/vanityPathOnJcrContent/jcr:content"));
- assertNotNull(vanityTargets.get("/vanityPathOnJcrContent"));
- }
-
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doUpdateVanity() throws Exception {
- Field field0 = MapEntries.class.getDeclaredField("resolveMapsMap");
- field0.setAccessible(true);
- Map<String, List<MapEntry>> resolveMapsMap = (Map<String, List<MapEntry>>) field0.get(mapEntries);
- assertEquals(1, resolveMapsMap.size());
-
- Field field = MapEntries.class.getDeclaredField("vanityTargets");
- field.setAccessible(true);
- Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries);
- assertEquals(0, vanityTargets.size());
-
- Method method = MapEntries.class.getDeclaredMethod("doAddVanity", String.class);
- method.setAccessible(true);
-
- Method method1 = MapEntries.class.getDeclaredMethod("doUpdateVanity", String.class);
- method1.setAccessible(true);
-
- Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
- method.invoke(mapEntries, "/justVanityPath");
-
- assertEquals(2, resolveMapsMap.size());
- assertEquals(1, vanityTargets.size());
- assertNotNull(resolveMapsMap.get("/target/justVanityPath"));
- assertNull(resolveMapsMap.get("/target/justVanityPathUpdated"));
- assertEquals(1, vanityTargets.get("/justVanityPath").size());
- assertEquals("/target/justVanityPath", vanityTargets.get("/justVanityPath").get(0));
-
- //update vanity path
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPathUpdated"));
- method1.invoke(mapEntries, "/justVanityPath");
-
- assertEquals(2, resolveMapsMap.size());
- assertEquals(1, vanityTargets.size());
- assertNull(resolveMapsMap.get("/target/justVanityPath"));
- assertNotNull(resolveMapsMap.get("/target/justVanityPathUpdated"));
- assertEquals(1, vanityTargets.get("/justVanityPath").size());
- assertEquals("/target/justVanityPathUpdated", vanityTargets.get("/justVanityPath").get(0));
-
- //vanity under jcr:content
- Resource vanityPathOnJcrContentParent = mock(Resource.class, "vanityPathOnJcrContentParent");
- when(vanityPathOnJcrContentParent.getPath()).thenReturn("/vanityPathOnJcrContent");
- when(vanityPathOnJcrContentParent.getName()).thenReturn("vanityPathOnJcrContent");
-
- Resource vanityPathOnJcrContent = mock(Resource.class, "vanityPathOnJcrContent");
- when(resourceResolver.getResource("/vanityPathOnJcrContent/jcr:content")).thenReturn(vanityPathOnJcrContent);
- when(vanityPathOnJcrContent.getPath()).thenReturn("/vanityPathOnJcrContent/jcr:content");
- when(vanityPathOnJcrContent.getName()).thenReturn("jcr:content");
- when(vanityPathOnJcrContent.getParent()).thenReturn(vanityPathOnJcrContentParent);
- when(vanityPathOnJcrContent.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContent"));
-
- method.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content");
-
- assertEquals(3, resolveMapsMap.size());
- assertEquals(2, vanityTargets.size());
- assertNotNull(resolveMapsMap.get("/target/vanityPathOnJcrContent"));
- assertNull(resolveMapsMap.get("/target/vanityPathOnJcrContentUpdated"));
- assertEquals(1, vanityTargets.get("/vanityPathOnJcrContent").size());
- assertEquals("/target/vanityPathOnJcrContent", vanityTargets.get("/vanityPathOnJcrContent").get(0));
-
- //update vanity path
- when(vanityPathOnJcrContent.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContentUpdated"));
- method1.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content");
-
- assertEquals(3, resolveMapsMap.size());
- assertEquals(2, vanityTargets.size());
- assertNull(resolveMapsMap.get("/target/vanityPathOnJcrContent"));
- assertNotNull(resolveMapsMap.get("/target/vanityPathOnJcrContentUpdated"));
- assertEquals(1, vanityTargets.get("/vanityPathOnJcrContent").size());
- assertEquals("/target/vanityPathOnJcrContentUpdated", vanityTargets.get("/vanityPathOnJcrContent").get(0));
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doRemoveVanity() throws Exception {
- Field field0 = MapEntries.class.getDeclaredField("resolveMapsMap");
- field0.setAccessible(true);
- Map<String, List<MapEntry>> resolveMapsMap = (Map<String, List<MapEntry>>) field0.get(mapEntries);
- assertEquals(1, resolveMapsMap.size());
-
- Field field = MapEntries.class.getDeclaredField("vanityTargets");
- field.setAccessible(true);
- Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries);
- assertEquals(0, vanityTargets.size());
-
- Method method = MapEntries.class.getDeclaredMethod("doAddVanity", String.class);
- method.setAccessible(true);
-
- Method method1 = MapEntries.class.getDeclaredMethod("doRemoveVanity", String.class);
- method1.setAccessible(true);
-
- Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
- method.invoke(mapEntries, "/justVanityPath");
-
- Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(2, counter.longValue());
- assertEquals(2, resolveMapsMap.size());
- assertEquals(1, vanityTargets.size());
- assertNotNull(resolveMapsMap.get("/target/justVanityPath"));
- assertEquals(1, vanityTargets.get("/justVanityPath").size());
- assertEquals("/target/justVanityPath", vanityTargets.get("/justVanityPath").get(0));
-
- //remove vanity path
- method1.invoke(mapEntries, "/justVanityPath");
-
- counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(0, counter.longValue());
-
- assertEquals(1, resolveMapsMap.size());
- assertEquals(0, vanityTargets.size());
- assertNull(resolveMapsMap.get("/target/justVanityPath"));
-
- //vanity under jcr:content
- Resource vanityPathOnJcrContentParent = mock(Resource.class, "vanityPathOnJcrContentParent");
- when(vanityPathOnJcrContentParent.getPath()).thenReturn("/vanityPathOnJcrContent");
- when(vanityPathOnJcrContentParent.getName()).thenReturn("vanityPathOnJcrContent");
-
- Resource vanityPathOnJcrContent = mock(Resource.class, "vanityPathOnJcrContent");
- when(resourceResolver.getResource("/vanityPathOnJcrContent/jcr:content")).thenReturn(vanityPathOnJcrContent);
- when(vanityPathOnJcrContent.getPath()).thenReturn("/vanityPathOnJcrContent/jcr:content");
- when(vanityPathOnJcrContent.getName()).thenReturn("jcr:content");
- when(vanityPathOnJcrContent.getParent()).thenReturn(vanityPathOnJcrContentParent);
- when(vanityPathOnJcrContent.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContent"));
-
- method.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content");
-
- assertEquals(2, resolveMapsMap.size());
- assertEquals(1, vanityTargets.size());
- assertNotNull(resolveMapsMap.get("/target/vanityPathOnJcrContent"));
- assertEquals(1,vanityTargets.get("/vanityPathOnJcrContent").size());
- assertEquals("/target/vanityPathOnJcrContent", vanityTargets.get("/vanityPathOnJcrContent").get(0));
-
- //remove vanity path
- method1.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content");
-
- assertEquals(1, resolveMapsMap.size());
- assertEquals(0, vanityTargets.size());
- assertNull(resolveMapsMap.get("/target/vanityPathOnJcrContent"));
-
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doUpdateVanityOrder() throws Exception {
- Field field0 = MapEntries.class.getDeclaredField("resolveMapsMap");
- field0.setAccessible(true);
- Map<String, List<MapEntry>> resolveMapsMap = (Map<String, List<MapEntry>>) field0.get(mapEntries);
- assertEquals(1, resolveMapsMap.size());
-
- Field field = MapEntries.class.getDeclaredField("vanityTargets");
- field.setAccessible(true);
- Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries);
- assertEquals(0, vanityTargets.size());
-
- Method method = MapEntries.class.getDeclaredMethod("doAddVanity", String.class);
- method.setAccessible(true);
-
- Method method1 = MapEntries.class.getDeclaredMethod("doUpdateVanityOrder", String.class, boolean.class);
- method1.setAccessible(true);
-
- Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
- method.invoke(mapEntries, "/justVanityPath");
-
- Resource justVanityPath2 = mock(Resource.class, "justVanityPath2");
- when(resourceResolver.getResource("/justVanityPath2")).thenReturn(justVanityPath2);
- when(justVanityPath2.getPath()).thenReturn("/justVanityPath2");
- when(justVanityPath2.getName()).thenReturn("justVanityPath2");
- when(justVanityPath2.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath","sling:vanityOrder", 100));
-
- method.invoke(mapEntries, "/justVanityPath2");
-
- assertEquals(2, resolveMapsMap.size());
- assertEquals(2, vanityTargets.size());
- assertNotNull(resolveMapsMap.get("/target/justVanityPath"));
-
- Iterator <MapEntry> iterator = resolveMapsMap.get("/target/justVanityPath").iterator();
- assertEquals("/justVanityPath2$1", iterator.next().getRedirect()[0]);
- assertEquals("/justVanityPath$1", iterator.next().getRedirect()[0]);
- assertEquals("/justVanityPath2.html", iterator.next().getRedirect()[0]);
- assertEquals("/justVanityPath.html", iterator.next().getRedirect()[0]);
- assertFalse(iterator.hasNext());
-
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath","sling:vanityOrder", 1000));
- method1.invoke(mapEntries, "/justVanityPath",false);
-
- iterator = resolveMapsMap.get("/target/justVanityPath").iterator();
- assertEquals("/justVanityPath$1", iterator.next().getRedirect()[0]);
- assertEquals("/justVanityPath2$1", iterator.next().getRedirect()[0]);
- assertEquals("/justVanityPath.html", iterator.next().getRedirect()[0]);
- assertEquals("/justVanityPath2.html", iterator.next().getRedirect()[0]);
- assertFalse(iterator.hasNext());
-
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
- method1.invoke(mapEntries, "/justVanityPath",true);
-
- iterator = resolveMapsMap.get("/target/justVanityPath").iterator();
- assertEquals("/justVanityPath2$1", iterator.next().getRedirect()[0]);
- assertEquals("/justVanityPath$1", iterator.next().getRedirect()[0]);
- assertEquals("/justVanityPath2.html", iterator.next().getRedirect()[0]);
- assertEquals("/justVanityPath.html", iterator.next().getRedirect()[0]);
- assertFalse(iterator.hasNext());
- }
-
- //SLING-3727
- @Test
- public void test_doAddAliasAttributesWithDisableAliasOptimization() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doAddAttributes", String.class, String[].class, boolean.class);
- method.setAccessible(true);
-
- when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(false);
- mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin);
- Field field0 = MapEntries.class.getDeclaredField("mapRoot");
- field0.setAccessible(true);
- field0.set(mapEntries, MapEntries.DEFAULT_MAP_ROOT);
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent/child");
- when(result.getName()).thenReturn("child");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent/child",
- new String[] { "sling:alias" }, false);
-
- Map<String, String> aliasMap = mapEntries.getAliasMap("/parent");
- assertNull(aliasMap);
- }
-
- //SLING-3727
- @Test
- public void test_doUpdateAttributesWithDisableAliasOptimization() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doUpdateAttributes", String.class, String[].class, boolean.class);
- method.setAccessible(true);
-
- when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(false);
- mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin);
- Field field0 = MapEntries.class.getDeclaredField("mapRoot");
- field0.setAccessible(true);
- field0.set(mapEntries, MapEntries.DEFAULT_MAP_ROOT);
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent/child");
- when(result.getName()).thenReturn("child");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent/child",
- new String[] { "sling:alias" }, false);
-
- Map<String, String> aliasMap = mapEntries.getAliasMap("/parent");
- assertNull(aliasMap);
- }
-
- //SLING-3727
- @Test
- public void test_doRemoveAttributessWithDisableAliasOptimization() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doRemoveAttributes", String.class, String[].class, boolean.class, boolean.class);
- method.setAccessible(true);
-
- when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(false);
- mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin);
- Field field0 = MapEntries.class.getDeclaredField("mapRoot");
- field0.setAccessible(true);
- field0.set(mapEntries, MapEntries.DEFAULT_MAP_ROOT);
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent/child");
- when(result.getName()).thenReturn("child");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent/child",
- new String[] { "sling:alias" }, false, false);
-
- Map<String, String> aliasMap = mapEntries.getAliasMap("/parent");
- assertNull(aliasMap);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doAddAlias() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doAddAlias", String.class);
- method.setAccessible(true);
-
- Field field0 = MapEntries.class.getDeclaredField("aliasMap");
- field0.setAccessible(true);
-
- Map<String, Map<String, String>> aliasMap = ( Map<String, Map<String, String>>) field0.get(mapEntries);
- assertEquals(0, aliasMap.size());
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent/child");
- when(result.getName()).thenReturn("child");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent/child");
-
- Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("alias"));
- assertEquals("child", aliasMapEntry.get("alias"));
-
- assertEquals(1, aliasMap.size());
-
- //test_that_duplicate_alias_doesnt_replace_first_alias
- final Resource secondResult = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child2")).thenReturn(secondResult);
- when(secondResult.getParent()).thenReturn(parent);
- when(secondResult.getPath()).thenReturn("/parent/child2");
- when(secondResult.getName()).thenReturn("child2");
- when(secondResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent/child2");
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("alias"));
- assertEquals("child", aliasMapEntry.get("alias"));
-
- assertEquals(1, aliasMap.size());
-
- //testing jcr:content node
- final Resource jcrContentResult = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult);
- when(jcrContentResult.getParent()).thenReturn(result);
- when(jcrContentResult.getPath()).thenReturn("/parent/child/jcr:content");
- when(jcrContentResult.getName()).thenReturn("jcr:content");
- when(jcrContentResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "aliasJcrContent"));
-
- method.invoke(mapEntries, "/parent/child/jcr:content");
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(2, aliasMapEntry.size());
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
-
- assertEquals(1, aliasMap.size());
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doAddAlias2() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doAddAlias", String.class);
- method.setAccessible(true);
-
- Field field0 = MapEntries.class.getDeclaredField("aliasMap");
- field0.setAccessible(true);
-
- Map<String, Map<String, String>> aliasMap = ( Map<String, Map<String, String>>) field0.get(mapEntries);
- assertEquals(0, aliasMap.size());
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent");
- when(result.getName()).thenReturn("parent");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent");
-
- Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("alias"));
- assertEquals("parent", aliasMapEntry.get("alias"));
-
- assertEquals(1, aliasMap.size());
-
- //test_that_duplicate_alias_doesnt_replace_first_alias
- final Resource secondResult = mock(Resource.class);
- when(resourceResolver.getResource("/parent2")).thenReturn(secondResult);
- when(secondResult.getParent()).thenReturn(parent);
- when(secondResult.getPath()).thenReturn("/parent2");
- when(secondResult.getName()).thenReturn("parent2");
- when(secondResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent2");
-
- aliasMapEntry = mapEntries.getAliasMap("/");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("alias"));
- assertEquals("parent", aliasMapEntry.get("alias"));
-
- assertEquals(1, aliasMap.size());
-
- //testing jcr:content node
- final Resource jcrContentResult = mock(Resource.class);
- when(resourceResolver.getResource("/parent/jcr:content")).thenReturn(jcrContentResult);
- when(jcrContentResult.getParent()).thenReturn(result);
- when(jcrContentResult.getPath()).thenReturn("/parent/jcr:content");
- when(jcrContentResult.getName()).thenReturn("jcr:content");
- when(jcrContentResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "aliasJcrContent"));
-
- method.invoke(mapEntries, "/parent/jcr:content");
-
- aliasMapEntry = mapEntries.getAliasMap("/");
- assertNotNull(aliasMapEntry);
- assertEquals(2, aliasMapEntry.size());
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertEquals("parent", aliasMapEntry.get("aliasJcrContent"));
-
- assertEquals(1, aliasMap.size());
- }
-
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doUpdateAlias() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doAddAlias", String.class);
- method.setAccessible(true);
-
- Method method1 = MapEntries.class.getDeclaredMethod("doUpdateAttributes", String.class , String[].class, boolean.class);
- method1.setAccessible(true);
-
- Field field0 = MapEntries.class.getDeclaredField("aliasMap");
- field0.setAccessible(true);
-
- Map<String, Map<String, String>> aliasMap = ( Map<String, Map<String, String>>) field0.get(mapEntries);
- assertEquals(0, aliasMap.size());
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent/child");
- when(result.getName()).thenReturn("child");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent/child");
-
- Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("alias"));
- assertFalse(aliasMapEntry.containsKey("aliasUpdated"));
- assertEquals("child", aliasMapEntry.get("alias"));
-
- assertEquals(1, aliasMap.size());
-
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "aliasUpdated"));
-
- method1.invoke(mapEntries, "/parent/child", new String[] { "sling:alias" }, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertFalse(aliasMapEntry.containsKey("alias"));
- assertTrue(aliasMapEntry.containsKey("aliasUpdated"));
- assertEquals("child", aliasMapEntry.get("aliasUpdated"));
-
- assertEquals(1, aliasMap.size());
-
- //testing jcr:content node update
- final Resource jcrContentResult = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult);
- when(jcrContentResult.getParent()).thenReturn(result);
- when(jcrContentResult.getPath()).thenReturn("/parent/child/jcr:content");
- when(jcrContentResult.getName()).thenReturn("jcr:content");
- when(jcrContentResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "aliasJcrContent"));
- when(result.getChild("jcr:content")).thenReturn(jcrContentResult);
-
- method.invoke(mapEntries, "/parent/child/jcr:content");
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(2, aliasMapEntry.size());
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertFalse(aliasMapEntry.containsKey("aliasJcrContentUpdated"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
-
- assertEquals(1, aliasMap.size());
-
- when(jcrContentResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "aliasJcrContentUpdated"));
- method1.invoke(mapEntries, "/parent/child/jcr:content", new String[] { "sling:alias" }, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(2, aliasMapEntry.size());
- assertFalse(aliasMapEntry.containsKey("aliasJcrContent"));
- assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated"));
-
- assertEquals(1, aliasMap.size());
-
- //re-update alias
- method1.invoke(mapEntries, "/parent/child", new String[] { "sling:alias" }, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(2, aliasMapEntry.size());
- assertFalse(aliasMapEntry.containsKey("alias"));
- assertTrue(aliasMapEntry.containsKey("aliasUpdated"));
- assertEquals("child", aliasMapEntry.get("aliasUpdated"));
-
- //add another node with different alias and check that the update doesn't break anything (see also SLING-3728)
- final Resource secondResult = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child2")).thenReturn(secondResult);
- when(secondResult.getParent()).thenReturn(parent);
- when(secondResult.getPath()).thenReturn("/parent/child2");
- when(secondResult.getName()).thenReturn("child2");
- when(secondResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias2"));
-
- method.invoke(mapEntries, "/parent/child2");
- assertEquals(1, aliasMap.size());
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(3, aliasMapEntry.size());
-
- when(jcrContentResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "aliasJcrContentUpdated"));
- method1.invoke(mapEntries, "/parent/child/jcr:content", new String[] { "sling:alias" }, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(3, aliasMapEntry.size());
- assertFalse(aliasMapEntry.containsKey("aliasJcrContent"));
- assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated"));
-
- assertEquals(1, aliasMap.size());
-
-
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", null));
- when(jcrContentResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "aliasJcrContentUpdated"));
- method1.invoke(mapEntries, "/parent/child/jcr:content", new String[] { "sling:alias" }, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(2, aliasMapEntry.size());
- assertFalse(aliasMapEntry.containsKey("aliasJcrContent"));
- assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated"));
-
- assertEquals(1, aliasMap.size());
-
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doRemoveAlias() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doAddAlias", String.class);
- method.setAccessible(true);
-
- Method method1 = MapEntries.class.getDeclaredMethod("doRemoveAttributes", String.class, String[].class, boolean.class, boolean.class);
- method1.setAccessible(true);
-
- Field field0 = MapEntries.class.getDeclaredField("aliasMap");
- field0.setAccessible(true);
-
- Map<String, Map<String, String>> aliasMap = ( Map<String, Map<String, String>>) field0.get(mapEntries);
- assertEquals(0, aliasMap.size());
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent/child");
- when(result.getName()).thenReturn("child");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent/child");
-
- Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("alias"));
- assertEquals("child", aliasMapEntry.get("alias"));
-
- assertEquals(1, aliasMap.size());
-
- method1.invoke(mapEntries, "/parent/child", new String[] { "sling:alias" }, false, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNull(aliasMapEntry);
-
- assertEquals(0, aliasMap.size());
-
- //re-add node and test nodeDeletion true
- method.invoke(mapEntries, "/parent/child");
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("alias"));
- assertEquals("child", aliasMapEntry.get("alias"));
-
- assertEquals(1, aliasMap.size());
-
- when(resourceResolver.getResource("/parent/child")).thenReturn(null);
- method1.invoke(mapEntries, "/parent/child", new String[] { "sling:alias" }, true, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNull(aliasMapEntry);
-
- assertEquals(0, aliasMap.size());
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doRemoveAlias2() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doAddAlias", String.class);
- method.setAccessible(true);
-
- Method method1 = MapEntries.class.getDeclaredMethod("doRemoveAttributes", String.class, String[].class, boolean.class, boolean.class);
- method1.setAccessible(true);
-
- Field field0 = MapEntries.class.getDeclaredField("aliasMap");
- field0.setAccessible(true);
-
- Map<String, Map<String, String>> aliasMap = ( Map<String, Map<String, String>>) field0.get(mapEntries);
- assertEquals(0, aliasMap.size());
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent/child");
- when(result.getName()).thenReturn("child");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap());
-
- //testing jcr:content node removal
- final Resource jcrContentResult = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult);
- when(jcrContentResult.getParent()).thenReturn(result);
- when(jcrContentResult.getPath()).thenReturn("/parent/child/jcr:content");
- when(jcrContentResult.getName()).thenReturn("jcr:content");
- when(jcrContentResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "aliasJcrContent"));
- when(result.getChild("jcr:content")).thenReturn(jcrContentResult);
-
- method.invoke(mapEntries, "/parent/child/jcr:content");
-
- Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
-
- assertEquals(1, aliasMap.size());
-
- method1.invoke(mapEntries, "/parent/child/jcr:content", new String[] { "sling:alias" }, false, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNull(aliasMapEntry);
-
- assertEquals(0, aliasMap.size());
-
- //re-add node and test nodeDeletion true
- method.invoke(mapEntries, "/parent/child/jcr:content");
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
-
- assertEquals(1, aliasMap.size());
- when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null);
- when(result.getChild("jcr:content")).thenReturn(null);
- method1.invoke(mapEntries, "/parent/child/jcr:content", new String[] { "sling:alias" }, true, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNull(aliasMapEntry);
-
- assertEquals(0, aliasMap.size());
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doRemoveAlias3() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doAddAlias", String.class);
- method.setAccessible(true);
-
- Method method1 = MapEntries.class.getDeclaredMethod("doRemoveAttributes", String.class, String[].class, boolean.class, boolean.class);
- method1.setAccessible(true);
-
- Field field0 = MapEntries.class.getDeclaredField("aliasMap");
- field0.setAccessible(true);
-
- Map<String, Map<String, String>> aliasMap = ( Map<String, Map<String, String>>) field0.get(mapEntries);
- assertEquals(0, aliasMap.size());
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent/child");
- when(result.getName()).thenReturn("child");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent/child");
-
- final Resource jcrContentResult = mock(Resource.class);
- when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult);
- when(jcrContentResult.getParent()).thenReturn(result);
- when(jcrContentResult.getPath()).thenReturn("/parent/child/jcr:content");
- when(jcrContentResult.getName()).thenReturn("jcr:content");
- when(jcrContentResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "aliasJcrContent"));
- when(result.getChild("jcr:content")).thenReturn(jcrContentResult);
-
- method.invoke(mapEntries, "/parent/child/jcr:content");
-
- Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
-
- //test with two nodes
- assertEquals(1, aliasMap.size());
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(2, aliasMapEntry.size());
-
- method1.invoke(mapEntries, "/parent/child/jcr:content", new String[] { "sling:alias" }, false, false);
-
- assertEquals(1, aliasMap.size());
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(1, aliasMapEntry.size());
-
- // re-add the node and test /parent/child
- method.invoke(mapEntries, "/parent/child/jcr:content");
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
- assertEquals(2, aliasMapEntry.size());
-
- method1.invoke(mapEntries, "/parent/child", new String[] { "sling:alias" }, false, false);
-
- assertEquals(1, aliasMap.size());
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(1, aliasMapEntry.size());
-
- // re-add the node and test node removal
- method.invoke(mapEntries, "/parent/child");
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
- assertEquals(2, aliasMapEntry.size());
-
- when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null);
- when(result.getChild("jcr:content")).thenReturn(null);
- method1.invoke(mapEntries, "/parent/child/jcr:content", new String[] { "sling:alias" }, true, false);
-
- assertEquals(1, aliasMap.size());
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertEquals(1, aliasMapEntry.size());
-
- // re-add the node and test node removal for /parent/child
- when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult);
- when(result.getChild("jcr:content")).thenReturn(jcrContentResult);
- method.invoke(mapEntries, "/parent/child/jcr:content");
-
-
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertEquals("child", aliasMapEntry.get("aliasJcrContent"));
- assertEquals(2, aliasMapEntry.size());
-
- method1.invoke(mapEntries, "/parent/child", new String[] { "sling:alias" }, true, false);
-
- assertEquals(0, aliasMap.size());
- aliasMapEntry = mapEntries.getAliasMap("/parent");
- assertNull(aliasMapEntry);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doRemoveAlias4() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doAddAlias", String.class);
- method.setAccessible(true);
-
- Method method1 = MapEntries.class.getDeclaredMethod("doRemoveAttributes", String.class, String[].class, boolean.class, boolean.class);
- method1.setAccessible(true);
-
- Field field0 = MapEntries.class.getDeclaredField("aliasMap");
- field0.setAccessible(true);
-
- Map<String, Map<String, String>> aliasMap = ( Map<String, Map<String, String>>) field0.get(mapEntries);
- assertEquals(0, aliasMap.size());
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent");
- when(result.getName()).thenReturn("parent");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "alias"));
-
- method.invoke(mapEntries, "/parent");
-
- Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("alias"));
- assertEquals("parent", aliasMapEntry.get("alias"));
-
- assertEquals(1, aliasMap.size());
-
- method1.invoke(mapEntries, "/parent", new String[] { "sling:alias" }, false, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/");
- assertNull(aliasMapEntry);
-
- assertEquals(0, aliasMap.size());
-
- //re-add node and test nodeDeletion true
- method.invoke(mapEntries, "/parent");
-
- aliasMapEntry = mapEntries.getAliasMap("/");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("alias"));
- assertEquals("parent", aliasMapEntry.get("alias"));
-
- assertEquals(1, aliasMap.size());
-
- when(resourceResolver.getResource("/parent")).thenReturn(null);
- method1.invoke(mapEntries, "/parent", new String[] { "sling:alias" }, true, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/");
- assertNull(aliasMapEntry);
-
- assertEquals(0, aliasMap.size());
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void test_doRemoveAlias5() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doAddAlias", String.class);
- method.setAccessible(true);
-
- Method method1 = MapEntries.class.getDeclaredMethod("doRemoveAttributes", String.class, String[].class, boolean.class, boolean.class);
- method1.setAccessible(true);
-
- Field field0 = MapEntries.class.getDeclaredField("aliasMap");
- field0.setAccessible(true);
-
- Map<String, Map<String, String>> aliasMap = ( Map<String, Map<String, String>>) field0.get(mapEntries);
- assertEquals(0, aliasMap.size());
-
- Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/");
-
- final Resource result = mock(Resource.class);
- when(resourceResolver.getResource("/parent")).thenReturn(result);
- when(result.getParent()).thenReturn(parent);
- when(result.getPath()).thenReturn("/parent");
- when(result.getName()).thenReturn("parent");
- when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap());
-
- //testing jcr:content node removal
- final Resource jcrContentResult = mock(Resource.class);
- when(resourceResolver.getResource("/parent/jcr:content")).thenReturn(jcrContentResult);
- when(jcrContentResult.getParent()).thenReturn(result);
- when(jcrContentResult.getPath()).thenReturn("/parent/jcr:content");
- when(jcrContentResult.getName()).thenReturn("jcr:content");
- when(jcrContentResult.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:alias", "aliasJcrContent"));
- when(result.getChild("jcr:content")).thenReturn(jcrContentResult);
-
- method.invoke(mapEntries, "/parent/jcr:content");
-
- Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertEquals("parent", aliasMapEntry.get("aliasJcrContent"));
-
- assertEquals(1, aliasMap.size());
-
- method1.invoke(mapEntries, "/parent/jcr:content", new String[] { "sling:alias" }, false, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/");
- assertNull(aliasMapEntry);
-
- assertEquals(0, aliasMap.size());
-
- //re-add node and test nodeDeletion true
- method.invoke(mapEntries, "/parent/jcr:content");
-
- aliasMapEntry = mapEntries.getAliasMap("/");
- assertNotNull(aliasMapEntry);
- assertTrue(aliasMapEntry.containsKey("aliasJcrContent"));
- assertEquals("parent", aliasMapEntry.get("aliasJcrContent"));
-
- assertEquals(1, aliasMap.size());
- when(resourceResolver.getResource("/parent/jcr:content")).thenReturn(null);
- when(result.getChild("jcr:content")).thenReturn(null);
- method1.invoke(mapEntries, "/parent/jcr:content", new String[] { "sling:alias" }, true, false);
-
- aliasMapEntry = mapEntries.getAliasMap("/");
- assertNull(aliasMapEntry);
-
- assertEquals(0, aliasMap.size());
- }
-
- @Test
- public void test_isValidVanityPath() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("isValidVanityPath", Resource.class);
- method.setAccessible(true);
-
- final Resource resource = mock(Resource.class);
- when(resource.getPath()).thenReturn("/jcr:system/node");
-
- assertFalse((Boolean)method.invoke(mapEntries, resource));
-
- when(resource.getPath()).thenReturn("/justVanityPath");
- assertFalse((Boolean)method.invoke(mapEntries, resource));
-
- when(resource.adaptTo(ValueMap.class)).thenReturn(mock(ValueMap.class));
- assertTrue((Boolean)method.invoke(mapEntries, resource));
- }
-
- @Test
- //SLING-4847
- public void test_doNodeAdded1() throws Exception {
- Method method = MapEntries.class.getDeclaredMethod("doNodeAdded", String.class, boolean.class);
- method.setAccessible(true);
- Boolean resfreshed = (Boolean ) method.invoke(mapEntries, "/node", true);
- assertTrue(resfreshed.booleanValue());
- }
-
- @Test
- //SLING-4891
- public void test_getVanityPaths_1() throws Exception {
-
- Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries");
- field1.setAccessible(true);
- field1.set(mapEntries, 0);
-
- Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class);
- method.setAccessible(true);
- method.invoke(mapEntries, "/notExisting");
-
- Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(0, counter.longValue());
- }
-
- @Test
- //SLING-4891
- public void test_getVanityPaths_2() throws Exception {
-
- final Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return Collections.singleton(justVanityPath).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries");
- field1.setAccessible(true);
- field1.set(mapEntries, 0);
-
- Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class);
- method.setAccessible(true);
- method.invoke(mapEntries, "/target/justVanityPath");
-
- Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(2, counter.longValue());
-
- final Resource justVanityPath2 = mock(Resource.class, "justVanityPath2");
- when(resourceResolver.getResource("/justVanityPath2")).thenReturn(justVanityPath2);
- when(justVanityPath2.getPath()).thenReturn("/justVanityPath2");
- when(justVanityPath2.getName()).thenReturn("justVanityPath2");
- when(justVanityPath2.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath","sling:vanityOrder", 100));
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return Collections.singleton(justVanityPath).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- method.invoke(mapEntries, "/target/justVanityPath");
-
- counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(4, counter.longValue());
- }
-
- @Test
- //SLING-4891
- public void test_getVanityPaths_3() throws Exception {
-
- final Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return Collections.singleton(justVanityPath).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries");
- field1.setAccessible(true);
- field1.set(mapEntries, 0);
-
- Field field2 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntriesStartup");
- field2.setAccessible(true);
- field2.set(mapEntries, false);
-
- Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class);
- method.setAccessible(true);
- method.invoke(mapEntries, "/target/justVanityPath");
-
- Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(0, counter.longValue());
- }
-
- @Test
- //SLING-4891
- public void test_getVanityPaths_4() throws Exception {
-
- final Resource badVanityPath = mock(Resource.class, "badVanityPath");
- when(badVanityPath.getPath()).thenReturn("/badVanityPath");
- when(badVanityPath.getName()).thenReturn("badVanityPath");
- when(badVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/content/mypage/en-us-{132"));
-
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return Collections.singleton(badVanityPath).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries");
- field1.setAccessible(true);
- field1.set(mapEntries, 0);
-
- Field field2 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntriesStartup");
- field2.setAccessible(true);
- field2.set(mapEntries, true);
-
- Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class);
- method.setAccessible(true);
- method.invoke(mapEntries, "/content/mypage/en-us-{132");
-
- Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(0, counter.longValue());
- }
-
- @Test
- //SLING-4891
- public void test_getVanityPaths_5() throws Exception {
-
- final Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return Collections.singleton(justVanityPath).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries");
- field1.setAccessible(true);
- field1.set(mapEntries, 2);
-
- Field field2 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntriesStartup");
- field2.setAccessible(true);
- field2.set(mapEntries, false);
-
- Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class);
- method.setAccessible(true);
- method.invoke(mapEntries, "/target/justVanityPath");
-
- Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(2, counter.longValue());
-
- final Resource justVanityPath2 = mock(Resource.class, "justVanityPath2");
- when(resourceResolver.getResource("/justVanityPath2")).thenReturn(justVanityPath2);
- when(justVanityPath2.getPath()).thenReturn("/justVanityPath2");
- when(justVanityPath2.getName()).thenReturn("justVanityPath2");
- when(justVanityPath2.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath","sling:vanityOrder", 100));
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return Collections.singleton(justVanityPath).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- method.invoke(mapEntries, "/target/justVanityPath");
-
- counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(2, counter.longValue());
- }
-
- @Test
- //SLING-4891
- public void test_loadVanityPaths() throws Exception {
- Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries");
- field1.setAccessible(true);
- field1.set(mapEntries, 2);
-
- final Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return Collections.singleton(justVanityPath).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- Method method = MapEntries.class.getDeclaredMethod("loadVanityPaths", boolean.class);
- method.setAccessible(true);
- method.invoke(mapEntries, false);
-
- Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(2, counter.longValue());
- }
-
- @Test
- //SLING-4891
- public void test_loadVanityPaths_1() throws Exception {
-
- final Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return Collections.singleton(justVanityPath).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- Method method = MapEntries.class.getDeclaredMethod("loadVanityPaths", boolean.class);
- method.setAccessible(true);
- method.invoke(mapEntries, false);
-
- Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(2, counter.longValue());
- }
-
- @Test
- //SLING-4891
- public void test_getMapEntryList() throws Exception {
-
- List<MapEntry> entries = mapEntries.getResolveMaps();
- assertEquals(0, entries.size());
-
-
- final Resource justVanityPath = mock(Resource.class,
- "justVanityPath");
-
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
-
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
-
- when(justVanityPath.getName()).thenReturn("justVanityPath");
-
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath",
- "/target/justVanityPath"));
-
- when(resourceResolver.findResources(anyString(),
- eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation)
- throws Throwable {
- if
- (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return Collections.singleton(justVanityPath).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
- Method method =
- MapEntries.class.getDeclaredMethod("getMapEntryList",String.class);
- method.setAccessible(true);
- method.invoke(mapEntries, "/target/justVanityPath");
-
- entries = mapEntries.getResolveMaps();
- assertEquals(2, entries.size());
-
- Field vanityCounter =
- MapEntries.class.getDeclaredField("vanityCounter");
- vanityCounter.setAccessible(true);
- AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(2, counter.longValue());
-
- method.invoke(mapEntries, "/target/justVanityPath");
-
- entries = mapEntries.getResolveMaps();
- assertEquals(2, entries.size());
-
- counter = (AtomicLong) vanityCounter.get(mapEntries);
- assertEquals(2, counter.longValue());
- }
-
- @Test
- //SLING-4883
- public void test_concutrrent_getResolveMapsIterator() throws Exception {
- ExecutorService pool = Executors.newFixedThreadPool(10);
-
- final Resource justVanityPath = mock(Resource.class, "justVanityPath");
- when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath);
- when(justVanityPath.getPath()).thenReturn("/justVanityPath");
- when(justVanityPath.getName()).thenReturn("justVanityPath");
- when(justVanityPath.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath"));
-
-
- when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() {
-
- public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable {
- if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) {
- return Collections.singleton(justVanityPath).iterator();
- } else {
- return Collections.<Resource> emptySet().iterator();
- }
- }
- });
-
-
- Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries");
- field1.setAccessible(true);
- field1.set(mapEntries, 2);
-
- ArrayList<DataFuture> list = new ArrayList<DataFuture>();
- for (int i =0;i<10;i++) {
- list.add(createDataFuture(pool, mapEntries));
-
- }
-
- for (DataFuture df : list) {
- df.future.get();
- }
-
- }
-
- // -------------------------- private methods ----------
- private DataFuture createDataFuture(ExecutorService pool, final MapEntries mapEntries) {
-
- Future<Iterator<?>> future = pool.submit(new Callable<Iterator<?>>() {
- @Override
- public Iterator<MapEntry> call() throws Exception {
- return mapEntries.getResolveMapsIterator("http/localhost.8080/target/justVanityPath");
- }
- });
- return new DataFuture(future);
- }
-
- // -------------------------- inner classes ------------
-
- private static class DataFuture {
- public Future<Iterator<?>> future;
-
- public DataFuture(Future<Iterator<?>> future) {
- super();
- this.future = future;
- }
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntryTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntryTest.java
deleted file mode 100644
index d45fcf0..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntryTest.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * 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.resourceresolver.impl.mapping;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.lang.reflect.Method;
-
-import junit.framework.TestCase;
-
-import org.junit.Test;
-
-public class MapEntryTest {
-
- @Test public void test_to_url_http_80() {
- assertEqualUri("http://sling.apache.org", "http/sling.apache.org.80");
- assertEqualUri("http://sling.apache.org/", "http/sling.apache.org.80/");
- assertEqualUri("http://sling.apache.org/site/index.html",
- "http/sling.apache.org.80/site/index.html");
- }
-
- @Test public void test_to_url_https_443() {
- assertEqualUri("https://sling.apache.org", "https/sling.apache.org.443");
- assertEqualUri("https://sling.apache.org/",
- "https/sling.apache.org.443/");
- assertEqualUri("https://sling.apache.org/site/index.html",
- "https/sling.apache.org.443/site/index.html");
- }
-
- @Test public void test_to_url_any_999() {
- // http with arbitrary port
- assertEqualUri("http://sling.apache.org:123",
- "http/sling.apache.org.123");
- assertEqualUri("http://sling.apache.org:456/",
- "http/sling.apache.org.456/");
- assertEqualUri("http://sling.apache.org:456/site/index.html",
- "http/sling.apache.org.456/site/index.html");
-
- // https with arbitrary port
- assertEqualUri("https://sling.apache.org:987",
- "https/sling.apache.org.987");
- assertEqualUri("https://sling.apache.org:654/",
- "https/sling.apache.org.654/");
- assertEqualUri("https://sling.apache.org:321/site/index.html",
- "https/sling.apache.org.321/site/index.html");
-
- // any scheme with arbitrary port
- assertEqualUri("gurk://sling.apache.org:987",
- "gurk/sling.apache.org.987");
- assertEqualUri("gurk://sling.apache.org:654/",
- "gurk/sling.apache.org.654/");
- assertEqualUri("gurk://sling.apache.org:321/site/index.html",
- "gurk/sling.apache.org.321/site/index.html");
- }
-
- @Test public void test_to_url_any() {
- // http without port
- assertEqualUri("http://sling.apache.org", "http/sling.apache.org");
- assertEqualUri("http://sling.apache.org/", "http/sling.apache.org/");
- assertEqualUri("http://sling.apache.org/site/index.html",
- "http/sling.apache.org/site/index.html");
-
- // https without port
- assertEqualUri("https://sling.apache.org", "https/sling.apache.org");
- assertEqualUri("https://sling.apache.org/", "https/sling.apache.org/");
- assertEqualUri("https://sling.apache.org/site/index.html",
- "https/sling.apache.org/site/index.html");
-
- // any scheme without port
- assertEqualUri("gurk://sling.apache.org", "gurk/sling.apache.org");
- assertEqualUri("gurk://sling.apache.org/", "gurk/sling.apache.org/");
- assertEqualUri("gurk://sling.apache.org/site/index.html",
- "gurk/sling.apache.org/site/index.html");
- }
-
- @Test public void test_fixUriPath() {
- // http without port
- assertEqualUriPath("http/sling.apache.org.80", "http/sling.apache.org");
- assertEqualUriPath("http/sling.apache.org.80/",
- "http/sling.apache.org/");
- assertEqualUriPath("http/sling.apache.org.80/site/index.html",
- "http/sling.apache.org/site/index.html");
-
- // http with port
- assertEqualUriPath("http/sling.apache.org.80",
- "http/sling.apache.org.80");
- assertEqualUriPath("http/sling.apache.org.80/",
- "http/sling.apache.org.80/");
- assertEqualUriPath("http/sling.apache.org.80/site/index.html",
- "http/sling.apache.org.80/site/index.html");
-
- // https without port
- assertEqualUriPath("https/sling.apache.org.443",
- "https/sling.apache.org");
- assertEqualUriPath("https/sling.apache.org.443/",
- "https/sling.apache.org/");
- assertEqualUriPath("https/sling.apache.org.443/site/index.html",
- "https/sling.apache.org/site/index.html");
-
- // https with port
- assertEqualUriPath("https/sling.apache.org.443",
- "https/sling.apache.org.443");
- assertEqualUriPath("https/sling.apache.org.443/",
- "https/sling.apache.org.443/");
- assertEqualUriPath("https/sling.apache.org.443/site/index.html",
- "https/sling.apache.org.443/site/index.html");
-
- // anything without port
- assertEqualUriPath("gurk/sling.apache.org", "gurk/sling.apache.org");
- assertEqualUriPath("gurk/sling.apache.org/", "gurk/sling.apache.org/");
- assertEqualUriPath("gurk/sling.apache.org/site/index.html",
- "gurk/sling.apache.org/site/index.html");
-
- // http with port
- assertEqualUriPath("gurk/sling.apache.org.123",
- "gurk/sling.apache.org.123");
- assertEqualUriPath("gurk/sling.apache.org.456/",
- "gurk/sling.apache.org.456/");
- assertEqualUriPath("gurk/sling.apache.org.789/site/index.html",
- "gurk/sling.apache.org.789/site/index.html");
-
- }
-
- @Test public void test_isRegExp() {
- TestCase.assertFalse(isRegExp("http/www.example.com.8080/bla"));
- TestCase.assertTrue(isRegExp("http/.+\\.www.example.com.8080/bla"));
- TestCase.assertTrue(isRegExp("http/(.+)\\.www.example.com.8080/bla"));
- TestCase.assertTrue(isRegExp("http/(.+)\\.www.example.com.8080/bla"));
- TestCase.assertTrue(isRegExp("http/[^.]+.www.example.com.8080/bla"));
- }
-
- @Test public void test_filterRegExp() {
- TestCase.assertNull(filterRegExp((String[]) null));
- TestCase.assertNull(filterRegExp(new String[0]));
-
- String aString = "plain";
- String aPattern = "http/[^.]+.www.example.com.8080/bla";
-
- TestCase.assertNull(filterRegExp(aPattern));
-
- String[] res = filterRegExp(aString);
- TestCase.assertNotNull(res);
- TestCase.assertEquals(1, res.length);
- TestCase.assertEquals(aString, res[0]);
-
- res = filterRegExp(aString, aPattern);
- TestCase.assertNotNull(res);
- TestCase.assertEquals(1, res.length);
- TestCase.assertEquals(aString, res[0]);
-
- res = filterRegExp(aPattern, aString, aPattern);
- TestCase.assertNotNull(res);
- TestCase.assertEquals(1, res.length);
- TestCase.assertEquals(aString, res[0]);
-
- res = filterRegExp(aPattern, aString);
- TestCase.assertNotNull(res);
- TestCase.assertEquals(1, res.length);
- TestCase.assertEquals(aString, res[0]);
- }
-
- @Test public void test_compareTo() {
- final MapEntry a = new MapEntry("/foo", 200, false, 5, new String[0]);
- final MapEntry b = new MapEntry("/bar", 200, false, 5, new String[0]);
-
- assertTrue(a.compareTo(b) > 0);
- assertTrue(b.compareTo(a) < 0);
- assertTrue(a.compareTo(a) == 0);
- assertTrue(b.compareTo(b) == 0);
- }
-
- private void assertEqualUri(String expected, String uriPath) {
- String uri = MapEntry.toURI(uriPath);
- assertNotNull("Failed converting " + uriPath, uri);
- assertEquals(expected, uri.toString());
- }
-
- private void assertEqualUriPath(String expected, String uriPath) {
- String fixed = MapEntry.fixUriPath(uriPath);
- assertNotNull(fixed);
- assertEquals(expected, fixed);
- }
-
- private boolean isRegExp(final String string) {
- try {
- Method m = MapEntry.class.getDeclaredMethod("isRegExp", String.class);
- m.setAccessible(true);
- return (Boolean) m.invoke(null, string);
- } catch (Exception e) {
- fail(e.toString());
- return false; // quiesc compiler
- }
- }
-
- private String[] filterRegExp(final String... strings) {
- try {
- Method m = MapEntry.class.getDeclaredMethod("filterRegExp", String[].class);
- m.setAccessible(true);
- return (String[]) m.invoke(null, new Object[] {
- strings
- });
- } catch (Exception e) {
- fail(e.toString());
- return null; // quiesc compiler
- }
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerInfoTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerInfoTest.java
deleted file mode 100644
index cdcfd81..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/observation/ResourceChangeListenerInfoTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*******************************************************************************
- * 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.resourceresolver.impl.observation;
-
-import java.util.Set;
-
-import org.apache.sling.api.resource.observation.ResourceChangeListener;
-import org.junit.Test;
-import org.osgi.framework.ServiceReference;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class ResourceChangeListenerInfoTest {
-
- @Test
- public void testGetExpandedRelativePaths() {
- ServiceReference reference = mock(ServiceReference.class);
- when(reference.getProperty(ResourceChangeListener.PATHS)).thenReturn(new String[] {"./**/*.html"});
- final ResourceChangeListenerInfo rcli = new ResourceChangeListenerInfo(reference, new String[] {"/apps/", "/libs/"});
- Set<String> paths = rcli.getPaths().toStringSet();
- assertTrue("PathSet " + paths.toString() + " does not contain /apps/**/*.html.", paths.contains("/apps/**/*.html"));
- assertTrue("PathSet " + paths.toString() + " does not contain /libs/**/*.html.", paths.contains("/libs/**/*.html"));
- }
-
- @Test
- public void testDotPathConfig() {
- ServiceReference reference = mock(ServiceReference.class);
- when(reference.getProperty(ResourceChangeListener.PATHS)).thenReturn(new String[] {"."});
- final ResourceChangeListenerInfo rcli = new ResourceChangeListenerInfo(reference, new String[] {"/apps/", "/libs/"});
- Set<String> paths = rcli.getPaths().toStringSet();
- assertTrue("PathSet " + paths.toString() + " does not contain /apps/", paths.contains("/apps/"));
- assertTrue("PathSet " + paths.toString() + " does not contain /libs/.", paths.contains("/libs/"));
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/params/PathParserTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/params/PathParserTest.java
deleted file mode 100644
index 5c81d6a..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/params/PathParserTest.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.resourceresolver.impl.params;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.sling.resourceresolver.impl.params.PathParser;
-import org.junit.Test;
-
-public class PathParserTest {
-
- private PathParser parser = new PathParser();
-
- @Test
- public void nullParsesToNull() {
- parser.parse(null);
- assertNull(parser.getPath());
- assertTrue(parser.getParameters().isEmpty());
- }
-
- @Test
- public void emptyParsesToEmpty() {
- parser.parse("");
- assertEquals("", parser.getPath());
- assertTrue(parser.getParameters().isEmpty());
- }
-
- @Test
- public void noParametersReturnEmptyMap() {
- parser.parse("/path/with/no/parameters");
- assertEquals("/path/with/no/parameters", parser.getPath());
- assertTrue(parser.getParameters().isEmpty());
- }
-
- @Test
- public void parameterCanBeAddedAfterResource() {
- parser.parse("/content/test;key1=xyz");
- assertEquals("/content/test", parser.getPath());
- assertEquals(map("key1", "xyz"), parser.getParameters());
-
- parser.parse("/content/test;key1=xyz.html");
- assertEquals("/content/test.html", parser.getPath());
- assertEquals(map("key1", "xyz"), parser.getParameters());
- }
-
- @Test
- public void parameterCanBeEscaped() {
- parser.parse("/content/test;key1='xyz'");
- assertEquals("/content/test", parser.getPath());
- assertEquals(map("key1", "xyz"), parser.getParameters());
-
- parser.parse("/content/test;key1='xyz'.html");
- assertEquals("/content/test.html", parser.getPath());
- assertEquals(map("key1", "xyz"), parser.getParameters());
- }
-
- @Test
- public void multipleParametersAreAllowed() {
- parser.parse("/content/test;key1=xyz;key2=abc");
- assertEquals("/content/test", parser.getPath());
- assertEquals(map("key1", "xyz", "key2", "abc"), parser.getParameters());
-
- parser.parse("/content/test;key1=xyz;key2=abc.html");
- assertEquals("/content/test.html", parser.getPath());
- assertEquals(map("key1", "xyz", "key2", "abc"), parser.getParameters());
- }
-
- @Test
- public void multipleParametersCanBeEscaped() {
- parser.parse("/content/test;key1='a.b';key2='c.d'");
- assertEquals("/content/test", parser.getPath());
- assertEquals(map("key1", "a.b", "key2", "c.d"), parser.getParameters());
-
- parser.parse("/content/test;key1='a.b';key2='c.d'.html");
- assertEquals("/content/test.html", parser.getPath());
- assertEquals(map("key1", "a.b", "key2", "c.d"), parser.getParameters());
- }
-
- @Test
- public void parameterCanBeAddedAfterExtension() {
- parser.parse("/content/test.html;key1=xyz");
- assertEquals("/content/test.html", parser.getPath());
- assertEquals(map("key1", "xyz"), parser.getParameters());
-
- parser.parse("/content/test.html;key1=xyz/suffix");
- assertEquals("/content/test.html/suffix", parser.getPath());
- assertEquals(map("key1", "xyz"), parser.getParameters());
-
- }
-
- @Test
- public void dotDoesntHaveToBeEscapedAfterExtension() {
- parser.parse("/content/test.html;v=1.0");
- assertEquals("/content/test.html", parser.getPath());
- assertEquals(map("v", "1.0"), parser.getParameters());
-
- parser.parse("/content/test.html;v=1.0/suffix");
- assertEquals("/content/test.html/suffix", parser.getPath());
- assertEquals(map("v", "1.0"), parser.getParameters());
- }
-
- @Test
- public void slashHaveToBeEscapedAfterExtension() {
- parser.parse("/content/test.html;v='1/0'");
- assertEquals("/content/test.html", parser.getPath());
- assertEquals(map("v", "1/0"), parser.getParameters());
-
- parser.parse("/content/test.html;v='1/0'/suffix");
- assertEquals("/content/test.html/suffix", parser.getPath());
- assertEquals(map("v", "1/0"), parser.getParameters());
- }
-
- @Test
- public void quoteHasToBeClosed() {
- testInvalidParams("/content/test;key1='a.b;key2=cde.html/asd");
- }
-
- @Test
- public void emptyValueIsAllowed() {
- parser.parse("/content/test;key1=''.html");
- assertEquals("/content/test.html", parser.getPath());
- assertEquals(map("key1", ""), parser.getParameters());
-
- parser.parse("/content/test;key1=.html");
- assertEquals("/content/test.html", parser.getPath());
- assertEquals(map("key1", ""), parser.getParameters());
- }
-
- @Test
- public void parametersWithoutEqualsSignAreInvalid() {
- testInvalidParams("/content/test;key1.html");
- }
-
- @Test
- public void parametersInTheMiddleOfThePathAreInvalid() {
- testInvalidParams("/content;key=value/test.html");
- }
-
- @Test
- public void parametersInTheSuffixAreInvalid() {
- testInvalidParams("/content/test.html/suffix;key=value");
- }
-
- private static Map<String, String> map(String... values) {
- Map<String, String> m = new HashMap<String, String>();
- for (int i = 0; i < values.length; i += 2) {
- m.put(values[i], values[i + 1]);
- }
- return m;
- }
-
- private void testInvalidParams(String path) {
- parser.parse(path);
- assertEquals(path, parser.getPath());
- assertEquals(map(), parser.getParameters());
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTrackerTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTrackerTest.java
deleted file mode 100644
index 9105929..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTrackerTest.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers;
-
-import static org.hamcrest.Matchers.arrayWithSize;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.hasSize;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.sling.api.resource.observation.ResourceChange;
-import org.apache.sling.api.resource.path.Path;
-import org.apache.sling.api.resource.path.PathSet;
-import org.apache.sling.api.resource.runtime.dto.AuthType;
-import org.apache.sling.api.resource.runtime.dto.RuntimeDTO;
-import org.apache.sling.resourceresolver.impl.Fixture;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker.ChangeListener;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker.ObservationReporterGenerator;
-import org.apache.sling.spi.resource.provider.ObservationReporter;
-import org.apache.sling.spi.resource.provider.ObserverConfiguration;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.apache.sling.testing.mock.osgi.MockOsgi;
-import org.junit.Before;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.event.EventAdmin;
-
-public class ResourceProviderTrackerTest {
-
- private ResourceProviderInfo rp2Info;
- private ResourceProviderTracker tracker;
- private Fixture fixture;
-
- @Before
- public void prepare() throws Exception {
- BundleContext bundleContext = MockOsgi.newBundleContext();
-
- fixture = new Fixture(bundleContext);
-
- EventAdmin eventAdmin = mock(EventAdmin.class);
-
- @SuppressWarnings("unchecked")
- ResourceProvider<Object> rp = mock(ResourceProvider.class);
- @SuppressWarnings("unchecked")
- ResourceProvider<Object> rp2 = mock(ResourceProvider.class);
- @SuppressWarnings("unchecked")
- ResourceProvider<Object> rp3 = mock(ResourceProvider.class);
-
- fixture.registerResourceProvider(rp, "/", AuthType.no);
- rp2Info = fixture.registerResourceProvider(rp2, "/path", AuthType.lazy);
- fixture.registerResourceProvider(rp3, "invalid", AuthType.no);
-
- tracker = new ResourceProviderTracker();
-
- tracker.setObservationReporterGenerator(new SimpleObservationReporterGenerator(new NoDothingObservationReporter()));
- tracker.activate(bundleContext, eventAdmin, new DoNothingChangeListener());
- }
-
- @Test
- public void activate() {
-
- // since the OSGi mocks are asynchronous we don't have to wait for the changes to propagate
-
- assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(2));
-
- fixture.unregisterResourceProvider(rp2Info);
-
- assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(1));
- }
-
- @Test
- public void deactivate() {
-
- tracker.deactivate();
-
- assertThat(tracker.getResourceProviderStorage().getAllHandlers(), hasSize(0));
- }
-
- @Test
- public void testActivationDeactivation() throws Exception {
- final BundleContext bundleContext = MockOsgi.newBundleContext();
- final EventAdmin eventAdmin = mock(EventAdmin.class);
-
- final Fixture fixture = new Fixture(bundleContext);
- final ResourceProviderTracker tracker = new ResourceProviderTracker();
- tracker.setObservationReporterGenerator(new SimpleObservationReporterGenerator(new NoDothingObservationReporter()));
-
- // create boolean markers for the listener
- final AtomicBoolean addedCalled = new AtomicBoolean(false);
- final AtomicBoolean removedCalled = new AtomicBoolean(false);
-
- final ChangeListener listener = new ChangeListener() {
-
- @Override
- public void providerAdded() {
- addedCalled.set(true);
- }
-
- @Override
- public void providerRemoved(String name, String pid, boolean stateful, boolean used) {
- removedCalled.set(true);
- }
-
- };
- // activate and check that no listener is called yet
- tracker.activate(bundleContext, eventAdmin, listener);
- assertFalse(addedCalled.get());
- assertFalse(removedCalled.get());
-
- // add a new resource provider
- @SuppressWarnings("unchecked")
- ResourceProvider<Object> rp = mock(ResourceProvider.class);
- final ResourceProviderInfo info = fixture.registerResourceProvider(rp, "/", AuthType.no);
-
- // check added is called but not removed
- assertTrue(addedCalled.get());
- assertFalse(removedCalled.get());
-
- // verify a single provider
- assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(1));
-
- // reset boolean markers
- addedCalled.set(false);
- removedCalled.set(false);
-
- // remove provider
- fixture.unregisterResourceProvider(info);
-
- // verify removed is called but not added
- assertTrue(removedCalled.get());
- assertFalse(addedCalled.get());
-
- // no provider anymore
- assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(0));
- }
-
- @Test
- public void testReactivation() throws Exception {
- final BundleContext bundleContext = MockOsgi.newBundleContext();
- final EventAdmin eventAdmin = mock(EventAdmin.class);
-
- final Fixture fixture = new Fixture(bundleContext);
- final ResourceProviderTracker tracker = new ResourceProviderTracker();
- tracker.setObservationReporterGenerator(new SimpleObservationReporterGenerator(new NoDothingObservationReporter()));
-
- // create boolean markers for the listener
- final AtomicBoolean addedCalled = new AtomicBoolean(false);
- final AtomicBoolean removedCalled = new AtomicBoolean(false);
-
- final ChangeListener listener = new ChangeListener() {
-
- @Override
- public void providerAdded() {
- addedCalled.set(true);
- }
-
- @Override
- public void providerRemoved(String name, String pid, boolean stateful, boolean used) {
- removedCalled.set(true);
- }
-
- };
- // activate and check that no listener is called yet
- tracker.activate(bundleContext, eventAdmin, listener);
- assertFalse(addedCalled.get());
- assertFalse(removedCalled.get());
-
- // activate and check that no listener is called yet
- @SuppressWarnings("unchecked")
- ResourceProvider<Object> rp = mock(ResourceProvider.class);
- final ResourceProviderInfo info = fixture.registerResourceProvider(rp, "/", AuthType.no);
-
- // check added is called but not removed
- assertTrue(addedCalled.get());
- assertFalse(removedCalled.get());
-
- // verify a single provider
- assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(1));
-
- // reset boolean markers
- addedCalled.set(false);
- removedCalled.set(false);
-
- // add overlay provider
- final ResourceProviderInfo infoOverlay = fixture.registerResourceProvider(rp, "/", AuthType.no);
-
- // check added and removed is called
- assertTrue(addedCalled.get());
- assertTrue(removedCalled.get());
-
- // verify a single provider
- assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(1));
-
- // reset boolean markers
- addedCalled.set(false);
- removedCalled.set(false);
-
- // unregister overlay provider
- fixture.unregisterResourceProvider(infoOverlay);
-
- // check added and removed is called
- assertTrue(addedCalled.get());
- assertTrue(removedCalled.get());
-
- // verify a single provider
- assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(1));
-
- // reset boolean markers
- addedCalled.set(false);
- removedCalled.set(false);
-
- // unregister first provider
- fixture.unregisterResourceProvider(info);
-
- // check removed is called but not added
- assertTrue(removedCalled.get());
- assertFalse(addedCalled.get());
-
- // verify no provider
- assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(0));
- }
-
- @Test
- public void fillDto() throws Exception {
-
- RuntimeDTO dto = new RuntimeDTO();
-
- tracker.fill(dto);
-
- assertThat( dto.providers, arrayWithSize(2));
- assertThat( dto.failedProviders, arrayWithSize(1));
- }
-
- static final class NoDothingObservationReporter implements ObservationReporter {
- @Override
- public void reportChanges(Iterable<ResourceChange> changes, boolean distribute) {
- }
-
- @Override
- public List<ObserverConfiguration> getObserverConfigurations() {
- return Collections.emptyList();
- }
- }
-
- static final class SimpleObservationReporterGenerator implements ObservationReporterGenerator {
- private final ObservationReporter reporter;
-
- SimpleObservationReporterGenerator(ObservationReporter reporter) {
- this.reporter = reporter;
- }
-
- @Override
- public ObservationReporter createProviderReporter() {
- return reporter;
- }
-
- @Override
- public ObservationReporter create(Path path, PathSet excludes) {
- return reporter;
- }
- }
-
- static final class DoNothingChangeListener implements ChangeListener {
-
- @Override
- public void providerAdded() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void providerRemoved(String name, String pid, boolean stateful, boolean used) {
- // TODO Auto-generated method stub
-
- }
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProviderTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProviderTest.java
deleted file mode 100644
index 319cd95..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/providers/stateful/AuthenticatedResourceProviderTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers.stateful;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.security.AccessSecurityException;
-import org.apache.sling.api.security.ResourceAccessSecurity;
-import org.apache.sling.resourceresolver.impl.ResourceAccessSecurityTracker;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.junit.Before;
-import org.junit.Test;
-
-public class AuthenticatedResourceProviderTest {
-
- private AuthenticatedResourceProvider src;
-
- private ResourceAccessSecurity security;
- private ResourceResolver resourceResolver;
- private ResolveContext<Object> resolveContext;
- private ResourceProvider<Object> resourceProvider;
- private QueryLanguageProvider<Object> queryLanguageProvider;
-
- private boolean useRAS;
-
- @Before
- public void prepare() throws PersistenceException, AccessSecurityException {
- this.resourceResolver = mock(ResourceResolver.class);
- this.resolveContext = mock(ResolveContext.class);
- when(this.resolveContext.getResourceResolver()).thenReturn(this.resourceResolver);
-
- this.security = mock(ResourceAccessSecurity.class);
-
- this.queryLanguageProvider = mock(QueryLanguageProvider.class);
-
- this.resourceProvider = mock(ResourceProvider.class);
- when(resourceProvider.getQueryLanguageProvider()).thenReturn(this.queryLanguageProvider);
-
- final ResourceProviderHandler handler = mock(ResourceProviderHandler.class);
- when(handler.getResourceProvider()).thenReturn(this.resourceProvider);
-
- useRAS = false;
-
- final ResourceAccessSecurityTracker securityTracker = new ResourceAccessSecurityTracker() {
- @Override
- public ResourceAccessSecurity getApplicationResourceAccessSecurity() {
- if ( useRAS) {
- return security;
- }
- return null;
- }
- };
-
- this.src = new AuthenticatedResourceProvider(handler, false, this.resolveContext, securityTracker);
-
- }
-
- @Test public void testBasics() throws Exception {
- assertEquals(this.resolveContext, this.src.getResolveContext());
-
- this.src.refresh();
- verify(this.resourceProvider).refresh(this.resolveContext);
-
- when(this.resourceProvider.isLive(this.resolveContext)).thenReturn(true);
- assertTrue(this.src.isLive());
- when(this.resourceProvider.isLive(this.resolveContext)).thenReturn(false);
- assertFalse(this.src.isLive());
-
- this.src.commit();
- verify(this.resourceProvider).commit(this.resolveContext);
- }
-
- @Test public void testGetParent() {
- final Resource child = mock(Resource.class);
- when(child.getPath()).thenReturn("/parent/child");
- final Resource parent = mock(Resource.class);
- when(parent.getPath()).thenReturn("/parent");
- when(this.resourceProvider.getParent(this.resolveContext, child)).thenReturn(parent);
-
- assertEquals("/parent", this.src.getParent(child).getPath());
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/providers/stateful/SecureResourceProviderDecoratorTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/providers/stateful/SecureResourceProviderDecoratorTest.java
deleted file mode 100644
index 8442a71..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/providers/stateful/SecureResourceProviderDecoratorTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers.stateful;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.equalTo;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.security.AccessSecurityException;
-import org.apache.sling.api.security.ResourceAccessSecurity;
-import org.apache.sling.resourceresolver.impl.ResourceAccessSecurityTracker;
-import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
-import org.apache.sling.spi.resource.provider.QueryLanguageProvider;
-import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-public class SecureResourceProviderDecoratorTest {
-
- private ResourceAccessSecurity security;
- private ResourceResolver rr;
- private ResolveContext resolveContext;
- private AuthenticatedResourceProvider src;
- private ResourceProvider rp;
- private Resource first;
- private Resource second;
-
- @Before
- public void prepare() throws PersistenceException, AccessSecurityException {
-
- rr = mock(ResourceResolver.class);
- resolveContext = mock(ResolveContext.class);
- when(resolveContext.getResourceResolver()).thenReturn(rr);
-
- security = mock(ResourceAccessSecurity.class);
- first = mock(Resource.class);
- second = mock(Resource.class);
-
- when(security.getReadableResource(first)).thenReturn(first);
- when(security.getReadableResource(second)).thenReturn(null);
- when(security.transformQuery("FIND ALL", "MockQueryLanguage", rr)).thenReturn("FIND ALL");
-
- QueryLanguageProvider qlp = mock(QueryLanguageProvider.class);
-
- rp = mock(ResourceProvider.class);
- when(rp.getQueryLanguageProvider()).thenReturn(qlp);
-
- when(rp.create(resolveContext, "/some/path", Collections.<String, Object> emptyMap())).thenReturn(mock(Resource.class));
- when(qlp.findResources(resolveContext, "FIND ALL", "MockQueryLanguage")).thenReturn(Arrays.asList(first, second).iterator());
-
- ResourceAccessSecurityTracker securityTracker = new ResourceAccessSecurityTracker() {
- @Override
- public ResourceAccessSecurity getApplicationResourceAccessSecurity() {
- return security;
- }
- };
-
- final ResourceProviderHandler handler = mock(ResourceProviderHandler.class);
- when(handler.getResourceProvider()).thenReturn(this.rp);
-
- src = new AuthenticatedResourceProvider(handler, false, resolveContext, securityTracker);
-
- }
-
- @Test
- public void create_success() throws PersistenceException {
-
- when(security.canCreate("/some/path", rr)).thenReturn(true);
-
- assertNotNull("expected resource to be created", src.create(rr, "/some/path", Collections.<String, Object> emptyMap()));
- }
-
- @Test
- public void create_failure() throws PersistenceException {
-
- when(security.canCreate("/some/path", rr)).thenReturn(false);
-
- assertNull("expected resource to not be created", src.create(rr, "/some/path", Collections.<String, Object> emptyMap()));
- }
-
- @Test
- public void delete_success() throws PersistenceException {
-
- Resource toDelete = mock(Resource.class);
-
- when(security.canDelete(toDelete)).thenReturn(true);
-
- src.delete(toDelete);
-
- verify(rp).delete(resolveContext, toDelete);
- }
-
- @Test
- public void delete_failure() throws PersistenceException {
-
- Resource toDelete = mock(Resource.class);
-
- when(security.canDelete(toDelete)).thenReturn(false);
-
- try {
- src.delete(toDelete);
- fail();
- } catch ( PersistenceException pe ) {
- // correct
- }
-
- Mockito.verifyZeroInteractions(rp);
- }
-
- @Test
- public void find() {
-
- Iterator<Resource> resources = src.findResources("FIND ALL", "MockQueryLanguage");
-
- assertThat("resources should contain at least one item", resources.hasNext(), equalTo(true));
-
- Resource resource = resources.next();
-
- assertThat("unexpected resource found", resource, equalTo(first));
-
- assertThat("resources should exactly at least one item", resources.hasNext(), equalTo(false));
- }
-}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/providers/tree/PathTreeTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/providers/tree/PathTreeTest.java
deleted file mode 100644
index 3a4fb21..0000000
--- a/src/test/java/org/apache/sling/resourceresolver/impl/providers/tree/PathTreeTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.resourceresolver.impl.providers.tree;
-
-import static java.util.Arrays.asList;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.nullValue;
-import static org.junit.Assert.assertThat;
-
-import org.hamcrest.Matchers;
-import org.junit.Before;
-import org.junit.Test;
-
-public class PathTreeTest {
-
- private PathTree<Pathable> tree;
-
- @Before
- public void createTree() {
-
- Pathable root = new StringPath("/");
- Pathable libs = new StringPath("/libs");
- Pathable libsSling = new StringPath("/libs/sling");
- Pathable apps = new StringPath("/apps");
-
- tree = new PathTree<Pathable>(asList(root, libs, libsSling, apps));
- }
-
- @Test
- public void bestMatchForChildNode() {
-
- assertPathHasBestMatch("/libs", "/libs");
- assertPathHasExactMatch("/libs");
- }
-
- private void assertPathHasBestMatch(String path, String expectedNode) {
-
- assertThat(tree.getBestMatchingNode(path).getValue().getPath(), equalTo(expectedNode));
- }
-
- private void assertPathHasExactMatch(String path) {
-
- assertThat(tree.getNode(path).getValue().getPath(), equalTo(path));
- }
-
- private void assertPathDoesNotHaveExactMatch(String path) {
-
- assertThat(tree.getNode(path), nullValue());
- }
-
- @Test
- public void bestMatchForChildNodeNested() {
-
- assertPathHasBestMatch("/apps/sling", "/apps");
- assertPathDoesNotHaveExactMatch("/apps/sling");
- }
-
- @Test
- public void bestMatchForChildNodeDeeplyNested() {
-
- assertPathHasBestMatch("/libs/sling/base/install", "/libs/sling");
- assertPathDoesNotHaveExactMatch("/libs/sling/base/install");
- }
-
- @Test
- public void bestMatchRootNodeFallback() {
-
- assertPathHasBestMatch("/system", "/");
- assertPathDoesNotHaveExactMatch("/system");
- }
-
- @Test
- public void bestMatchForInvalidPaths() {
-
- for ( String invalid : new String[] { null, "", "not/absolute/path"} ) {
- assertThat("getBestMatchingNode(" + invalid + ")", tree.getBestMatchingNode(invalid), Matchers.nullValue());
- assertThat("getNode(" + invalid + ")", tree.getNode(invalid), Matchers.nullValue());
- }
- }
-
- static class StringPath implements Pathable {
-
- private final String path;
-
- public StringPath(String path) {
- this.path = path;
- }
-
- @Override
- public String getPath() {
- return path;
- }
- }
-}
\ No newline at end of file
diff --git a/src/test/resources/test-project/explicit-excludes.pom.xml b/src/test/resources/test-project/explicit-excludes.pom.xml
new file mode 100644
index 0000000..4fb5fe7
--- /dev/null
+++ b/src/test/resources/test-project/explicit-excludes.pom.xml
@@ -0,0 +1,52 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.sling</groupId>
+ <artifactId>htl-maven-plugin-it-explicit-excludes</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>HTL Maven Plugin IT - Explicit excludes</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>htl-maven-plugin</artifactId>
+ <configuration>
+ <sourceDirectory>src/main/resources</sourceDirectory>
+ <!-- only script.html will be compiled -->
+ <excludes>
+ <exclude>**/exclude.html</exclude>
+ </excludes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>validate-scripts</id>
+ <goals>
+ <goal>validate</goal>
+ </goals>
+ <phase>compile</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/src/test/resources/test-project/explicit-includes.pom.xml b/src/test/resources/test-project/explicit-includes.pom.xml
new file mode 100644
index 0000000..9e073da
--- /dev/null
+++ b/src/test/resources/test-project/explicit-includes.pom.xml
@@ -0,0 +1,52 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.sling</groupId>
+ <artifactId>htl-maven-plugin-it-explicit-includes</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>HTL Maven Plugin IT - Explicit includes</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>htl-maven-plugin</artifactId>
+ <configuration>
+ <sourceDirectory>src/main/resources</sourceDirectory>
+ <!-- only *.sly files will be compiled -->
+ <includes>
+ <include>**/*.sly</include>
+ </includes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>validate-scripts</id>
+ <goals>
+ <goal>validate</goal>
+ </goals>
+ <phase>compile</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/src/test/resources/test-project/fail-on-warnings.pom.xml b/src/test/resources/test-project/fail-on-warnings.pom.xml
new file mode 100644
index 0000000..f207e65
--- /dev/null
+++ b/src/test/resources/test-project/fail-on-warnings.pom.xml
@@ -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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.sling</groupId>
+ <artifactId>htl-maven-plugin-it-fail-on-warnings</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>HTL Maven Plugin IT - Fail On Warnings</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>htl-maven-plugin</artifactId>
+ <configuration>
+ <sourceDirectory>src/main/resources</sourceDirectory>
+ <!-- only the warning.sly file will be compiled -->
+ <includes>
+ <include>**/warning.sly</include>
+ </includes>
+ <failOnWarnings>true</failOnWarnings>
+ </configuration>
+ <executions>
+ <execution>
+ <id>validate-scripts</id>
+ <goals>
+ <goal>validate</goal>
+ </goals>
+ <phase>compile</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/src/test/resources/test-project/src/main/resources/apps/projects/error.sly b/src/test/resources/test-project/src/main/resources/apps/projects/error.sly
new file mode 100644
index 0000000..ffe8613
--- /dev/null
+++ b/src/test/resources/test-project/src/main/resources/apps/projects/error.sly
@@ -0,0 +1,18 @@
+<!--/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->
+<!--/* Intentionally add a Sightly error here; this file should be compiled by the plugin and fail the build. */-->
+${expression.notClosed
diff --git a/src/test/resources/test-project/src/main/resources/apps/projects/exclude.html b/src/test/resources/test-project/src/main/resources/apps/projects/exclude.html
new file mode 100644
index 0000000..95d56d6
--- /dev/null
+++ b/src/test/resources/test-project/src/main/resources/apps/projects/exclude.html
@@ -0,0 +1,18 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<!--/* Intentionally add a Sightly error here; this file should not be compiled by the plugin. */-->
+${expression.notClosed
diff --git a/src/test/resources/test-project/src/main/resources/apps/projects/script.html b/src/test/resources/test-project/src/main/resources/apps/projects/script.html
new file mode 100644
index 0000000..5df9256
--- /dev/null
+++ b/src/test/resources/test-project/src/main/resources/apps/projects/script.html
@@ -0,0 +1,17 @@
+<!--/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->
+${this.is.an.expression @ i18n, locale='de'}
diff --git a/src/test/resources/test-project/src/main/resources/apps/projects/warning.sly b/src/test/resources/test-project/src/main/resources/apps/projects/warning.sly
new file mode 100644
index 0000000..fb79153
--- /dev/null
+++ b/src/test/resources/test-project/src/main/resources/apps/projects/warning.sly
@@ -0,0 +1,19 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<script>
+ var a = '${a}';
+</script>