You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2014/06/06 14:18:30 UTC
svn commit: r1600865 - in /sling/trunk/contrib/crankstart: core/
core/src/main/java/org/apache/sling/crankstart/core/commands/ launcher/
launcher/src/test/java/org/apache/sling/crankstart/launcher/
launcher/src/test/resources/
Author: bdelacretaz
Date: Fri Jun 6 12:18:30 2014
New Revision: 1600865
URL: http://svn.apache.org/r1600865
Log:
Add support for configurations in Felix .config format
Added:
sling/trunk/contrib/crankstart/launcher/src/test/java/org/apache/sling/crankstart/launcher/PreemptiveAuthInterceptor.java
Modified:
sling/trunk/contrib/crankstart/core/pom.xml
sling/trunk/contrib/crankstart/core/src/main/java/org/apache/sling/crankstart/core/commands/Configure.java
sling/trunk/contrib/crankstart/launcher/pom.xml
sling/trunk/contrib/crankstart/launcher/src/test/java/org/apache/sling/crankstart/launcher/CrankstartBootstrapTest.java
sling/trunk/contrib/crankstart/launcher/src/test/resources/launcher-test.crank.txt
Modified: sling/trunk/contrib/crankstart/core/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/crankstart/core/pom.xml?rev=1600865&r1=1600864&r2=1600865&view=diff
==============================================================================
--- sling/trunk/contrib/crankstart/core/pom.xml (original)
+++ sling/trunk/contrib/crankstart/core/pom.xml Fri Jun 6 12:18:30 2014
@@ -36,6 +36,44 @@
<target>1.6</target>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>2.3</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <createDependencyReducedPom>false</createDependencyReducedPom>
+ <artifactSet>
+ <includes>
+ <include>org.apache.felix:org.apache.felix.configadmin</include>
+ </includes>
+ <excludes>
+ <exclude>org.osgi</exclude>
+ </excludes>
+ </artifactSet>
+ <filters>
+ <filter>
+ <artifact>org.apache.felix:org.apache.felix.configadmin</artifact>
+ <includes>
+ <include>org/apache/felix/cm/file/Config*</include>
+ </includes>
+ </filter>
+ </filters>
+ <relocations>
+ <relocation>
+ <pattern>org.apache.felix.cm.file</pattern>
+ <shadedPattern>org.apache.felix.SHADED.cm.file</shadedPattern>
+ </relocation>
+ </relocations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
@@ -58,6 +96,16 @@
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
+ <!--
+ We use a class from the config admin implementation to read config files,
+ and we process it using maven-shade-plugin to avoid conflicts
+ -->
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.configadmin</artifactId>
+ <version>1.2.8</version>
+ <scope>compile</scope>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Modified: sling/trunk/contrib/crankstart/core/src/main/java/org/apache/sling/crankstart/core/commands/Configure.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/crankstart/core/src/main/java/org/apache/sling/crankstart/core/commands/Configure.java?rev=1600865&r1=1600864&r2=1600865&view=diff
==============================================================================
--- sling/trunk/contrib/crankstart/core/src/main/java/org/apache/sling/crankstart/core/commands/Configure.java (original)
+++ sling/trunk/contrib/crankstart/core/src/main/java/org/apache/sling/crankstart/core/commands/Configure.java Fri Jun 6 12:18:30 2014
@@ -16,8 +16,13 @@
*/
package org.apache.sling.crankstart.core.commands;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.Dictionary;
+import java.util.Enumeration;
+import org.apache.felix.cm.file.ConfigurationHandler;
import org.apache.sling.crankstart.api.CrankstartCommand;
import org.apache.sling.crankstart.api.CrankstartCommandLine;
import org.apache.sling.crankstart.api.CrankstartContext;
@@ -30,6 +35,7 @@ import org.slf4j.LoggerFactory;
public class Configure implements CrankstartCommand {
public static final String I_CONFIGURE = "config";
public static final String FACTORY_SUFFIX = ".factory";
+ public static final String FELIX_FORMAT_SUFFIX = "FORMAT:felix.config";
private final Logger log = LoggerFactory.getLogger(getClass());
@Override
@@ -43,8 +49,21 @@ public class Configure implements Cranks
@Override
public void execute(CrankstartContext crankstartContext, CrankstartCommandLine commandLine) throws Exception {
- final String pid = commandLine.getQualifier();
- final Dictionary<String, Object> properties = commandLine.getProperties();
+
+ // Configs can be in our plain format or in Felix .config format, which supports various data types
+ String pid = null;
+ boolean felixFormat = false;
+ if(commandLine.getQualifier().endsWith(FELIX_FORMAT_SUFFIX)) {
+ felixFormat = true;
+ pid = commandLine.getQualifier().split(" ")[0].trim();
+ } else {
+ pid = commandLine.getQualifier();
+ }
+
+ Dictionary<String, Object> properties = commandLine.getProperties();
+ if(felixFormat) {
+ properties = parseFelixConfig(properties);
+ }
final BundleContext bundleContext = crankstartContext.getOsgiFramework().getBundleContext();
// TODO: wait for configadmin service?
@@ -74,4 +93,23 @@ public class Configure implements Cranks
.invoke(config, properties);
log.info("Updated configuration {}: {}", pid, properties);
}
+
+ @SuppressWarnings("unchecked")
+ private Dictionary<String, Object> parseFelixConfig(Dictionary<String, Object> properties) throws IOException {
+ // Build a stream in Felix .config format and parse it
+ final StringBuilder sb = new StringBuilder();
+ final Enumeration<String> keys = properties.keys();
+ while(keys.hasMoreElements()) {
+ final String key = keys.nextElement();
+ final Object value = properties.get(key);
+ sb.append(key).append("=").append(value).append("\n");
+ }
+
+ final InputStream is = new ByteArrayInputStream(sb.toString().getBytes("UTF-8"));
+ try {
+ return ConfigurationHandler.read(is);
+ } finally {
+ is.close();
+ }
+ }
}
Modified: sling/trunk/contrib/crankstart/launcher/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/crankstart/launcher/pom.xml?rev=1600865&r1=1600864&r2=1600865&view=diff
==============================================================================
--- sling/trunk/contrib/crankstart/launcher/pom.xml (original)
+++ sling/trunk/contrib/crankstart/launcher/pom.xml Fri Jun 6 12:18:30 2014
@@ -157,5 +157,11 @@
<version>4.1</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
Modified: sling/trunk/contrib/crankstart/launcher/src/test/java/org/apache/sling/crankstart/launcher/CrankstartBootstrapTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/crankstart/launcher/src/test/java/org/apache/sling/crankstart/launcher/CrankstartBootstrapTest.java?rev=1600865&r1=1600864&r2=1600865&view=diff
==============================================================================
--- sling/trunk/contrib/crankstart/launcher/src/test/java/org/apache/sling/crankstart/launcher/CrankstartBootstrapTest.java (original)
+++ sling/trunk/contrib/crankstart/launcher/src/test/java/org/apache/sling/crankstart/launcher/CrankstartBootstrapTest.java Fri Jun 6 12:18:30 2014
@@ -3,6 +3,7 @@ package org.apache.sling.crankstart.laun
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 static org.junit.Assert.fail;
import java.io.File;
@@ -13,11 +14,18 @@ import java.io.Reader;
import java.net.ServerSocket;
import java.util.Random;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.util.EntityUtils;
import org.apache.sling.commons.testing.junit.Retry;
import org.apache.sling.commons.testing.junit.RetryRule;
import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
@@ -28,7 +36,7 @@ import org.junit.Test;
public class CrankstartBootstrapTest {
private static final int port = getAvailablePort();
- private static final HttpClient client = new HttpClient();
+ private static DefaultHttpClient client;
private static Thread crankstartThread;
private static String baseUrl = "http://localhost:" + port;
public static final String TEST_RESOURCE = "/launcher-test.crank.txt";
@@ -55,6 +63,18 @@ public class CrankstartBootstrapTest {
return result;
}
+ @Before
+ public void setupHttpClient() {
+ client = new DefaultHttpClient();
+ }
+
+ private void setAdminCredentials() {
+ client.getCredentialsProvider().setCredentials(
+ AuthScope.ANY,
+ new UsernamePasswordCredentials("admin", "admin"));
+ client.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0);
+ }
+
@BeforeClass
public static void testExtensionPropertyBeforeTests() {
assertNull(TEST_SYSTEM_PROPERTY + " should not be set before tests", System.getProperty(TEST_SYSTEM_PROPERTY));
@@ -62,7 +82,8 @@ public class CrankstartBootstrapTest {
@BeforeClass
public static void setup() {
- final GetMethod get = new GetMethod(baseUrl);
+ client = new DefaultHttpClient();
+ final HttpUriRequest get = new HttpGet(baseUrl);
System.setProperty("http.port", String.valueOf(port));
System.setProperty("osgi.storage.path", getOsgiStoragePath());
@@ -71,7 +92,7 @@ public class CrankstartBootstrapTest {
final Reader input = new InputStreamReader(is);
try {
- client.executeMethod(get);
+ client.execute(get);
fail("Expecting connection to " + port + " to fail before starting HTTP service");
} catch(IOException expected) {
}
@@ -101,20 +122,36 @@ public class CrankstartBootstrapTest {
crankstartThread.join();
}
+ private void closeConnection(HttpResponse r) throws IOException {
+ if(r != null && r.getEntity() != null) {
+ EntityUtils.consume(r.getEntity());
+ }
+ }
+
@Test
@Retry(timeoutMsec=10000, intervalMsec=250)
public void testHttpRoot() throws Exception {
- final GetMethod get = new GetMethod(baseUrl);
- client.executeMethod(get);
- assertEquals("Expecting page not found at " + get.getURI(), 404, get.getStatusCode());
+ final HttpUriRequest get = new HttpGet(baseUrl);
+ HttpResponse response = null;
+ try {
+ response = client.execute(get);
+ assertEquals("Expecting page not found at " + get.getURI(), 404, response.getStatusLine().getStatusCode());
+ } finally {
+ closeConnection(response);
+ }
}
@Test
@Retry(timeoutMsec=10000, intervalMsec=250)
public void testSingleConfigServlet() throws Exception {
- final GetMethod get = new GetMethod(baseUrl + "/single");
- client.executeMethod(get);
- assertEquals("Expecting success for " + get.getURI(), 200, get.getStatusCode());
+ final HttpUriRequest get = new HttpGet(baseUrl + "/single");
+ HttpResponse response = null;
+ try {
+ response = client.execute(get);
+ assertEquals("Expecting success for " + get.getURI(), 200, response.getStatusLine().getStatusCode());
+ } finally {
+ closeConnection(response);
+ }
}
@Test
@@ -122,9 +159,14 @@ public class CrankstartBootstrapTest {
public void testConfigFactoryServlet() throws Exception {
final String [] paths = { "/foo", "/bar/test" };
for(String path : paths) {
- final GetMethod get = new GetMethod(baseUrl + path);
- client.executeMethod(get);
- assertEquals("Expecting success for " + get.getURI(), 200, get.getStatusCode());
+ final HttpUriRequest get = new HttpGet(baseUrl + path);
+ HttpResponse response = null;
+ try {
+ response = client.execute(get);
+ assertEquals("Expecting success for " + get.getURI(), 200, response.getStatusLine().getStatusCode());
+ } finally {
+ closeConnection(response);
+ }
}
}
@@ -139,9 +181,42 @@ public class CrankstartBootstrapTest {
@Retry(timeoutMsec=10000, intervalMsec=250)
public void testJUnitServlet() throws Exception {
final String path = "/system/sling/junit";
- final GetMethod get = new GetMethod(baseUrl + path);
- client.executeMethod(get);
- assertEquals("Expecting JUnit servlet to be installed via sling extension command, at " + get.getURI(), 200, get.getStatusCode());
+ final HttpUriRequest get = new HttpGet(baseUrl + path);
+ HttpResponse response = null;
+ try {
+ response = client.execute(get);
+ assertEquals("Expecting JUnit servlet to be installed via sling extension command, at " + get.getURI(), 200, response.getStatusLine().getStatusCode());
+ } finally {
+ closeConnection(response);
+ }
+ }
+
+ @Test
+ @Retry(timeoutMsec=10000, intervalMsec=250)
+ public void testFelixFormatConfig() throws Exception {
+ setAdminCredentials();
+ final String path = "/system/console/config/configuration-status-20140606-1347+0200.txt";
+ final HttpUriRequest get = new HttpGet(baseUrl + path);
+ HttpResponse response = null;
+ try {
+ response = client.execute(get);
+ assertEquals("Expecting config dump to be available at " + get.getURI(), 200, response.getStatusLine().getStatusCode());
+ assertNotNull("Expecting response entity", response.getEntity());
+ String encoding = "UTF-8";
+ if(response.getEntity().getContentEncoding() != null) {
+ encoding = response.getEntity().getContentEncoding().getValue();
+ }
+ final String content = IOUtils.toString(response.getEntity().getContent(), encoding);
+ final String [] expected = new String[] {
+ "array = [foo, bar.from.launcher.test]",
+ "service.ranking.launcher.test = 54321"
+ };
+ for(String exp : expected) {
+ assertTrue("Expecting config content to contain " + exp, content.contains(exp));
+ }
+ } finally {
+ closeConnection(response);
+ }
}
private static String getOsgiStoragePath() {
@@ -154,4 +229,4 @@ public class CrankstartBootstrapTest {
tmpFolder.deleteOnExit();
return tmpFolder.getAbsolutePath();
}
-}
+}
\ No newline at end of file
Added: sling/trunk/contrib/crankstart/launcher/src/test/java/org/apache/sling/crankstart/launcher/PreemptiveAuthInterceptor.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/crankstart/launcher/src/test/java/org/apache/sling/crankstart/launcher/PreemptiveAuthInterceptor.java?rev=1600865&view=auto
==============================================================================
--- sling/trunk/contrib/crankstart/launcher/src/test/java/org/apache/sling/crankstart/launcher/PreemptiveAuthInterceptor.java (added)
+++ sling/trunk/contrib/crankstart/launcher/src/test/java/org/apache/sling/crankstart/launcher/PreemptiveAuthInterceptor.java Fri Jun 6 12:18:30 2014
@@ -0,0 +1,41 @@
+package org.apache.sling.crankstart.launcher;
+
+import java.io.IOException;
+
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.AuthState;
+import org.apache.http.auth.Credentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.protocol.ExecutionContext;
+import org.apache.http.protocol.HttpContext;
+
+/** It's not like httpclient 4.1 makes this simple... */
+class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
+
+ public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
+
+ AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
+ CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER);
+ HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
+
+ // If not auth scheme has been initialized yet
+ if (authState.getAuthScheme() == null) {
+ AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
+
+ // Obtain credentials matching the target host
+ Credentials creds = credsProvider.getCredentials(authScope);
+
+ // If found, generate BasicScheme preemptively
+ if (creds != null) {
+ authState.setAuthScheme(new BasicScheme());
+ authState.setCredentials(creds);
+ }
+ }
+ }
+}
Modified: sling/trunk/contrib/crankstart/launcher/src/test/resources/launcher-test.crank.txt
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/crankstart/launcher/src/test/resources/launcher-test.crank.txt?rev=1600865&r1=1600864&r2=1600865&view=diff
==============================================================================
--- sling/trunk/contrib/crankstart/launcher/src/test/resources/launcher-test.crank.txt (original)
+++ sling/trunk/contrib/crankstart/launcher/src/test/resources/launcher-test.crank.txt Fri Jun 6 12:18:30 2014
@@ -57,6 +57,12 @@ config.factory org.apache.sling.cranksta
path=/bar/test
message=Not used
+# Test Felix format configs
+config felix.format.test FORMAT:felix.config
+ mongouri="mongodb://localhost:27017"
+ service.ranking.launcher.test=I"54321"
+ array=["foo","bar.from.launcher.test"]
+
# Test an extension command provided by our test-services bundle
test.system.property the.test.system.property was set by test-services bundle