blob: 8204a641d1feb94aa2f369c22af951eda92d2308 [file] [log] [blame]
/*
* 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.it;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.inject.Inject;
import javax.jcr.Session;
import org.apache.commons.io.IOUtils;
import org.apache.sling.commons.testing.junit.RetryRule;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.launchpad.api.StartupHandler;
import org.apache.sling.launchpad.api.StartupMode;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.tinybundles.core.TinyBundle;
import org.ops4j.pax.tinybundles.core.TinyBundles;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Base class for testing bundles that provide initial content */
@RunWith(PaxExam.class)
public abstract class ContentBundleTestBase {
private final Logger log = LoggerFactory.getLogger(getClass());
@Rule
public final RetryRule retry = new RetryRule(RETRY_TIMEOUT, RETRY_INTERVAL);
@Inject
protected BundleContext bundleContext;
@Inject
protected SlingRepository repository;
protected static Session session;
protected static String bundleSymbolicName;
protected static String contentRootPath;
private static final List<Bundle> bundlesToRemove = new ArrayList<>();
protected static final int RETRY_TIMEOUT = 5000;
protected static final int RETRY_INTERVAL = 100;
protected static final String SLING_INITIAL_CONTENT_HEADER = "Sling-Initial-Content";
protected static final String DEFAULT_PATH_IN_BUNDLE = "test-initial-content";
@org.ops4j.pax.exam.Configuration
public Option[] config() {
return PaxExamUtilities.paxConfig();
}
@BeforeClass
public static void setupClass() {
bundleSymbolicName = "TEST-" + UUID.randomUUID();
contentRootPath = "/test-content/" + bundleSymbolicName;
}
@Before
public void setup() throws Exception {
registerStartupHandler();
session = repository.loginAdministrative(null);
// The RetryRule executes this method on every retry, make
// sure to install our test bundle only once
if(!bundlesToRemove.isEmpty()) {
return;
}
assertFalse("Expecting no content before test", session.itemExists(contentRootPath));
// Create, install and start a bundle that has initial content
final InputStream is = getTestBundleStream();
try {
final Bundle b = bundleContext.installBundle(bundleSymbolicName, is);
bundlesToRemove.add(b);
b.start();
} finally {
is.close();
}
maybeDumpTestBundle();
}
/** Optionally dump our test bundle, for troubleshooting it */
private void maybeDumpTestBundle() throws Exception {
final boolean doDump = Boolean.valueOf(System.getProperty("dump.test.bundles", "false"));
if(doDump) {
final File target = File.createTempFile(bundleSymbolicName, ".jar");
FileOutputStream fos = new FileOutputStream(target);
try {
IOUtils.copy(getTestBundleStream(), fos);
log.info("Dumped test bundle to {} for troubleshooting", target.getAbsolutePath());
} finally {
IOUtils.closeQuietly(fos);
}
}
}
private InputStream getTestBundleStream() throws Exception {
return setupTestBundle(TinyBundles.bundle()
.set(Constants.BUNDLE_SYMBOLICNAME, bundleSymbolicName)
).build(TinyBundles.withBnd());
}
abstract protected TinyBundle setupTestBundle(TinyBundle b) throws Exception;
/** Add content to our test bundle */
protected void addContent(TinyBundle b, String pathInBundle, String resourcePath) throws IOException {
pathInBundle += "/" + resourcePath;
resourcePath = "/initial-content/" + resourcePath;
final InputStream is = getClass().getResourceAsStream(resourcePath);
try {
assertNotNull("Expecting resource to be found:" + resourcePath, is);
log.info("Adding resource to bundle, path={}, resource={}", pathInBundle, resourcePath);
b.add(pathInBundle, is);
} finally {
if(is != null) {
is.close();
}
}
}
@AfterClass
public static void cleanupClass() throws BundleException {
for(Bundle b : bundlesToRemove) {
b.uninstall();
}
bundlesToRemove.clear();
session.logout();
session = null;
}
private void registerStartupHandler() {
// SLING-4917 (org.apache.sling.paxexam.util.SlingSetupTest)
// In Sling launchpad 7 the SlingSettings service
// requires a StartupHandler, and that's usually provided
// by the launchpad bootstrap code. Supply our own so that
// everything starts properly.
// TODO should be provided by a utility/bootstrap bundle
final StartupHandler h = new StartupHandler() {
@Override
public void waitWithStartup(boolean b) {
}
@Override
public boolean isFinished() {
return true;
}
@Override
public StartupMode getMode() {
return StartupMode.INSTALL;
}
};
bundleContext.registerService(StartupHandler.class.getName(), h, null);
}
}