You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by dk...@apache.org on 2020/10/21 21:34:31 UTC
[sling-org-apache-sling-jcr-contentloader] branch
SLING-9841-jcr-contentloader-include-exclude created (now 0298cdf)
This is an automated email from the ASF dual-hosted git repository.
dklco pushed a change to branch SLING-9841-jcr-contentloader-include-exclude
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-contentloader.git.
at 0298cdf SLING-9841 - Added support for filtering installs based on the target path and renamed the ContentLoaderService since only handles bundles and isn't a service
This branch includes the following new commits:
new 0298cdf SLING-9841 - Added support for filtering installs based on the target path and renamed the ContentLoaderService since only handles bundles and isn't a service
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
[sling-org-apache-sling-jcr-contentloader] 01/01: SLING-9841 -
Added support for filtering installs based on the target path and renamed
the ContentLoaderService since only handles bundles and isn't a service
Posted by dk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dklco pushed a commit to branch SLING-9841-jcr-contentloader-include-exclude
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-contentloader.git
commit 0298cdf1c20cc80b606f40f108131c7e0fe576f1
Author: Dan Klco <dk...@apache.org>
AuthorDate: Wed Oct 21 17:34:11 2020 -0400
SLING-9841 - Added support for filtering installs based on the target path and renamed the ContentLoaderService since only handles bundles and isn't a service
---
.../contentloader/hc/BundleContentLoadedCheck.java | 8 +-
.../internal/BundleContentLoader.java | 131 +++++++++++++-----
.../internal/BundleContentLoaderConfiguration.java | 32 +++++
...rvice.java => BundleContentLoaderListener.java} | 148 ++++++++++-----------
src/main/resources/OSGI-INF/l10n/bundle.properties | 33 +++++
...t.java => BundleContentLoaderListenerTest.java} | 32 ++---
.../internal/BundleContentLoaderTest.java | 124 +++++++++++++++--
7 files changed, 359 insertions(+), 149 deletions(-)
diff --git a/src/main/java/org/apache/sling/jcr/contentloader/hc/BundleContentLoadedCheck.java b/src/main/java/org/apache/sling/jcr/contentloader/hc/BundleContentLoadedCheck.java
index 2fe432b..a4d1584 100644
--- a/src/main/java/org/apache/sling/jcr/contentloader/hc/BundleContentLoadedCheck.java
+++ b/src/main/java/org/apache/sling/jcr/contentloader/hc/BundleContentLoadedCheck.java
@@ -31,7 +31,7 @@ import org.apache.felix.hc.api.HealthCheck;
import org.apache.felix.hc.api.Result;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.contentloader.internal.BundleHelper;
-import org.apache.sling.jcr.contentloader.internal.ContentLoaderService;
+import org.apache.sling.jcr.contentloader.internal.BundleContentLoaderListener;
import org.apache.sling.jcr.contentloader.internal.PathEntry;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -117,7 +117,7 @@ public class BundleContentLoadedCheck implements HealthCheck {
try {
metadataSession = repository.loginService(null, null);
- BundleHelper bundleHelper = new ContentLoaderService();
+ BundleHelper bundleHelper = new BundleContentLoaderListener();
for (Bundle bundle : bundles) {
String bundleSymbolicName = bundle.getSymbolicName();
@@ -155,9 +155,9 @@ public class BundleContentLoadedCheck implements HealthCheck {
}
} else {
try {
- final boolean contentAlreadyLoaded = ((Boolean) bundleContentInfo.get(ContentLoaderService.PROPERTY_CONTENT_LOADED)).booleanValue();
+ final boolean contentAlreadyLoaded = ((Boolean) bundleContentInfo.get(BundleContentLoaderListener.PROPERTY_CONTENT_LOADED)).booleanValue();
boolean isBundleUpdated = false;
- Calendar lastLoadedAt = (Calendar) bundleContentInfo.get(ContentLoaderService.PROPERTY_CONTENT_LOADED_AT);
+ Calendar lastLoadedAt = (Calendar) bundleContentInfo.get(BundleContentLoaderListener.PROPERTY_CONTENT_LOADED_AT);
if (lastLoadedAt != null && lastLoadedAt.getTimeInMillis() < bundle.getLastModified()) {
isBundleUpdated = true;
}
diff --git a/src/main/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoader.java b/src/main/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoader.java
index 84dbeb6..7740765 100644
--- a/src/main/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoader.java
+++ b/src/main/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoader.java
@@ -25,6 +25,7 @@ import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Enumeration;
@@ -33,7 +34,12 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
import java.util.StringTokenizer;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import javax.jcr.Item;
import javax.jcr.NoSuchWorkspaceException;
@@ -62,10 +68,31 @@ public class BundleContentLoader extends BaseImportLoader {
// bundles whose registration failed and should be retried
private List<Bundle> delayedBundles;
- public BundleContentLoader(BundleHelper bundleHelper, ContentReaderWhiteboard contentReaderWhiteboard) {
+ private final Predicate<String> pathFilter;
+
+ public BundleContentLoader(BundleHelper bundleHelper, ContentReaderWhiteboard contentReaderWhiteboard,
+ BundleContentLoaderConfiguration configuration) {
super(contentReaderWhiteboard);
this.bundleHelper = bundleHelper;
this.delayedBundles = new LinkedList<>();
+
+ List<Pattern> includes = Arrays
+ .stream(Optional.ofNullable(configuration).map(BundleContentLoaderConfiguration::includedTargets)
+ .orElse(new String[0]))
+ .filter(Objects::nonNull).map(Pattern::compile).collect(Collectors.toList());
+ List<Pattern> excludes = Arrays
+ .stream(Optional.ofNullable(configuration).map(BundleContentLoaderConfiguration::excludedTargets)
+ .orElse(new String[0]))
+ .filter(Objects::nonNull).map(Pattern::compile).collect(Collectors.toList());
+ this.pathFilter = path -> {
+ if (configuration == null || path == null) {
+ return true;
+ } else {
+ return includes.stream().anyMatch(p -> p.matcher(path).matches())
+ && excludes.stream().noneMatch(p -> p.matcher(path).matches());
+ }
+ };
+ log.debug("Using includes: {} and excludes: {}", includes, excludes);
}
public void dispose() {
@@ -95,8 +122,9 @@ public class BundleContentLoader extends BaseImportLoader {
if (registerBundleInternal(metadataSession, bundle, false, isUpdate)) {
// handle delayed bundles, might help now
int currentSize = -1;
- for (int i = delayedBundles.size(); i > 0 && currentSize != delayedBundles.size() && !delayedBundles.isEmpty(); i--) {
- for (Iterator<Bundle> di = delayedBundles.iterator(); di.hasNext(); ) {
+ for (int i = delayedBundles.size(); i > 0 && currentSize != delayedBundles.size()
+ && !delayedBundles.isEmpty(); i--) {
+ for (Iterator<Bundle> di = delayedBundles.iterator(); di.hasNext();) {
Bundle delayed = di.next();
if (registerBundleInternal(metadataSession, delayed, true, false)) {
di.remove();
@@ -110,7 +138,8 @@ public class BundleContentLoader extends BaseImportLoader {
}
}
- private boolean registerBundleInternal(final Session metadataSession, final Bundle bundle, final boolean isRetry, final boolean isUpdate) {
+ private boolean registerBundleInternal(final Session metadataSession, final Bundle bundle, final boolean isRetry,
+ final boolean isUpdate) {
// check if bundle has initial content
final Iterator<PathEntry> pathIter = PathEntry.getContentPaths(bundle);
@@ -120,10 +149,11 @@ public class BundleContentLoader extends BaseImportLoader {
}
try {
- bundleHelper.createRepositoryPath(metadataSession, ContentLoaderService.BUNDLE_CONTENT_NODE);
+ bundleHelper.createRepositoryPath(metadataSession, BundleContentLoaderListener.BUNDLE_CONTENT_NODE);
// check if the content has already been loaded
- final Map<String, Object> bundleContentInfo = bundleHelper.getBundleContentInfo(metadataSession, bundle, true);
+ final Map<String, Object> bundleContentInfo = bundleHelper.getBundleContentInfo(metadataSession, bundle,
+ true);
// if we don't get an info, someone else is currently loading
if (bundleContentInfo == null) {
@@ -133,16 +163,19 @@ public class BundleContentLoader extends BaseImportLoader {
boolean success = false;
List<String> createdNodes = null;
try {
- final boolean contentAlreadyLoaded = ((Boolean) bundleContentInfo.get(ContentLoaderService.PROPERTY_CONTENT_LOADED)).booleanValue();
+ final boolean contentAlreadyLoaded = ((Boolean) bundleContentInfo
+ .get(BundleContentLoaderListener.PROPERTY_CONTENT_LOADED)).booleanValue();
boolean isBundleUpdated = false;
- Calendar lastLoadedAt = (Calendar) bundleContentInfo.get(ContentLoaderService.PROPERTY_CONTENT_LOADED_AT);
+ Calendar lastLoadedAt = (Calendar) bundleContentInfo
+ .get(BundleContentLoaderListener.PROPERTY_CONTENT_LOADED_AT);
if (lastLoadedAt != null && lastLoadedAt.getTimeInMillis() < bundle.getLastModified()) {
isBundleUpdated = true;
}
if (!isUpdate && !isBundleUpdated && contentAlreadyLoaded) {
log.info("Content of bundle already loaded {}.", bundle.getSymbolicName());
} else {
- createdNodes = installContent(metadataSession, bundle, pathIter, contentAlreadyLoaded && !isBundleUpdated);
+ createdNodes = installContent(metadataSession, bundle, pathIter,
+ contentAlreadyLoaded && !isBundleUpdated);
if (isRetry) {
// log success of retry
log.info("Retrying to load initial content for bundle {} succeeded.", bundle.getSymbolicName());
@@ -159,7 +192,9 @@ public class BundleContentLoader extends BaseImportLoader {
// if we are retrying we already logged this message once, so we
// won't log it again
if (!isRetry) {
- log.error("Cannot load initial content for bundle " + bundle.getSymbolicName() + " : " + re.getMessage(), re);
+ log.error(
+ "Cannot load initial content for bundle " + bundle.getSymbolicName() + " : " + re.getMessage(),
+ re);
}
}
return false;
@@ -176,7 +211,7 @@ public class BundleContentLoader extends BaseImportLoader {
delayedBundles.remove(bundle);
} else {
try {
- bundleHelper.createRepositoryPath(session, ContentLoaderService.BUNDLE_CONTENT_NODE);
+ bundleHelper.createRepositoryPath(session, BundleContentLoaderListener.BUNDLE_CONTENT_NODE);
final Map<String, Object> bundleContentInfo = bundleHelper.getBundleContentInfo(session, bundle, false);
@@ -187,13 +222,15 @@ public class BundleContentLoader extends BaseImportLoader {
}
try {
- uninstallContent(session, bundle, (String[]) bundleContentInfo.get(ContentLoaderService.PROPERTY_UNINSTALL_PATHS));
+ uninstallContent(session, bundle,
+ (String[]) bundleContentInfo.get(BundleContentLoaderListener.PROPERTY_UNINSTALL_PATHS));
bundleHelper.contentIsUninstalled(session, bundle);
} finally {
bundleHelper.unlockBundleContentInfo(session, bundle, false, null);
}
} catch (RepositoryException re) {
- log.error("Cannot remove initial content for bundle " + bundle.getSymbolicName() + " : " + re.getMessage(), re);
+ log.error("Cannot remove initial content for bundle " + bundle.getSymbolicName() + " : "
+ + re.getMessage(), re);
}
}
}
@@ -205,7 +242,8 @@ public class BundleContentLoader extends BaseImportLoader {
*
* @return If the content should be removed on uninstall, a list of top nodes
*/
- private List<String> installContent(final Session defaultSession, final Bundle bundle, final Iterator<PathEntry> pathIter, final boolean contentAlreadyLoaded) throws RepositoryException {
+ private List<String> installContent(final Session defaultSession, final Bundle bundle,
+ final Iterator<PathEntry> pathIter, final boolean contentAlreadyLoaded) throws RepositoryException {
final List<String> createdNodes = new ArrayList<>();
final Map<String, Session> createdSessions = new HashMap<>();
@@ -215,6 +253,12 @@ public class BundleContentLoader extends BaseImportLoader {
try {
while (pathIter.hasNext()) {
final PathEntry pathEntry = pathIter.next();
+
+ if (!pathFilter.test(pathEntry.getTarget())) {
+ log.debug("Path {} excluded by configuration", pathEntry.getPath());
+ continue;
+ }
+
if (!contentAlreadyLoaded || pathEntry.isOverwrite()) {
String workspace = pathEntry.getWorkspace();
final Session targetSession;
@@ -232,7 +276,8 @@ public class BundleContentLoader extends BaseImportLoader {
final Node targetNode = getTargetNode(targetSession, pathEntry.getTarget());
if (targetNode != null) {
- installFromPath(bundle, pathEntry.getPath(), pathEntry, targetNode, pathEntry.isUninstall() ? createdNodes : null, contentCreator);
+ installFromPath(bundle, pathEntry.getPath(), pathEntry, targetNode,
+ pathEntry.isUninstall() ? createdNodes : null, contentCreator);
}
}
}
@@ -263,8 +308,8 @@ public class BundleContentLoader extends BaseImportLoader {
// finally check in versionable nodes
for (final Node versionable : contentCreator.getVersionables()) {
- VersionManager versionManager = versionable.getSession().getWorkspace().getVersionManager();
- versionManager.checkin(versionable.getPath());
+ VersionManager versionManager = versionable.getSession().getWorkspace().getVersionManager();
+ versionManager.checkin(versionable.getPath());
}
} finally {
try {
@@ -296,12 +341,15 @@ public class BundleContentLoader extends BaseImportLoader {
* @param path The path
* @param configuration
* @param parent The parent node.
- * @param createdNodes An optional list to store all new nodes. This list is used for an uninstall
+ * @param createdNodes An optional list to store all new nodes. This list is
+ * used for an uninstall
* @throws RepositoryException
*/
- private void installFromPath(final Bundle bundle, final String path, final PathEntry configuration, final Node parent, final List<String> createdNodes, final DefaultContentCreator contentCreator) throws RepositoryException {
+ private void installFromPath(final Bundle bundle, final String path, final PathEntry configuration,
+ final Node parent, final List<String> createdNodes, final DefaultContentCreator contentCreator)
+ throws RepositoryException {
- // init content creator
+ // init content creator
contentCreator.init(configuration, getContentReaders(), createdNodes, null);
final Map<String, Node> processedEntries = new HashMap<>();
@@ -314,7 +362,8 @@ public class BundleContentLoader extends BaseImportLoader {
log.info("install: No initial content entries at {} in bundle {}", path, bundle.getSymbolicName());
return;
}
- // we have a single file content, let's check if this has an content reader extension
+ // we have a single file content, let's check if this has an content reader
+ // extension
for (String ext : contentCreator.getContentReaders().keySet()) {
if (path.endsWith(ext)) {
@@ -384,7 +433,9 @@ public class BundleContentLoader extends BaseImportLoader {
* @param createdNodes
* @throws RepositoryException
*/
- private void handleFile(final String entry, final Bundle bundle, final Map<String, Node> processedEntries, final PathEntry configuration, final Node parent, final List<String> createdNodes, final DefaultContentCreator contentCreator) throws RepositoryException {
+ private void handleFile(final String entry, final Bundle bundle, final Map<String, Node> processedEntries,
+ final PathEntry configuration, final Node parent, final List<String> createdNodes,
+ final DefaultContentCreator contentCreator) throws RepositoryException {
final URL file = bundle.getEntry(entry);
final String name = getName(entry);
@@ -456,8 +507,8 @@ public class BundleContentLoader extends BaseImportLoader {
* @return
* @throws RepositoryException
*/
- private Node createNode(Node parent, String name, URL resourceUrl, final DefaultContentCreator contentCreator, PathEntry configuration)
- throws RepositoryException {
+ private Node createNode(Node parent, String name, URL resourceUrl, final DefaultContentCreator contentCreator,
+ PathEntry configuration) throws RepositoryException {
final String resourcePath = resourceUrl.getPath().toLowerCase();
InputStream contentStream = null;
@@ -523,7 +574,8 @@ public class BundleContentLoader extends BaseImportLoader {
* @throws IOException
* @throws RepositoryException
*/
- private void createFile(PathEntry configuration, Node parent, URL source, List<String> createdNodes, final DefaultContentCreator contentCreator) throws IOException, RepositoryException {
+ private void createFile(PathEntry configuration, Node parent, URL source, List<String> createdNodes,
+ final DefaultContentCreator contentCreator) throws IOException, RepositoryException {
final String srcPath = source.getPath();
int pos = srcPath.lastIndexOf('/');
@@ -547,12 +599,12 @@ public class BundleContentLoader extends BaseImportLoader {
}
/**
- * Gets and decodes the name part of the <code>path</code>. The name is
- * the part of the path after the last slash (or the complete path if no
- * slash is contained). To support names containing unsupported characters
- * such as colon (<code>:</code>), names may be URL encoded (see
- * <code>java.net.URLEncoder</code>) using the <i>UTF-8</i> character
- * encoding. In this case, this method decodes the name using the
+ * Gets and decodes the name part of the <code>path</code>. The name is the part
+ * of the path after the last slash (or the complete path if no slash is
+ * contained). To support names containing unsupported characters such as colon
+ * (<code>:</code>), names may be URL encoded (see
+ * <code>java.net.URLEncoder</code>) using the <i>UTF-8</i> character encoding.
+ * In this case, this method decodes the name using the
* <code>java.net.URLDecoder</code> class with the <i>UTF-8</i> character
* encoding.
*
@@ -618,6 +670,10 @@ public class BundleContentLoader extends BaseImportLoader {
log.debug("Uninstalling initial content from bundle {}", bundle.getSymbolicName());
if (uninstallPaths != null && uninstallPaths.length > 0) {
for (String path : uninstallPaths) {
+ if (!pathFilter.test(path)) {
+ log.debug("Path {} excluded by configuration", path);
+ continue;
+ }
final Session targetSession;
final int wsSepPos = path.indexOf(":/");
@@ -662,7 +718,8 @@ public class BundleContentLoader extends BaseImportLoader {
}
}
} catch (RepositoryException re) {
- log.warn("Failure to rollback uninstalling initial content for bundle {}", bundle.getSymbolicName(), re);
+ log.warn("Failure to rollback uninstalling initial content for bundle {}", bundle.getSymbolicName(),
+ re);
}
for (Session session : createdSessions.values()) {
@@ -682,7 +739,8 @@ public class BundleContentLoader extends BaseImportLoader {
/**
* Return the parent node descriptor (ROOT).
*/
- private Descriptor getParentNodeDescriptor(final Bundle bundle, final String path, final DefaultContentCreator contentCreator) {
+ private Descriptor getParentNodeDescriptor(final Bundle bundle, final String path,
+ final DefaultContentCreator contentCreator) {
for (Map.Entry<String, ContentReader> entry : contentCreator.getContentReaders().entrySet()) {
if (entry.getValue() != null) {
@@ -706,10 +764,11 @@ public class BundleContentLoader extends BaseImportLoader {
}
/**
- * Imports mixin nodes and properties (and optionally child nodes) of the
- * parent node.
+ * Imports mixin nodes and properties (and optionally child nodes) of the parent
+ * node.
*/
- private URL importParentNode(Bundle bundle, String path, Node parent, final DefaultContentCreator contentCreator) throws RepositoryException {
+ private URL importParentNode(Bundle bundle, String path, Node parent, final DefaultContentCreator contentCreator)
+ throws RepositoryException {
final Descriptor descriptor = getParentNodeDescriptor(bundle, path, contentCreator);
// no parent descriptor (ROOT) found
diff --git a/src/main/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderConfiguration.java b/src/main/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderConfiguration.java
new file mode 100644
index 0000000..1302778
--- /dev/null
+++ b/src/main/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderConfiguration.java
@@ -0,0 +1,32 @@
+/*
+ * 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.jcr.contentloader.internal;
+
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+@ObjectClassDefinition(name = "%contentloader.config.name", description = "%contentloader.config.description", localization = "OSGI-INF/l10n/bundle")
+public @interface BundleContentLoaderConfiguration {
+
+ @AttributeDefinition(name = "%includedTargets.name", description = "%includedTargets.description")
+ String[] includedTargets() default { "^\\/.*$" };
+
+ @AttributeDefinition(name = "%excludedTargets.name", description = "%excludedTargets.description")
+ String[] excludedTargets() default {};
+}
diff --git a/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java b/src/main/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderListener.java
similarity index 76%
rename from src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
rename to src/main/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderListener.java
index d68d605..b671133 100644
--- a/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
+++ b/src/main/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderListener.java
@@ -43,25 +43,26 @@ import org.osgi.framework.Constants;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * The <code>ContentLoaderService</code> is the service
- * providing the following functionality:
+ * The <code>BundleContentLoaderListener</code> is the service providing the
+ * following functionality:
* <ul>
* <li>Bundle listener to load and unload initial content.
* </ul>
*
*/
-@Component(service = {},
- property = {
- Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
- Constants.SERVICE_DESCRIPTION + "=Apache Sling Content Loader Implementation"
- })
-public class ContentLoaderService implements SynchronousBundleListener, BundleHelper {
+@Component(service = {}, property = { Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
+ Constants.SERVICE_DESCRIPTION
+ + "=Apache Sling Content Loader Implementation" }, configurationPolicy = ConfigurationPolicy.OPTIONAL)
+@Designate(ocd = BundleContentLoaderConfiguration.class, factory = false)
+public class BundleContentLoaderListener implements SynchronousBundleListener, BundleHelper {
public static final String PROPERTY_CONTENT_LOADED = "content-loaded";
public static final String PROPERTY_CONTENT_LOADED_AT = "content-load-time";
@@ -82,8 +83,8 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
private SlingRepository repository;
/**
- * The MimeTypeService used by the bundle content loader to
- * resolve MIME types for files to be installed.
+ * The MimeTypeService used by the bundle content loader to resolve MIME types
+ * for files to be installed.
*/
@Reference
private MimeTypeService mimeTypeService;
@@ -95,8 +96,8 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
private ContentReaderWhiteboard contentReaderWhiteboard;
/**
- * The initial content loader which is called to load initial content up
- * into the repository when the providing bundle is installed.
+ * The initial content loader which is called to load initial content up into
+ * the repository when the providing bundle is installed.
*/
private BundleContentLoader bundleContentLoader;
@@ -117,12 +118,12 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
// ---------- BundleListener -----------------------------------------------
/**
- * Loads and unloads any content provided by the bundle whose state
- * changed. If the bundle has been started, the content is loaded. If
- * the bundle is about to stop, the content are unloaded.
+ * Loads and unloads any content provided by the bundle whose state changed. If
+ * the bundle has been started, the content is loaded. If the bundle is about to
+ * stop, the content are unloaded.
*
* @param event The <code>BundleEvent</code> representing the bundle state
- * change.
+ * change.
*/
@Override
public synchronized void bundleChanged(BundleEvent event) {
@@ -149,10 +150,8 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
isUpdate = this.updatedBundles.remove(bundle.getSymbolicName());
bundleContentLoader.registerBundle(session, bundle, isUpdate);
} catch (Exception t) {
- log.error(
- "bundleChanged: Problem loading initial content of bundle "
- + bundle.getSymbolicName() + " ("
- + bundle.getBundleId() + ")", t);
+ log.error("bundleChanged: Problem loading initial content of bundle " + bundle.getSymbolicName()
+ + " (" + bundle.getBundleId() + ")", t);
} finally {
this.ungetSession(session);
}
@@ -167,10 +166,8 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
session = this.getSession();
bundleContentLoader.unregisterBundle(session, bundle);
} catch (Exception t) {
- log.error(
- "bundleChanged: Problem unloading initial content of bundle "
- + bundle.getSymbolicName() + " ("
- + bundle.getBundleId() + ")", t);
+ log.error("bundleChanged: Problem unloading initial content of bundle " + bundle.getSymbolicName()
+ + " (" + bundle.getBundleId() + ")", t);
} finally {
this.ungetSession(session);
}
@@ -192,16 +189,16 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
@Override
public void createRepositoryPath(final Session writerSession, final String repositoryPath)
- throws RepositoryException {
- if ( !writerSession.itemExists(repositoryPath) ) {
+ throws RepositoryException {
+ if (!writerSession.itemExists(repositoryPath)) {
Node node = writerSession.getRootNode();
String path = repositoryPath.substring(1);
int pos = path.lastIndexOf('/');
- if ( pos != -1 ) {
+ if (pos != -1) {
final StringTokenizer st = new StringTokenizer(path.substring(0, pos), "/");
- while ( st.hasMoreTokens() ) {
+ while (st.hasMoreTokens()) {
final String token = st.nextToken();
- if ( !node.hasNode(token) ) {
+ if (!node.hasNode(token)) {
node.addNode(token, "sling:Folder");
writerSession.save();
}
@@ -209,7 +206,7 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
}
path = path.substring(pos + 1);
}
- if ( !node.hasNode(path) ) {
+ if (!node.hasNode(path)) {
node.addNode(path, "sling:Folder");
writerSession.save();
}
@@ -220,9 +217,9 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
/** Activates this component, called by SCR before registering as a service */
@Activate
- protected synchronized void activate(BundleContext bundleContext) {
+ protected synchronized void activate(BundleContext bundleContext, BundleContentLoaderConfiguration configuration) {
this.slingId = this.settingsService.getSlingId();
- this.bundleContentLoader = new BundleContentLoader(this, contentReaderWhiteboard);
+ this.bundleContentLoader = new BundleContentLoader(this, contentReaderWhiteboard, configuration);
bundleContext.addBundleListener(this);
@@ -230,8 +227,7 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
try {
session = this.getSession();
this.createRepositoryPath(session, BUNDLE_CONTENT_NODE);
- log.debug(
- "Activated - attempting to load content from all "
+ log.debug("Activated - attempting to load content from all "
+ "bundles which are neither INSTALLED nor UNINSTALLED");
int ignored = 0;
@@ -247,29 +243,25 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
}
- log.debug(
- "Out of {} bundles, {} were not in a suitable state for initial content loading",
- bundles.length, ignored
- );
+ log.debug("Out of {} bundles, {} were not in a suitable state for initial content loading", bundles.length,
+ ignored);
} catch (Exception t) {
log.error("activate: Problem while loading initial content and"
- + " registering mappings for existing bundles", t);
+ + " registering mappings for existing bundles", t);
} finally {
this.ungetSession(session);
}
}
-
+
private void loadBundle(Bundle bundle, Session session) throws RepositoryException {
try {
bundleContentLoader.registerBundle(session, bundle, false);
} catch (Exception t) {
- log.error(
- "Problem loading initial content of bundle "
- + bundle.getSymbolicName() + " ("
+ log.error("Problem loading initial content of bundle " + bundle.getSymbolicName() + " ("
+ bundle.getBundleId() + ")", t);
} finally {
- if ( session.hasPendingChanges() ) {
+ if (session.hasPendingChanges()) {
session.refresh(false);
}
}
@@ -280,7 +272,7 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
protected synchronized void deactivate(BundleContext bundleContext) {
bundleContext.removeBundleListener(this);
- if ( this.bundleContentLoader != null ) {
+ if (this.bundleContentLoader != null) {
this.bundleContentLoader.dispose();
this.bundleContentLoader = null;
}
@@ -297,8 +289,7 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
* Returns an administrative session to the default workspace.
*/
@Override
- public Session getSession()
- throws RepositoryException {
+ public Session getSession() throws RepositoryException {
return getRepository().loginService(null, null);
}
@@ -314,7 +305,7 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
* Return the administrative session and close it.
*/
private void ungetSession(final Session session) {
- if ( session != null ) {
+ if (session != null) {
try {
session.logout();
} catch (Exception t) {
@@ -325,6 +316,7 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
/**
* Return the bundle content info and make an exclusive lock.
+ *
* @param session
* @param bundle
* @return The map of bundle content info or null.
@@ -332,11 +324,11 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
*/
@Override
public Map<String, Object> getBundleContentInfo(final Session session, final Bundle bundle, boolean create)
- throws RepositoryException {
+ throws RepositoryException {
final String nodeName = bundle.getSymbolicName();
- final Node parentNode = (Node)session.getItem(BUNDLE_CONTENT_NODE);
- if ( !parentNode.hasNode(nodeName) ) {
- if ( !create ) {
+ final Node parentNode = (Node) session.getItem(BUNDLE_CONTENT_NODE);
+ if (!parentNode.hasNode(nodeName)) {
+ if (!create) {
return null;
}
try {
@@ -350,33 +342,31 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
}
}
final Node bcNode = parentNode.getNode(nodeName);
- if ( bcNode.isLocked() ) {
+ if (bcNode.isLocked()) {
return null;
}
try {
- LockManager lockManager = session.getWorkspace().getLockManager();
- lockManager.lock(bcNode.getPath(),
- false, // isDeep
- true, // isSessionScoped
- Long.MAX_VALUE, // timeoutHint
- null); // ownerInfo
+ LockManager lockManager = session.getWorkspace().getLockManager();
+ lockManager.lock(bcNode.getPath(), false, // isDeep
+ true, // isSessionScoped
+ Long.MAX_VALUE, // timeoutHint
+ null); // ownerInfo
} catch (LockException le) {
return null;
}
final Map<String, Object> info = new HashMap<>();
- if ( bcNode.hasProperty(PROPERTY_CONTENT_LOADED_AT)) {
+ if (bcNode.hasProperty(PROPERTY_CONTENT_LOADED_AT)) {
info.put(PROPERTY_CONTENT_LOADED_AT, bcNode.getProperty(PROPERTY_CONTENT_LOADED_AT).getDate());
}
- if ( bcNode.hasProperty(PROPERTY_CONTENT_LOADED) ) {
- info.put(PROPERTY_CONTENT_LOADED,
- bcNode.getProperty(PROPERTY_CONTENT_LOADED).getBoolean());
+ if (bcNode.hasProperty(PROPERTY_CONTENT_LOADED)) {
+ info.put(PROPERTY_CONTENT_LOADED, bcNode.getProperty(PROPERTY_CONTENT_LOADED).getBoolean());
} else {
info.put(PROPERTY_CONTENT_LOADED, false);
}
- if ( bcNode.hasProperty(PROPERTY_UNINSTALL_PATHS) ) {
+ if (bcNode.hasProperty(PROPERTY_UNINSTALL_PATHS)) {
final Value[] values = bcNode.getProperty(PROPERTY_UNINSTALL_PATHS).getValues();
final String[] s = new String[values.length];
- for(int i=0; i<values.length; i++) {
+ for (int i = 0; i < values.length; i++) {
s[i] = values[i].getString();
}
info.put(PROPERTY_UNINSTALL_PATHS, s);
@@ -385,41 +375,37 @@ public class ContentLoaderService implements SynchronousBundleListener, BundleHe
}
@Override
- public void unlockBundleContentInfo(final Session session,
- final Bundle bundle,
- final boolean contentLoaded,
- final List<String> createdNodes)
- throws RepositoryException {
+ public void unlockBundleContentInfo(final Session session, final Bundle bundle, final boolean contentLoaded,
+ final List<String> createdNodes) throws RepositoryException {
final String nodeName = bundle.getSymbolicName();
- final Node parentNode = (Node)session.getItem(BUNDLE_CONTENT_NODE);
+ final Node parentNode = (Node) session.getItem(BUNDLE_CONTENT_NODE);
final Node bcNode = parentNode.getNode(nodeName);
- if ( contentLoaded ) {
+ if (contentLoaded) {
bcNode.setProperty(PROPERTY_CONTENT_LOADED, contentLoaded);
bcNode.setProperty(PROPERTY_CONTENT_LOADED_AT, Calendar.getInstance());
bcNode.setProperty(PROPERTY_CONTENT_LOADED_BY, this.slingId);
- bcNode.setProperty(PROPERTY_CONTENT_UNLOADED_AT, (String)null);
- bcNode.setProperty(PROPERTY_CONTENT_UNLOADED_BY, (String)null);
- if ( createdNodes != null && !createdNodes.isEmpty() ) {
+ bcNode.setProperty(PROPERTY_CONTENT_UNLOADED_AT, (String) null);
+ bcNode.setProperty(PROPERTY_CONTENT_UNLOADED_BY, (String) null);
+ if (createdNodes != null && !createdNodes.isEmpty()) {
bcNode.setProperty(PROPERTY_UNINSTALL_PATHS, createdNodes.toArray(new String[createdNodes.size()]));
}
session.save();
}
LockManager lockManager = session.getWorkspace().getLockManager();
- lockManager.unlock(bcNode.getPath());
+ lockManager.unlock(bcNode.getPath());
}
@Override
- public void contentIsUninstalled(final Session session,
- final Bundle bundle) {
+ public void contentIsUninstalled(final Session session, final Bundle bundle) {
final String nodeName = bundle.getSymbolicName();
try {
- final Node parentNode = (Node)session.getItem(BUNDLE_CONTENT_NODE);
- if ( parentNode.hasNode(nodeName) ) {
+ final Node parentNode = (Node) session.getItem(BUNDLE_CONTENT_NODE);
+ if (parentNode.hasNode(nodeName)) {
final Node bcNode = parentNode.getNode(nodeName);
bcNode.setProperty(PROPERTY_CONTENT_LOADED, false);
bcNode.setProperty(PROPERTY_CONTENT_UNLOADED_AT, Calendar.getInstance());
bcNode.setProperty(PROPERTY_CONTENT_UNLOADED_BY, this.slingId);
- bcNode.setProperty(PROPERTY_UNINSTALL_PATHS, (String[])null);
+ bcNode.setProperty(PROPERTY_UNINSTALL_PATHS, (String[]) null);
session.save();
}
} catch (RepositoryException re) {
diff --git a/src/main/resources/OSGI-INF/l10n/bundle.properties b/src/main/resources/OSGI-INF/l10n/bundle.properties
new file mode 100644
index 0000000..ead6b55
--- /dev/null
+++ b/src/main/resources/OSGI-INF/l10n/bundle.properties
@@ -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.
+#
+
+# This file contains localization strings for configuration labels and
+# descriptions as used in the metatype.xml descriptor generated by the
+# the Sling SCR plugin
+
+contentloader.config.name=Apache Sling JCR ContentLoader - Bundle Content Loader
+contentloader.config.description=Configure the path handling of the JCR ContentLoader Bundle Content Loader
+
+includedTargets.name=Included Targets
+includedTargets.description=An array of regular expressions for the Path Entry targets to include when installing content \
+will be evaluated first
+
+excludedTargets.name=Excluded Targets
+excludedTargets.description=An array of regular expressions for the Path Entry targets to exclude when installing content \
+will be evaluated after include
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderServiceTest.java b/src/test/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderListenerTest.java
similarity index 83%
rename from src/test/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderServiceTest.java
rename to src/test/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderListenerTest.java
index 2db48d5..0bdef08 100644
--- a/src/test/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderServiceTest.java
+++ b/src/test/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderListenerTest.java
@@ -18,10 +18,10 @@
*/
package org.apache.sling.jcr.contentloader.internal;
-import static org.apache.sling.jcr.contentloader.internal.ContentLoaderService.BUNDLE_CONTENT_NODE;
-import static org.apache.sling.jcr.contentloader.internal.ContentLoaderService.PROPERTY_CONTENT_LOADED;
-import static org.apache.sling.jcr.contentloader.internal.ContentLoaderService.PROPERTY_CONTENT_LOADED_AT;
-import static org.apache.sling.jcr.contentloader.internal.ContentLoaderService.PROPERTY_UNINSTALL_PATHS;
+import static org.apache.sling.jcr.contentloader.internal.BundleContentLoaderListener.BUNDLE_CONTENT_NODE;
+import static org.apache.sling.jcr.contentloader.internal.BundleContentLoaderListener.PROPERTY_CONTENT_LOADED;
+import static org.apache.sling.jcr.contentloader.internal.BundleContentLoaderListener.PROPERTY_CONTENT_LOADED_AT;
+import static org.apache.sling.jcr.contentloader.internal.BundleContentLoaderListener.PROPERTY_UNINSTALL_PATHS;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -53,7 +53,7 @@ import org.osgi.framework.BundleEvent;
import junitx.util.PrivateAccessor;
-public class ContentLoaderServiceTest {
+public class BundleContentLoaderListenerTest {
@Rule
public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
@@ -61,7 +61,7 @@ public class ContentLoaderServiceTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
- private ContentLoaderService underTest;
+ private BundleContentLoaderListener underTest;
private BundleContentLoader contentLoader;
private Session session;
@@ -73,13 +73,13 @@ public class ContentLoaderServiceTest {
session = context.resourceResolver().adaptTo(Session.class);
// register the content loader service
- underTest = context.registerInjectActivateService(new ContentLoaderService());
+ underTest = context.registerInjectActivateService(new BundleContentLoaderListener());
contentLoader = (BundleContentLoader) PrivateAccessor.getField(underTest, "bundleContentLoader");
}
- //-------ContentLoaderService#bundleChanged(BundleEvent)-------//
+ //-------BundleContentLoaderListener#bundleChanged(BundleEvent)-------//
//I'm not very sure how to test this method, it looks like side effect of this method goes very deep
- //And more affects BundleContentLoader than ContentLoaderService
+ //And more affects BundleContentLoader than BundleContentLoaderListener
@Test
public void testBundleResolvedBundleChanged() throws NoSuchFieldException, RepositoryException {
@@ -103,12 +103,12 @@ public class ContentLoaderServiceTest {
underTest.bundleChanged(new BundleEvent(BundleEvent.UNINSTALLED, bundle));
}
- //-------ContentLoaderService#bundleChanged(BundleEvent)-------//
+ //-------BundleContentLoaderListener#bundleChanged(BundleEvent)-------//
@Test
public void getContentInfoFromLockedNode() throws RepositoryException {
final Bundle bundle = createNewBundle();
- final Node bcNode = (Node)session.getItem(ContentLoaderService.BUNDLE_CONTENT_NODE);
+ final Node bcNode = (Node)session.getItem(BundleContentLoaderListener.BUNDLE_CONTENT_NODE);
bcNode.addNode(bundle.getSymbolicName()).addMixin("mix:lockable");
session.save();
LockManager lockManager = session.getWorkspace().getLockManager();
@@ -124,7 +124,7 @@ public class ContentLoaderServiceTest {
@Test
public void getContentInfoFromNotLockableNode() throws RepositoryException {
final Bundle bundle = createNewBundle();
- final Node bcNode = (Node)session.getItem(ContentLoaderService.BUNDLE_CONTENT_NODE);
+ final Node bcNode = (Node)session.getItem(BundleContentLoaderListener.BUNDLE_CONTENT_NODE);
bcNode.addNode(bundle.getSymbolicName()); //Node without lockable mixin
session.save();
@@ -134,7 +134,7 @@ public class ContentLoaderServiceTest {
@Test
public void getContentInfo() throws RepositoryException {
final Bundle bundle = createNewBundle();
- final Node bcNode = (Node)session.getItem(ContentLoaderService.BUNDLE_CONTENT_NODE);
+ final Node bcNode = (Node)session.getItem(BundleContentLoaderListener.BUNDLE_CONTENT_NODE);
final Node bundleContent = bcNode.addNode(bundle.getSymbolicName());
bundleContent.addMixin("mix:lockable");
@@ -156,7 +156,7 @@ public class ContentLoaderServiceTest {
assertTrue(props.containsKey(PROPERTY_UNINSTALL_PATHS));
}
- //-------ContentLoaderService#contentIsUninstalled(Session, Bundle)-------//
+ //-------BundleContentLoaderListener#contentIsUninstalled(Session, Bundle)-------//
@Test
public void testContentIsUninstalled() throws RepositoryException {
@@ -171,14 +171,14 @@ public class ContentLoaderServiceTest {
assertFalse(bcNode.getProperty(PROPERTY_CONTENT_LOADED).getBoolean());
}
- //-------ContentLoaderService#getMimeType(String)-------//
+ //-------BundleContentLoaderListener#getMimeType(String)-------//
@Test
public void testMimeTypeService(){
assertEquals("audio/mpeg", underTest.getMimeType("test.mp3"));
}
- //-------ContentLoaderService#getMimeType(String)-------//
+ //-------BundleContentLoaderListener#getMimeType(String)-------//
@Test
public void getSessionForWorkspace() throws RepositoryException {
diff --git a/src/test/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderTest.java b/src/test/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderTest.java
index a985701..368bfc7 100644
--- a/src/test/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderTest.java
+++ b/src/test/java/org/apache/sling/jcr/contentloader/internal/BundleContentLoaderTest.java
@@ -21,8 +21,11 @@ package org.apache.sling.jcr.contentloader.internal;
import static java.util.Collections.singletonMap;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
+import java.lang.annotation.Annotation;
+
import javax.jcr.Session;
import org.apache.sling.api.resource.Resource;
@@ -43,7 +46,9 @@ public class BundleContentLoaderTest {
@Rule
public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
- private BundleContentLoader contentLoader;
+ private BundleContentLoaderListener bundleHelper;
+
+ private ContentReaderWhiteboard whiteboard;
@Before
public void prepareContentLoader() throws Exception {
@@ -56,17 +61,17 @@ public class BundleContentLoaderTest {
context.registerInjectActivateService(new ContentReaderWhiteboard());
// register the content loader service
- BundleHelper bundleHelper = context.registerInjectActivateService(new ContentLoaderService());
+ bundleHelper = context.registerInjectActivateService(new BundleContentLoaderListener());
- ContentReaderWhiteboard whiteboard = context.getService(ContentReaderWhiteboard.class);
+ whiteboard = context.getService(ContentReaderWhiteboard.class);
- contentLoader = new BundleContentLoader(bundleHelper, whiteboard);
}
-
@Test
public void loadContentWithSpecificPath() throws Exception {
+ BundleContentLoader contentLoader = new BundleContentLoader(bundleHelper, whiteboard, null);
+
Bundle mockBundle = newBundleWithInitialContent("SLING-INF/libs/app;path:=/libs/app");
contentLoader.registerBundle(context.resourceResolver().adaptTo(Session.class), mockBundle, false);
@@ -78,8 +83,102 @@ public class BundleContentLoaderTest {
}
@Test
+ public void loadContentWithExcludes() throws Exception {
+
+ BundleContentLoader contentLoader = new BundleContentLoader(bundleHelper, whiteboard,
+ new BundleContentLoaderConfiguration() {
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] includedTargets() {
+ return new String[] { "^/.*$" };
+ }
+
+ @Override
+ public String[] excludedTargets() {
+ return new String[] { "^/libs.*$" };
+ }
+
+ });
+
+ Bundle mockBundle = newBundleWithInitialContent(
+ "SLING-INF/libs/app;path:=/libs/app,SLING-INF/content/app;path:=/content/app");
+
+ contentLoader.registerBundle(context.resourceResolver().adaptTo(Session.class), mockBundle, false);
+
+ assertThat("Excluded resource imported", context.resourceResolver().getResource("/libs/app"), nullValue());
+ }
+
+
+ @Test
+ public void loadContentWithNullValue() throws Exception {
+
+ BundleContentLoader contentLoader = new BundleContentLoader(bundleHelper, whiteboard,
+ new BundleContentLoaderConfiguration() {
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] includedTargets() {
+ return new String[] { "^/.*$" };
+ }
+
+ @Override
+ public String[] excludedTargets() {
+ return null;
+ }
+
+ });
+
+ Bundle mockBundle = newBundleWithInitialContent(
+ "SLING-INF/libs/app;path:=/libs/app,SLING-INF/content/app;path:=/content/app");
+
+ contentLoader.registerBundle(context.resourceResolver().adaptTo(Session.class), mockBundle, false);
+
+ assertThat("Excluded resource imported", context.resourceResolver().getResource("/libs/app"), notNullValue());
+ }
+
+
+ @Test
+ public void loadContentWithIncludes() throws Exception {
+
+ BundleContentLoader contentLoader = new BundleContentLoader(bundleHelper, whiteboard,
+ new BundleContentLoaderConfiguration() {
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] includedTargets() {
+ return new String[] { "^/.*$" };
+ }
+
+ @Override
+ public String[] excludedTargets() {
+ return new String[] { "^/app.*$" };
+ }
+
+ });
+
+ Bundle mockBundle = newBundleWithInitialContent(
+ "SLING-INF/libs/app;path:=/libs/app");
+
+ contentLoader.registerBundle(context.resourceResolver().adaptTo(Session.class), mockBundle, false);
+
+ assertThat("Included resource not imported", context.resourceResolver().getResource("/libs/app"), notNullValue());
+ }
+
+ @Test
public void loadContentWithRootPath() throws Exception {
+ BundleContentLoader contentLoader = new BundleContentLoader(bundleHelper, whiteboard, null);
+
Bundle mockBundle = newBundleWithInitialContent("SLING-INF/");
contentLoader.registerBundle(context.resourceResolver().adaptTo(Session.class), mockBundle, false);
@@ -94,9 +193,12 @@ public class BundleContentLoaderTest {
@Ignore("TODO - unregister or somehow ignore the XmlReader component for this test")
public void loadXmlAsIs() throws Exception {
+ BundleContentLoader contentLoader = new BundleContentLoader(bundleHelper, whiteboard, null);
+
dumpRepo("/", 2);
- Bundle mockBundle = newBundleWithInitialContent("SLING-INF/libs/app;path:=/libs/app;ignoreImportProviders:=xml");
+ Bundle mockBundle = newBundleWithInitialContent(
+ "SLING-INF/libs/app;path:=/libs/app;ignoreImportProviders:=xml");
contentLoader.registerBundle(context.resourceResolver().adaptTo(Session.class), mockBundle, false);
@@ -120,27 +222,25 @@ public class BundleContentLoaderTest {
return mockBundle;
}
-
private void dumpRepo(String startPath, int maxDepth) {
dumpRepo0(startPath, maxDepth, 0);
}
-
private void dumpRepo0(String startPath, int maxDepth, int currentDepth) {
Resource resource = context.resourceResolver().getResource(startPath);
StringBuilder format = new StringBuilder();
- for ( int i = 0 ;i < currentDepth ; i++) {
+ for (int i = 0; i < currentDepth; i++) {
format.append(" ");
}
format.append("%s [%s]%n");
- String name = resource.getName().length() == 0 ? "/" : resource.getName();
+ String name = resource.getName().length() == 0 ? "/" : resource.getName();
System.out.format(format.toString(), name, resource.getResourceType());
currentDepth++;
- if ( currentDepth > maxDepth) {
+ if (currentDepth > maxDepth) {
return;
}
- for ( Resource child : resource.getChildren() ) {
+ for (Resource child : resource.getChildren()) {
dumpRepo0(child.getPath(), maxDepth, currentDepth);
}
}