/** * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. jclouds 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.jclouds.karaf.itests; import static org.openengsb.labs.paxexam.karaf.options.KarafDistributionOption.editConfigurationFileExtend; import static org.openengsb.labs.paxexam.karaf.options.KarafDistributionOption.karafDistributionConfiguration; import static org.ops4j.pax.exam.CoreOptions.maven; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintStream; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Dictionary; import java.util.Enumeration; import javax.inject.Inject; import org.apache.felix.service.command.CommandProcessor; import org.apache.felix.service.command.CommandSession; import org.ops4j.pax.exam.CoreOptions; import org.ops4j.pax.exam.MavenUtils; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.TestProbeBuilder; import org.ops4j.pax.exam.junit.ProbeBuilder; import org.ops4j.pax.exam.options.MavenArtifactProvisionOption; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.Filter; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.util.tracker.ServiceTracker; public class JcloudsKarafTestSupport { public static final Long DEFAULT_TIMEOUT = 10000L; public static final Long DEFAULT_WAIT = 10000L; public static final String KARAF_GROUP_ID = "org.apache.karaf"; public static final String KARAF_ARTIFACT_ID = "apache-karaf"; public static final String JCLOUDS_KARAF_GROUP_ID = "org.jclouds.karaf"; public static final String JCLOUDS_KARAF_ARTIFACT_ID = "jclouds-karaf"; public static final String JCLOUDS_GROUP_ID = "org.jclouds"; public static final String JCLOUDS_ARTIFACT_ID = "jclouds-core"; @Inject protected BundleContext bundleContext; /** * This is used to customize the Probe that will contain the test. * We need to enable dynamic import of provisional bundles, to use the Console. * * @param probe * @return */ @ProbeBuilder public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) { probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*,org.apache.felix.service.*;status=provisional"); return probe; } /** * Create an {@link Option} for using Apache Karaf distribution. * * @return */ protected Option jcloudsDistributionConfiguration() { return karafDistributionConfiguration().frameworkUrl( maven().groupId(KARAF_GROUP_ID).artifactId(KARAF_ARTIFACT_ID).versionAsInProject().type("tar.gz")) .karafVersion(getKarafVersion()).name("Apache Karaf Distro").unpackDirectory(new File("target/paxexam/unpack/")); } /** * Sets a System property. * @param propertyName * @return */ public static Option systemProperty(String propertyName, String propertyValue) { return editConfigurationFileExtend("etc/system.properties", propertyName, propertyValue != null ? propertyValue : ""); } /** * Copies the actual System property to the container properties. * @param propertyName * @return */ public static Option systemProperty(String propertyName) { return systemProperty(propertyName, System.getProperty(propertyName)); } /** * Executes the command and returns the output as a String. * * @param command * @return */ protected String executeCommand(String command) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); PrintStream printStream = new PrintStream(byteArrayOutputStream); CommandProcessor commandProcessor = getOsgiService(CommandProcessor.class); CommandSession commandSession = commandProcessor.createSession(System.in, printStream, System.err); //This is required in order to run scripts that use those session variables. commandSession.put("APPLICATION", System.getProperty("karaf.name", "root")); commandSession.put("USER", "karaf"); try { System.err.println(command); commandSession.execute(command); } catch (Exception e) { e.printStackTrace(System.err); } return byteArrayOutputStream.toString(); } /** * Executes multiple commands inside a Single Session. * Commands have a default timeout of 10 seconds. * @param commands * @return */ protected String executeCommands(final String ...commands) { final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); final PrintStream printStream = new PrintStream(byteArrayOutputStream); final CommandProcessor commandProcessor = getOsgiService(CommandProcessor.class); final CommandSession commandSession = commandProcessor.createSession(System.in, printStream, System.err); commandSession.put("APPLICATION", System.getProperty("karaf.name", "root")); commandSession.put("USER", "karaf"); for (String command : commands) { try { System.err.println(command); commandSession.execute(command); } catch (Exception e) { e.printStackTrace(System.err); } } return byteArrayOutputStream.toString(); } protected Bundle installBundle(String groupId, String artifactId) throws Exception { MavenArtifactProvisionOption mvnUrl = mavenBundle(groupId, artifactId); return bundleContext.installBundle(mvnUrl.getURL()); } protected Bundle getInstalledBundle(String symbolicName) { for (Bundle b : bundleContext.getBundles()) { if (b.getSymbolicName().equals(symbolicName)) { return b; } } for (Bundle b : bundleContext.getBundles()) { System.err.println("Bundle: " + b.getSymbolicName()); } throw new RuntimeException("Bundle " + symbolicName + " does not exist"); } /* * Explode the dictionary into a ,-delimited list of key=value pairs */ private static String explode(Dictionary dictionary) { Enumeration keys = dictionary.keys(); StringBuffer result = new StringBuffer(); while (keys.hasMoreElements()) { Object key = keys.nextElement(); result.append(String.format("%s=%s", key, dictionary.get(key))); if (keys.hasMoreElements()) { result.append(", "); } } return result.toString(); } protected <T> T getOsgiService(Class<T> type, long timeout) { return getOsgiService(type, null, timeout); } protected <T> T getOsgiService(Class<T> type) { return getOsgiService(type, null, DEFAULT_TIMEOUT); } protected <T> T getOsgiService(Class<T> type, String filter, long timeout) { ServiceTracker tracker = null; try { String flt; if (filter != null) { if (filter.startsWith("(")) { flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")" + filter + ")"; } else { flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")(" + filter + "))"; } } else { flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")"; } Filter osgiFilter = FrameworkUtil.createFilter(flt); tracker = new ServiceTracker(bundleContext, osgiFilter, null); tracker.open(true); // Note that the tracker is not closed to keep the reference // This is buggy, as the service reference may change i think Object svc = type.cast(tracker.waitForService(timeout)); if (svc == null) { Dictionary dic = bundleContext.getBundle().getHeaders(); System.err.println("Test bundle headers: " + explode(dic)); for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, null))) { System.err.println("ServiceReference: " + ref); } for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, flt))) { System.err.println("Filtered ServiceReference: " + ref); } throw new RuntimeException("Gave up waiting for service " + flt); } return type.cast(svc); } catch (InvalidSyntaxException e) { throw new IllegalArgumentException("Invalid filter", e); } catch (InterruptedException e) { throw new RuntimeException(e); } } /* * Provides an iterable collection of references, even if the original array is null */ private static Collection<ServiceReference> asCollection(ServiceReference[] references) { return references != null ? Arrays.asList(references) : Collections.<ServiceReference>emptyList(); } /** * Create an provisioning option for the specified maven artifact * (groupId and artifactId), using the version found in the list * of dependencies of this maven project. * * @param groupId the groupId of the maven bundle * @param artifactId the artifactId of the maven bundle * @return the provisioning option for the given bundle */ protected static MavenArtifactProvisionOption mavenBundle(String groupId, String artifactId) { return CoreOptions.mavenBundle(groupId, artifactId).versionAsInProject(); } /** * Create an provisioning option for the specified maven artifact * (groupId and artifactId), using the version found in the list * of dependencies of this maven project. * * @param groupId the groupId of the maven bundle * @param artifactId the artifactId of the maven bundle * @param version the version of the maven bundle * @return the provisioning option for the given bundle */ protected static MavenArtifactProvisionOption mavenBundle(String groupId, String artifactId, String version) { return CoreOptions.mavenBundle(groupId, artifactId).version(version); } /** * Returns the Version of Karaf to be used. * * @return */ protected String getKarafVersion() { return MavenUtils.getArtifactVersion(KARAF_GROUP_ID, KARAF_ARTIFACT_ID); } }