You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2012/07/05 14:10:06 UTC

svn commit: r1357570 [25/34] - in /ace/sandbox/marrs: cnf/ cnf/ext/ cnf/lib/ cnf/releaserepo/ cnf/repo/ cnf/repo/.obrcache/ cnf/repo/.obrcache/http%3A%2F%2Fbundles.bndtools.org.s3.amazonaws.com%2Fcom.jcraft.jsch/ cnf/repo/.obrcache/http%3A%2F%2Fbundles...

Added: ace/sandbox/marrs/org.apache.ace.configurator/test/org/apache/ace/configurator/MockConfigAdmin.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.configurator/test/org/apache/ace/configurator/MockConfigAdmin.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.configurator/test/org/apache/ace/configurator/MockConfigAdmin.java (added)
+++ ace/sandbox/marrs/org.apache.ace.configurator/test/org/apache/ace/configurator/MockConfigAdmin.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,54 @@
+/*
+ * 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.ace.configurator;
+
+import java.io.IOException;
+
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class MockConfigAdmin implements ConfigurationAdmin {
+
+    private Configuration m_configuration = new MockConfiguration();
+
+    public Configuration createFactoryConfiguration(String arg0) throws IOException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Configuration createFactoryConfiguration(String arg0, String arg1) throws IOException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Configuration getConfiguration(String pid) throws IOException {
+        return m_configuration;
+    }
+
+    public Configuration getConfiguration(String arg0, String arg1) throws IOException {
+        // TODO Auto-generated method stub
+        return m_configuration;
+    }
+
+    public Configuration[] listConfigurations(String arg0) throws IOException, InvalidSyntaxException {
+        return new Configuration[] {m_configuration};
+    }
+
+}

Added: ace/sandbox/marrs/org.apache.ace.configurator/test/org/apache/ace/configurator/MockConfiguration.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.configurator/test/org/apache/ace/configurator/MockConfiguration.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.configurator/test/org/apache/ace/configurator/MockConfiguration.java (added)
+++ ace/sandbox/marrs/org.apache.ace.configurator/test/org/apache/ace/configurator/MockConfiguration.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,75 @@
+/*
+ * 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.ace.configurator;
+
+import java.io.IOException;
+import java.util.Dictionary;
+
+import org.osgi.service.cm.Configuration;
+
+public class MockConfiguration implements Configuration {
+
+    @SuppressWarnings("unchecked")
+    private Dictionary m_properties = null;
+    private boolean m_isDeleted = false;
+
+    public void delete() throws IOException {
+        m_isDeleted = true;
+    }
+
+    public String getBundleLocation() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String getFactoryPid() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String getPid() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    public synchronized Dictionary getProperties() {
+        return m_properties;
+    }
+
+    public void setBundleLocation(String arg0) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void update() throws IOException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @SuppressWarnings("unchecked")
+    public synchronized void update(Dictionary newConfiguration) throws IOException {
+            m_properties = newConfiguration;
+    }
+
+    public boolean isDeleted() {
+        return m_isDeleted;
+    }
+
+}

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/.classpath
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/.classpath?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/.classpath (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/.classpath Thu Jul  5 12:09:30 2012
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" output="bin_test" path="test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/.project
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/.project?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/.project (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/.project Thu Jul  5 12:09:30 2012
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.ace.connectionfactory</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/bnd.bnd?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/bnd.bnd (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/bnd.bnd Thu Jul  5 12:09:30 2012
@@ -0,0 +1,9 @@
+-buildpath: osgi.core,\
+	osgi.cmpn,\
+	org.apache.ace.util;version=latest,\
+	../cnf/lib/commons-codec-1.4.jar;version=file
+Private-Package: org.apache.ace.connectionfactory.impl,\
+	org.apache.commons.codec,\
+	org.apache.commons.codec.binary
+Bundle-Activator: org.apache.ace.connectionfactory.impl.Activator
+Export-Package: org.apache.ace.connectionfactory
\ No newline at end of file

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/build.xml
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/build.xml?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/build.xml (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/build.xml Thu Jul  5 12:09:30 2012
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build"> 
+	<import file="../cnf/build.xml"/>
+</project>

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/pom.xml
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/pom.xml?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/pom.xml (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/pom.xml Thu Jul  5 12:09:30 2012
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ace</groupId>
+        <artifactId>ace-pom</artifactId>
+        <version>0.8.1-SNAPSHOT</version>
+        <relativePath>../pom/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.ace.connectionfactory</artifactId>
+
+    <name>Apache ACE :: Connection Factory</name>
+    <description>Provides a service for creating connections to remote resources.</description>
+    <packaging>bundle</packaging>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/ace/trunk/ace-connectionfactory</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/ace/trunk/ace-connectionfactory</developerConnection>
+        <url>http://svn.apache.org/repos/asf/ace/trunk/ace-connectionfactory</url>
+    </scm>
+        
+    <properties>
+        <import.package>
+        	!org.junit,
+        	javax.net.ssl,
+        	org.apache.ace.connectionfactory;version=${project.version},
+        	org.osgi.framework,
+        	org.osgi.service.cm,
+        	org.osgi.service.useradmin
+        </import.package>
+        <export.package>
+        	org.apache.ace.connectionfactory;version=${project.version},
+        </export.package>
+        <private.package>
+            org.apache.ace.connectionfactory.impl,
+            org.apache.commons.codec,
+			org.apache.commons.codec.binary
+        </private.package>
+        <bundle.activator>org.apache.ace.connectionfactory.impl.Activator</bundle.activator>
+    </properties>
+    
+    <dependencies>
+		<dependency>
+			<groupId>org.osgi</groupId>
+		    <artifactId>org.osgi.core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.osgi</groupId>
+		    <artifactId>org.osgi.compendium</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>commons-codec</groupId>
+			<artifactId>commons-codec</artifactId>
+		</dependency>
+        <dependency>
+            <groupId>org.apache.ace</groupId>
+            <artifactId>org.apache.ace.util</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/ConnectionFactory.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/ConnectionFactory.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/ConnectionFactory.java (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/ConnectionFactory.java Thu Jul  5 12:09:30 2012
@@ -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.
+ */
+package org.apache.ace.connectionfactory;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+import org.osgi.service.useradmin.User;
+
+/**
+ * Provides a service to create {@link URLConnection}s. The connection factory will be responsible 
+ * for supplying the necessary credentials to ensure the authentication of the connection succeeds.
+ */
+public interface ConnectionFactory {
+
+    /**
+     * Creates a new connection using the given URL, using the (optional) credentials.
+     * 
+     * @param url the URL to connect to, cannot be <code>null</code>.
+     * @return a {@link URLConnection} instance, never <code>null</code>.
+     * @throws IllegalArgumentException in case the given URL was <code>null</code>;
+     * @throws IOException in case the creation of the connection failed.
+     */
+    URLConnection createConnection(URL url) throws IOException;
+
+    /**
+     * Creates a new connection using the given URL, using the (optional) credentials.
+     * 
+     * @param url the URL to connect to, cannot be <code>null</code>;
+     * @param user the user to fetch the credentials from, cannot be <code>null</code>.
+     * @return a {@link URLConnection} instance, never <code>null</code>.
+     * @throws IllegalArgumentException in case the given URL was <code>null</code>, or when the supplied credentials are missing information;
+     * @throws IOException in case the creation of the connection failed.
+     */
+    URLConnection createConnection(URL url, User user) throws IOException;
+}

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/Activator.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/Activator.java (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/Activator.java Thu Jul  5 12:09:30 2012
@@ -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.
+ */
+
+package org.apache.ace.connectionfactory.impl;
+
+import java.util.Properties;
+
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+/**
+ * Provides the bundle activator for the {@link ConnectionFactoryImpl} service.
+ */
+public class Activator implements BundleActivator {
+
+    /**
+     * {@inheritDoc}
+     */
+    public void start(BundleContext context) throws Exception {
+        Properties props = new Properties();
+        props.put(Constants.SERVICE_PID, ConnectionFactoryImpl.FACTORY_PID);
+        props.put("impl.type", "jdk");
+
+        context.registerService(new String[]{ ConnectionFactory.class.getName(), ManagedServiceFactory.class.getName() }, 
+            new ConnectionFactoryImpl(), props);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void stop(BundleContext context) throws Exception {
+        // Nop
+    }
+}

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,234 @@
+/*
+ * 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.ace.connectionfactory.impl;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.apache.ace.connectionfactory.impl.UrlCredentials.AuthType;
+import org.apache.ace.connectionfactory.impl.UrlCredentialsFactory.MissingValueException;
+import org.apache.commons.codec.binary.Base64;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.service.useradmin.User;
+
+/**
+ * Provides a default implementation for {@link ConnectionFactory} based on the standard <code>java.net</code>
+ * implementation of {@link URLConnection}.
+ */
+public class ConnectionFactoryImpl implements ConnectionFactory, ManagedServiceFactory {
+
+    public static final String FACTORY_PID = "org.apache.ace.connectionfactory";
+
+    private static final String HTTP_HEADER_AUTHORIZATION = "Authorization";
+
+    private final Map<String /* config PID */, UrlCredentials> m_credentialMapping;
+
+    /**
+     * Creates a new {@link ConnectionFactoryImpl}.
+     */
+    public ConnectionFactoryImpl() {
+        m_credentialMapping = new HashMap<String, UrlCredentials>();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URLConnection createConnection(URL url) throws IOException {
+        if (url == null) {
+            throw new IllegalArgumentException("URL cannot be null!");
+        }
+
+        URLConnection conn = url.openConnection();
+
+        UrlCredentials creds = getCredentials(url);
+        if (creds != null) {
+            supplyCredentials(conn, creds);
+        }
+
+        return conn;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URLConnection createConnection(URL url, User user) throws IOException {
+        if (url == null) {
+            throw new IllegalArgumentException("URL cannot be null!");
+        }
+        if (user == null) {
+            throw new IllegalArgumentException("User cannot be null!");
+        }
+
+        URLConnection conn = url.openConnection();
+
+        UrlCredentials creds = getCredentials(url);
+        if (creds != null) {
+            // TODO apply user!
+            supplyCredentials(conn, creds);
+        }
+
+        return conn;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void deleted(String pid) {
+        synchronized (m_credentialMapping) {
+            m_credentialMapping.remove(pid);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getName() {
+        return "HTTP Connection Factory";
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void updated(String pid, Dictionary properties) throws ConfigurationException {
+        UrlCredentials creds;
+        synchronized (m_credentialMapping) {
+            creds = m_credentialMapping.get(pid);
+        }
+
+        try {
+            creds = UrlCredentialsFactory.getCredentials(properties);
+
+            synchronized (m_credentialMapping) {
+                m_credentialMapping.put(pid, creds);
+            }
+        }
+        catch (MissingValueException e) {
+            throw new ConfigurationException(e.getProperty(), e.getMessage());
+        }
+    }
+
+    /**
+     * Returns the credentials to access the given URL.
+     * 
+     * @param url the URL to find the credentials for, cannot be <code>null</code>.
+     * @return a {@link UrlCredentials} instance for the given URL, or <code>null</code>
+     *         if none were found, or if none were necessary.
+     */
+    final UrlCredentials getCredentials(URL url) {
+        Collection<UrlCredentials> creds;
+        synchronized (m_credentialMapping) {
+            creds = new ArrayList<UrlCredentials>(m_credentialMapping.values());
+        }
+
+        for (UrlCredentials c : creds) {
+            if (c.matches(url)) {
+                return c;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the authorization header for HTTP Basic Authentication.
+     * 
+     * @param values the credential values to supply, cannot be <code>null</code> and should be an array of two elements.
+     * @return a string that denotes the basic authentication header ("Basic " + encoded credentials), never <code>null</code>.
+     */
+    final String getBasicAuthCredentials(Object[] values) {
+        if ((values == null) || values.length < 2) {
+            throw new IllegalArgumentException("Insufficient credentials passed: expected 2 values!");
+        }
+
+        StringBuilder sb = new StringBuilder();
+        if (values[0] instanceof String) {
+            sb.append((String) values[0]);
+        }
+        else if (values[0] instanceof byte[]) {
+            sb.append(new String((byte[]) values[0]));
+        }
+        sb.append(':');
+        if (values[1] instanceof String) {
+            sb.append((String) values[1]);
+        }
+        else if (values[1] instanceof byte[]) {
+            sb.append(new String((byte[]) values[1]));
+        }
+
+        return "Basic " + new String(Base64.encodeBase64(sb.toString().getBytes()));
+    }
+
+    /**
+     * Applies basic authentication to the given connection, if it is a {@link HttpURLConnection}.
+     * 
+     * @param conn the connection to apply basic authentication to;
+     * @param values the credentials to apply.
+     */
+    private void applyBasicAuthentication(URLConnection conn, Object[] values) {
+        if (conn instanceof HttpURLConnection) {
+            conn.setRequestProperty(HTTP_HEADER_AUTHORIZATION, getBasicAuthCredentials(values));
+        }
+    }
+
+    /**
+     * Applies the use of client certificates to the given connection, if it a {@link HttpsURLConnection}.
+     * 
+     * @param conn the connection to apply client certs to;
+     * @param values the credentials to apply.
+     */
+    private void applyClientCertificate(URLConnection conn, Object[] values) {
+        if (conn instanceof HttpsURLConnection) {
+            ((HttpsURLConnection) conn).setSSLSocketFactory(((SSLContext) values[0]).getSocketFactory());
+        }
+    }
+
+    /**
+     * Supplies the actual credentials to the given {@link URLConnection}.
+     * 
+     * @param conn the connection to supply the credentials to, cannot be <code>null</code>;
+     * @param urlCreds the URL credentials to supply, cannot be <code>null</code>.
+     * @throws IOException in case of I/O problems.
+     */
+    private void supplyCredentials(URLConnection conn, UrlCredentials urlCreds) throws IOException {
+        final AuthType type = urlCreds.getType();
+        final Object[] creds = urlCreds.getCredentials();
+
+        if (AuthType.BASIC.equals(type)) {
+            applyBasicAuthentication(conn, creds);
+        }
+        else if (AuthType.CLIENT_CERT.equals(type)) {
+            applyClientCertificate(conn, creds);
+        }
+        else if (!AuthType.NONE.equals(type)) {
+            throw new IllegalArgumentException("Unknown authentication type: " + type);
+        }
+    }
+}

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/UrlCredentials.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/UrlCredentials.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/UrlCredentials.java (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/UrlCredentials.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,146 @@
+/*
+ * 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.ace.connectionfactory.impl;
+
+import java.net.URL;
+import java.util.Arrays;
+
+/**
+ * Small container for holding URL credentials.
+ */
+final class UrlCredentials {
+
+    static enum AuthType {
+        /** Indicates no authentication. */
+        NONE,
+        /** Indicates basic HTTP authentication. */
+        BASIC,
+        /** Indicates the use of client certificates. */
+        CLIENT_CERT;
+    }
+
+    private final AuthType m_type;
+    private final URL m_baseURL;
+    private final Object[] m_credentials;
+
+    /**
+     * Creates a new, anonymous, {@link UrlCredentials} instance.
+     * 
+     * @param baseURL the base URL for which to apply the credentials, cannot be <code>null</code>.
+     */
+    public UrlCredentials(URL baseURL) {
+        this(AuthType.NONE, baseURL);
+    }
+
+    /**
+     * Creates a new {@link UrlCredentials} instance.
+     * 
+     * @param type the authentication type to use for the authentication of the URL, cannot be <code>null</code>;
+     * @param baseURL the base URL for which to apply the credentials, cannot be <code>null</code>;
+     * @param credentials the credentials to use, cannot be <code>null</code>, but may be empty.
+     */
+    public UrlCredentials(AuthType type, URL baseURL, Object... credentials) {
+        if (type == null) {
+            throw new IllegalArgumentException("Type cannot be null!");
+        }
+        if (baseURL == null) {
+            throw new IllegalArgumentException("BaseURL cannot be null!");
+        }
+        m_type = type;
+        m_baseURL = baseURL;
+        m_credentials = (credentials == null) ? new Object[0] : credentials.clone();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+
+        UrlCredentials other = (UrlCredentials) obj;
+        if (m_type != other.m_type) {
+            return false;
+        }
+        if (!m_baseURL.equals(other.m_baseURL)) {
+            return false;
+        }
+        if (!Arrays.equals(m_credentials, other.m_credentials)) {
+            return false;
+        }
+        return true;
+    }
+    
+    /**
+     * Returns whether or not the given URL can be mapped to our own base URL.
+     * 
+     * @param url the URL to map, may be <code>null</code> in which case <code>false</code> will be returned.
+     * @return <code>true</code> if the given URL maps to our base URL, <code>false</code> otherwise.
+     */
+    public boolean matches(URL url) {
+        if (url == null) {
+            return false;
+        }
+        
+        String baseURL = m_baseURL.toExternalForm();
+        return url.toExternalForm().startsWith(baseURL);
+    }
+
+    /**
+     * Returns the credentials for a URL.
+     * 
+     * @return the credentials, never <code>null</code>.
+     */
+    public Object[] getCredentials() {
+        return m_credentials.clone();
+    }
+
+    /**
+     * Returns the authentication type.
+     * 
+     * @return the type of authentication to use.
+     */
+    public AuthType getType() {
+        return m_type;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((m_type == null) ? 0 : m_type.hashCode());
+        result = prime * result + ((m_baseURL == null) ? 0 : m_baseURL.hashCode());
+        result = prime * result + Arrays.hashCode(m_credentials);
+        return result;
+    }
+
+    /**
+     * @return the base URL these credentials apply to, cannot be <code>null</code>.
+     */
+    final URL getBaseURL() {
+        return m_baseURL;
+    }
+}

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,281 @@
+/*
+ * 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.ace.connectionfactory.impl;
+
+import java.io.Closeable;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.util.Dictionary;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.apache.ace.connectionfactory.impl.UrlCredentials.AuthType;
+
+/**
+ * Provides a helper class for obtaining access credentials from a dictionary.
+ */
+final class UrlCredentialsFactory {
+
+    public static final class MissingValueException extends RuntimeException {
+        private final String m_property;
+
+        /**
+         * @param property the name of the missing property;
+         * @param message the message explaining the missing property. 
+         */
+        public MissingValueException(String property) {
+            this(property, "No value for " + property + " given!");
+        }
+
+        /**
+         * @param property the name of the missing property;
+         * @param message the message explaining the missing property. 
+         */
+        public MissingValueException(String property, String message) {
+            super(message);
+            m_property = property;
+        }
+        
+        /**
+         * Returns the name of the missing property.
+         * @return the property name, never <code>null</code>.
+         */
+        public String getProperty() {
+            return m_property;
+        }
+    }
+
+    public static final String KEY_AUTH_BASE_URL = "authentication.baseURL";
+    public static final String KEY_AUTH_TYPE = "authentication.type";
+    public static final String KEY_AUTH_USER_NAME = "authentication.user.name";
+    public static final String KEY_AUTH_USER_PASSWORD = "authentication.user.password";
+    public static final String KEY_AUTH_KEYSTORE_FILE = "authentication.keystore.file";
+    public static final String KEY_AUTH_KEYSTORE_PASS = "authentication.keystore.storepass";
+    public static final String KEY_AUTH_TRUSTSTORE_FILE = "authentication.truststore.file";
+    public static final String KEY_AUTH_TRUSTSTORE_PASS = "authentication.truststore.storepass";
+    
+    /**
+     * Not used.
+     */
+    private UrlCredentialsFactory() {
+        // Nop
+    }
+
+    /**
+     * @param props the properties to take the access credentials from.
+     * @throws MissingValueException in case the given properties is missing values.
+     */
+    public static UrlCredentials getCredentials(Dictionary props) throws MissingValueException {
+        return getCredentials(props, "");
+    }
+    
+    /**
+     * @param props the properties to take the access credentials from;
+     * @param prefix the prefix to use to lookup the correct values in the given dictionary.
+     * @throws MissingValueException in case the given properties is missing values.
+     */
+    public static UrlCredentials getCredentials(Dictionary props, String prefix) throws MissingValueException {
+        if (props == null) {
+            throw new IllegalArgumentException("Properties cannot be null!");
+        }
+        if (prefix == null) {
+            throw new IllegalArgumentException("Prefix cannot be null!");
+        }
+
+        AuthType type;
+        URL baseURL; 
+        Object[] creds;
+        
+        String baseUrlValue = getStringProperty(props, prefix.concat(KEY_AUTH_BASE_URL));
+        if (baseUrlValue == null) {
+            throw new MissingValueException(KEY_AUTH_BASE_URL);
+        }
+        
+        try {
+            baseURL = new URL(baseUrlValue);
+        }
+        catch (MalformedURLException e) {
+            throw new MissingValueException(KEY_AUTH_BASE_URL, "Invalid base URL!");
+        }
+
+        String authType = getStringProperty(props, prefix.concat(KEY_AUTH_TYPE), "none");
+        try {
+            type = AuthType.valueOf(authType.toUpperCase());
+        }
+        catch (Exception e) {
+            throw new IllegalArgumentException("Unsupported authentication type: " + authType);
+        }
+        
+        if (AuthType.NONE.equals(type)) {
+            creds = new Object[0];
+        } else if (AuthType.BASIC.equals(type)) {
+            String userName = getStringProperty(props, prefix.concat(KEY_AUTH_USER_NAME));
+            if (userName == null) {
+                throw new MissingValueException(prefix.concat(KEY_AUTH_USER_NAME));
+            }
+
+            String password = getStringProperty(props, prefix.concat(KEY_AUTH_USER_PASSWORD));
+            if (password == null) {
+                throw new MissingValueException(prefix.concat(KEY_AUTH_USER_PASSWORD));
+            }
+
+            creds = new Object[] { userName, password };
+        } else if (AuthType.CLIENT_CERT.equals(type)) {
+            String keystoreFile = getStringProperty(props, prefix.concat(KEY_AUTH_KEYSTORE_FILE));
+            String keystorePass = getStringProperty(props, prefix.concat(KEY_AUTH_KEYSTORE_PASS));
+            if ((keystoreFile != null) && (keystorePass == null)) {
+                throw new MissingValueException(prefix.concat(KEY_AUTH_KEYSTORE_PASS));
+            }
+            if ((keystoreFile == null) && (keystorePass != null)) {
+                throw new MissingValueException(prefix.concat(KEY_AUTH_KEYSTORE_FILE));
+            }
+            
+            String truststoreFile = getStringProperty(props, prefix.concat(KEY_AUTH_TRUSTSTORE_FILE));            
+            String truststorePass = getStringProperty(props, prefix.concat(KEY_AUTH_TRUSTSTORE_PASS));
+            if ((truststoreFile != null) && (truststorePass == null)) {
+                throw new MissingValueException(prefix.concat(KEY_AUTH_TRUSTSTORE_PASS));
+            }
+            if ((truststoreFile == null) && (truststorePass != null)) {
+                throw new MissingValueException(prefix.concat(KEY_AUTH_TRUSTSTORE_FILE));
+            }
+
+            if ((keystoreFile == null) && (truststoreFile == null)) {
+                try {
+                    // No configuration given; use the system-wide defaults...
+                    creds = new Object[] { SSLContext.getDefault() };
+                }
+                catch (Exception e) {
+                    throw new IllegalArgumentException("Failed to obtain SSL context!", e);
+                }
+            } else {
+                try {
+                    KeyManager[] keyManagers = getKeyManagerFactory(keystoreFile, keystorePass);
+                    TrustManager[] trustManagers = getTrustManagerFactory(truststoreFile, truststorePass);
+
+                    SSLContext context = SSLContext.getInstance("TLS");
+                    context.init(keyManagers, trustManagers, new SecureRandom());
+
+                    creds = new Object[] { context };
+                }
+                catch (Exception e) {
+                    throw new IllegalArgumentException("Failed to load keystore!", e);
+                }
+            }
+        } else {
+            throw new IllegalArgumentException("Invalid/unhandled authentication type: " + authType);
+        }
+
+        return new UrlCredentials(type, baseURL, creds);
+    }
+
+    private static String getStringProperty(Dictionary dict, String key) {
+        Object value = dict.get(key);
+        if (value instanceof String) {
+            return (String) value;
+        } else if (value instanceof byte[]) {
+            return new String((byte[]) value);
+        }
+        return null;
+    }
+
+    private static String getStringProperty(Dictionary dict, String key, String defaultValue) {
+        String value = getStringProperty(dict, key);
+        return (value == null) ? defaultValue : value;
+    }
+
+    /**
+     * @param keystoreFile
+     * @param storePass
+     * @return
+     * @throws IOException
+     * @throws GeneralSecurityException
+     */
+    private static KeyManager[] getKeyManagerFactory(String keystoreFile, String storePass) throws IOException, GeneralSecurityException {
+        if (keystoreFile == null) {
+            return null;
+        }
+
+        InputStream keyInput = null;
+        try {
+            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+            
+            keyInput = new FileInputStream(keystoreFile);
+            
+            keyStore.load(keyInput, storePass.toCharArray());
+            
+            keyManagerFactory.init(keyStore, storePass.toCharArray());
+            return keyManagerFactory.getKeyManagers();
+        }
+        finally {
+            closeSafely(keyInput);
+        }
+    }
+
+    /**
+     * @param truststoreFile
+     * @param storePass
+     * @return
+     * @throws IOException
+     * @throws GeneralSecurityException
+     */
+    private static TrustManager[] getTrustManagerFactory(String truststoreFile, String storePass) throws IOException, GeneralSecurityException {
+        if (truststoreFile == null) {
+            return null;
+        }
+
+        InputStream trustInput = null;
+        try {
+            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+            
+            trustInput = new FileInputStream(truststoreFile);
+            
+            trustStore.load(trustInput, storePass.toCharArray());
+            
+            trustManagerFactory.init(trustStore);
+            return trustManagerFactory.getTrustManagers();
+        }
+        finally {
+            closeSafely(trustInput);
+        }
+    }
+    
+    private static void closeSafely(Closeable resource) {
+        try {
+            if (resource != null) {
+                resource.close();
+            }
+        }
+        catch (IOException e) {
+            // Ignore; nothing we can/will do...
+        }
+    }
+}

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/packageinfo
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/packageinfo?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/packageinfo (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/src/org/apache/ace/connectionfactory/packageinfo Thu Jul  5 12:09:30 2012
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/ConnectionFactoryImplTest.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/ConnectionFactoryImplTest.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/ConnectionFactoryImplTest.java (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/ConnectionFactoryImplTest.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,169 @@
+/*
+ * 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.ace.connectionfactory.impl;
+
+import static org.apache.ace.test.utils.TestUtils.UNIT;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Properties;
+
+import org.testng.annotations.Test;
+
+/**
+ * Test cases for {@link ConnectionFactoryImpl}.
+ */
+public class ConnectionFactoryImplTest {
+
+    private static final URL TEST_URL;
+    
+    static {
+        try {
+            TEST_URL = new URL("http://localhost:8080/");
+        }
+        catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.ConnectionFactoryImpl#createConnection(java.net.URL)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = IllegalArgumentException.class)
+    public void testCreateConnectionNullUrlFail() throws Exception {
+        new ConnectionFactoryImpl().createConnection(null);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.ConnectionFactoryImpl#createConnection(java.net.URL, org.osgi.service.useradmin.User)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = IllegalArgumentException.class)
+    public void testCreateConnectionNullUserFail() throws Exception {
+        new ConnectionFactoryImpl().createConnection(new URL("file:///tmp/foo"), null);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.ConnectionFactoryImpl#createConnection(java.net.URL, org.osgi.service.useradmin.User)}.
+     */
+    @Test(groups = { UNIT })
+    public void testCreateConnectionOk() throws Exception {
+        URLConnection conn = new ConnectionFactoryImpl().createConnection(new URL("file:///tmp/foo"));
+        assert conn != null : "Expected valid connection to be created!";
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.ConnectionFactoryImpl#deleted(java.lang.String)}.
+     */
+    @Test(groups = { UNIT })
+    public void testDeleted() throws Exception {
+        ConnectionFactoryImpl connFactory = new ConnectionFactoryImpl();
+
+        Properties props = createBasicAuthConfig(TEST_URL.toExternalForm());
+
+        connFactory.updated("pid1", props);
+        
+        UrlCredentials credentials = connFactory.getCredentials(TEST_URL);
+        assert credentials != null : "Expected valid credentials to be found!";
+
+        connFactory.deleted("pid1");
+        
+        credentials = connFactory.getCredentials(TEST_URL);
+        assert credentials == null : "Expected no credentials to be found!";
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.ConnectionFactoryImpl#getBasicAuthCredentials(UrlCredentials)}.
+     */
+    @Test(groups = { UNIT })
+    public void testGetBasicAuthCredentialsOk() throws Exception {
+        ConnectionFactoryImpl connFactory = new ConnectionFactoryImpl();
+
+        Properties props = createBasicAuthConfig(TEST_URL.toExternalForm());
+
+        connFactory.updated("pid1", props);
+
+        UrlCredentials credentials = connFactory.getCredentials(TEST_URL);
+        assert credentials != null : "Expected valid credentials to be found!";
+
+        String header = new ConnectionFactoryImpl().getBasicAuthCredentials(credentials.getCredentials());
+        assert header != null : "Expected valid HTTP header to be returned!";
+        assert header.equals(header.trim()) : "Expected HTTP header not to contain any leading/trailing whitespace!";
+        assert "Basic Zm9vOmJhcg==".equals(header) : "Expected HTTP header to be constant!";
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.ConnectionFactoryImpl#updated(java.lang.String, java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT })
+    public void testUpdatedInsertsCredentialsOk() throws Exception {
+        ConnectionFactoryImpl connFactory = new ConnectionFactoryImpl();
+        
+        UrlCredentials credentials = connFactory.getCredentials(TEST_URL);
+        assert credentials == null : "Expected no credentials to be found!";
+        
+        Properties props = createBasicAuthConfig(TEST_URL.toExternalForm());
+
+        connFactory.updated("pid1", props);
+        
+        credentials = connFactory.getCredentials(TEST_URL);
+        assert credentials != null : "Expected valid credentials to be found!";
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.ConnectionFactoryImpl#updated(java.lang.String, java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT })
+    public void testUpdatedUpdatesCredentialsOk() throws Exception {
+        ConnectionFactoryImpl connFactory = new ConnectionFactoryImpl();
+
+        Properties props = createBasicAuthConfig(TEST_URL.toExternalForm());
+
+        connFactory.updated("pid1", props);
+        
+        UrlCredentials credentials1 = connFactory.getCredentials(TEST_URL);
+        assert credentials1 != null : "Expected valid credentials to be found!";
+        
+        URL newURL = new URL("http://localhost:8181/test/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, newURL.toExternalForm());
+
+        connFactory.updated("pid1", props);
+
+        UrlCredentials credentials2 = connFactory.getCredentials(TEST_URL);
+        assert credentials2 == null : "Expected no credentials to be found!";
+
+        credentials2 = connFactory.getCredentials(newURL);
+        assert credentials2 != null : "Expected valid credentials to be found!";
+        
+        assert credentials1 != credentials2 && !credentials1.equals(credentials2) : "Expected not the same credentials to be returned!";
+    }
+
+    /**
+     * @return a dictionary containing a configuration for basic authentication, never <code>null</code>.
+     */
+    private Properties createBasicAuthConfig(String url) {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, url);
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "basic");
+        props.put(UrlCredentialsFactory.KEY_AUTH_USER_NAME, "foo");
+        props.put(UrlCredentialsFactory.KEY_AUTH_USER_PASSWORD, "bar");
+        return props;
+    }
+}

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/UrlCredentialsFactoryTest.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/UrlCredentialsFactoryTest.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/UrlCredentialsFactoryTest.java (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/UrlCredentialsFactoryTest.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,205 @@
+/*
+ * 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.ace.connectionfactory.impl;
+
+import static org.apache.ace.test.utils.TestUtils.UNIT;
+
+import java.util.Properties;
+
+import org.apache.ace.connectionfactory.impl.UrlCredentialsFactory.MissingValueException;
+import org.testng.annotations.Test;
+
+/**
+ * Test cases for {@link UrlCredentialsFactory}.
+ */
+public class UrlCredentialsFactoryTest {
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+    public void testGetCredentialsWithDictionaryBasicTypeMissingPasswordFail() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, "http://localhost:8080/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "basic");
+        props.put(UrlCredentialsFactory.KEY_AUTH_USER_NAME, "bar");
+
+        UrlCredentialsFactory.getCredentials(props);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+    public void testGetCredentialsWithDictionaryClientCertTypeMissingKeystorePasswordFail() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, "http://localhost:8080/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "client_cert");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_FILE, "bar");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_PASS, "qux");
+        props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_FILE, "foo");
+
+        UrlCredentialsFactory.getCredentials(props);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+    public void testGetCredentialsWithDictionaryClientCertTypeMissingKeystoreFileFail() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, "http://localhost:8080/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "client_cert");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_FILE, "bar");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_PASS, "qux");
+        props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_PASS, "foo");
+
+        UrlCredentialsFactory.getCredentials(props);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT })
+    public void testGetCredentialsWithDictionaryClientCertTypeOk() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, "http://localhost:8080/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "client_cert");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_FILE, "foo");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_PASS, "bar");
+        props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_FILE, "qux");
+        props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_PASS, "quu");
+
+        try {
+            UrlCredentialsFactory.getCredentials(props);
+        }
+        catch (IllegalArgumentException e) {
+            // Ok; expected as the implementation tries to open the files "foo" and "qux"...
+        }
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+    public void testGetCredentialsWithDictionaryClientCertTypeMissingTruststorePasswordFail() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, "http://localhost:8080/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "client_cert");
+        props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_FILE, "bar");
+        props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_PASS, "qux");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_FILE, "foo");
+
+        UrlCredentialsFactory.getCredentials(props);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+    public void testGetCredentialsWithDictionaryClientCertTypeMissingTruststoreFileFail() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, "http://localhost:8080/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "client_cert");
+        props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_FILE, "bar");
+        props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_PASS, "qux");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_PASS, "foo");
+
+        UrlCredentialsFactory.getCredentials(props);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+    public void testGetCredentialsWithDictionaryBasicTypeMissingUserNameFail() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, "http://localhost:8080/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "basic");
+        props.put(UrlCredentialsFactory.KEY_AUTH_USER_PASSWORD, "bar");
+
+        UrlCredentialsFactory.getCredentials(props);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT })
+    public void testGetCredentialsWithDictionaryBasicTypeOk() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, "http://localhost:8080/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "basic");
+        props.put(UrlCredentialsFactory.KEY_AUTH_USER_NAME, "foo");
+        props.put(UrlCredentialsFactory.KEY_AUTH_USER_PASSWORD, "bar");
+
+        UrlCredentialsFactory.getCredentials(props);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = IllegalArgumentException.class)
+    public void testGetCredentialsWithDictionaryInvalidAuthTypeFail() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, "http://localhost:8080/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "nonsense");
+
+        UrlCredentialsFactory.getCredentials(props);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+    public void testGetCredentialsWithDictionaryMissingBaseUrlFail() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "none");
+
+        UrlCredentialsFactory.getCredentials(props);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = IllegalArgumentException.class)
+    public void testGetCredentialsWithNullDictionaryFail() {
+        UrlCredentialsFactory.getCredentials(null);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary, java.lang.String)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = IllegalArgumentException.class)
+    public void testGetCredentialsWithNullPrefixFail() {
+        UrlCredentialsFactory.getCredentials(new Properties(), null);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+     */
+    @Test(groups = { UNIT })
+    public void testGetCredentialsWithValidDictionaryOk() {
+        Properties props = new Properties();
+        props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL, "http://localhost:8080/");
+        props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "none");
+
+        UrlCredentialsFactory.getCredentials(props);
+    }
+}

Added: ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/UrlCredentialsTest.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/UrlCredentialsTest.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/UrlCredentialsTest.java (added)
+++ ace/sandbox/marrs/org.apache.ace.connectionfactory/test/org/apache/ace/connectionfactory/impl/UrlCredentialsTest.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,116 @@
+/*
+ * 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.ace.connectionfactory.impl;
+
+import static org.apache.ace.test.utils.TestUtils.UNIT;
+
+import java.net.URL;
+
+import org.apache.ace.connectionfactory.impl.UrlCredentials.AuthType;
+import org.testng.annotations.Test;
+
+/**
+ * Test cases for {@link UrlCredentials}.
+ */
+public class UrlCredentialsTest {
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentials#UrlCredentials(java.net.URL)}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = IllegalArgumentException.class)
+    public void testUrlCredentialsNullURLFail() throws Exception {
+        new UrlCredentials(null);
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentials#UrlCredentials(java.net.URL)}.
+     */
+    @Test(groups = { UNIT })
+    public void testUrlCredentialsURLOk() throws Exception {
+        new UrlCredentials(new URL("http://localhost:8080/"));
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentials#UrlCredentials(org.apache.ace.connectionfactory.impl.UrlCredentials.AuthType, java.net.URL, java.lang.Object[])}.
+     */
+    @Test(groups = { UNIT }, expectedExceptions = IllegalArgumentException.class)
+    public void testUrlCredentialsNullTypeFail() throws Exception {
+        new UrlCredentials(null, new URL("http://localhost:8080/"));
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentials#UrlCredentials(org.apache.ace.connectionfactory.impl.UrlCredentials.AuthType, java.net.URL, java.lang.Object[])}.
+     */
+    @Test(groups = { UNIT })
+    public void testUrlCredentialsTypeAndURLOk() throws Exception {
+        new UrlCredentials(AuthType.NONE, new URL("http://localhost:8080/"));
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentials#matches(java.net.URL)}.
+     */
+    @Test(groups = { UNIT })
+    public void testMatchesNullURLOk() throws Exception {
+        UrlCredentials creds = new UrlCredentials(AuthType.NONE, new URL("http://localhost:8080/"));
+        assert creds.matches(null) == false : "Null URL should never match any credentials!";
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentials#matches(java.net.URL)}.
+     */
+    @Test(groups = { UNIT })
+    public void testMatchesValidURLOk() throws Exception {
+        UrlCredentials creds = new UrlCredentials(AuthType.NONE, new URL("http://localhost:8080/"));
+        assert creds.matches(new URL("http://localhost:8080/obr")) : "Base URL should match given URL!";
+        assert creds.matches(new URL("http://localhost:8080")) == false : "Base URL shouldn't match given URL!";
+        assert creds.matches(new URL("http://localhost:8081/")) == false : "Base URL shouldn't match given URL!";
+    }
+
+    /**
+     * Test method for {@link org.apache.ace.connectionfactory.impl.UrlCredentials#getCredentials()}.
+     */
+    @Test(groups = { UNIT })
+    public void testGetCredentialsOk() throws Exception {
+        UrlCredentials creds = new UrlCredentials(AuthType.NONE, new URL("http://localhost:8080/"));
+        assertArrayEquals(new Object[0], creds.getCredentials());
+
+        creds = new UrlCredentials(AuthType.NONE, new URL("http://localhost:8080/"), "foo");
+        assertArrayEquals(new Object[] { "foo" }, creds.getCredentials());
+
+        creds = new UrlCredentials(AuthType.NONE, new URL("http://localhost:8080/"), (Object[]) null );
+        assertArrayEquals(new Object[0], creds.getCredentials());
+
+        creds = new UrlCredentials(AuthType.NONE, new URL("http://localhost:8080/"), (Object) null);
+        assertArrayEquals(new Object[] { null }, creds.getCredentials());
+    }
+
+    /**
+     * Asserts that two given arrays are equal with respect to their content.
+     * 
+     * @param expected the expected array;
+     * @param given the given array to test.
+     */
+    private void assertArrayEquals(Object[] expected, Object[] given) {
+        assert expected != null && given != null : "Both arrays should never be null!";
+        assert expected.length == given.length : "Length mismatch!";
+        for (int i = 0; i < expected.length; i++) {
+            assert (expected[i] == given[i]) || (expected[i] != null && expected[i].equals(given[i])) : "Elements at index #" + i + " do not match!";
+        }
+    }
+}

Added: ace/sandbox/marrs/org.apache.ace.consolelogger/.classpath
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.consolelogger/.classpath?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.consolelogger/.classpath (added)
+++ ace/sandbox/marrs/org.apache.ace.consolelogger/.classpath Thu Jul  5 12:09:30 2012
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: ace/sandbox/marrs/org.apache.ace.consolelogger/.project
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.consolelogger/.project?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.consolelogger/.project (added)
+++ ace/sandbox/marrs/org.apache.ace.consolelogger/.project Thu Jul  5 12:09:30 2012
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.ace.consolelogger</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>

Added: ace/sandbox/marrs/org.apache.ace.consolelogger/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.consolelogger/bnd.bnd?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.consolelogger/bnd.bnd (added)
+++ ace/sandbox/marrs/org.apache.ace.consolelogger/bnd.bnd Thu Jul  5 12:09:30 2012
@@ -0,0 +1,5 @@
+-buildpath: osgi.core,\
+	osgi.cmpn,\
+	org.apache.felix.dependencymanager
+Private-Package: org.apache.ace.consolelogger
+Bundle-Activator: org.apache.ace.consolelogger.Activator
\ No newline at end of file

Added: ace/sandbox/marrs/org.apache.ace.consolelogger/build.xml
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.consolelogger/build.xml?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.consolelogger/build.xml (added)
+++ ace/sandbox/marrs/org.apache.ace.consolelogger/build.xml Thu Jul  5 12:09:30 2012
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build"> 
+	<import file="../cnf/build.xml"/>
+</project>

Added: ace/sandbox/marrs/org.apache.ace.consolelogger/pom.xml
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.consolelogger/pom.xml?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.consolelogger/pom.xml (added)
+++ ace/sandbox/marrs/org.apache.ace.consolelogger/pom.xml Thu Jul  5 12:09:30 2012
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ace</groupId>
+        <artifactId>ace-pom</artifactId>
+        <version>0.8.1-SNAPSHOT</version>
+        <relativePath>../pom/pom.xml</relativePath>
+    </parent>
+
+    <version>0.8.1-SNAPSHOT</version>
+    <artifactId>org.apache.ace.consolelogger</artifactId>
+    <packaging>bundle</packaging>
+
+    <name>Apache ACE :: ConsoleLogger</name>
+    <description />
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/ace/trunk/ace-consolelogger</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/ace/trunk/ace-consolelogger</developerConnection>
+        <url>http://svn.apache.org/repos/asf/ace/trunk/ace-consolelogger</url>
+    </scm>
+
+    <properties>
+        <import.package>
+            *
+        </import.package>
+        <private.package>
+            org.apache.ace.consolelogger
+        </private.package>
+        <bundle.activator>
+            org.apache.ace.consolelogger.Activator
+        </bundle.activator>
+    </properties>
+
+    <dependencies>
+        <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.felix</groupId>
+            <artifactId>org.apache.felix.dependencymanager</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

Added: ace/sandbox/marrs/org.apache.ace.consolelogger/src/org/apache/ace/consolelogger/Activator.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.consolelogger/src/org/apache/ace/consolelogger/Activator.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.consolelogger/src/org/apache/ace/consolelogger/Activator.java (added)
+++ ace/sandbox/marrs/org.apache.ace.consolelogger/src/org/apache/ace/consolelogger/Activator.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,36 @@
+/*
+ * 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.ace.consolelogger;
+
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+
+public class Activator extends DependencyActivatorBase {
+    public void init(BundleContext context, DependencyManager manager) throws Exception {
+        manager.add(createComponent()
+            .setInterface(LogService.class.getName(), null)
+            .setImplementation(Logger.class)
+        );
+    }
+
+    public void destroy(BundleContext context, DependencyManager manager) throws Exception {
+    }
+}
\ No newline at end of file

Added: ace/sandbox/marrs/org.apache.ace.consolelogger/src/org/apache/ace/consolelogger/Logger.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.consolelogger/src/org/apache/ace/consolelogger/Logger.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.consolelogger/src/org/apache/ace/consolelogger/Logger.java (added)
+++ ace/sandbox/marrs/org.apache.ace.consolelogger/src/org/apache/ace/consolelogger/Logger.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,72 @@
+/*
+ * 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.ace.consolelogger;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+/**
+ * An implementation of the OSGi LogService that directly outputs each log message
+ * to <code>System.out</code>. It does not implement the LogReader or LogListeners.
+ */
+public class Logger implements LogService {
+    private static String[] LEVEL = { "", "Error", "Warn ", "Info ", "Debug" };
+
+    public void log(int level, String message) {
+        log(null, level, message, null);
+    }
+
+    public void log(int level, String message, Throwable throwable) {
+        log(null, level, message, throwable);
+    }
+
+    public void log(ServiceReference reference, int level, String message) {
+        log(reference, level, message, null);
+    }
+
+    public void log(ServiceReference reference, int level, String message, Throwable throwable) {
+        String bundle = " [   ]";
+        String service = " ";
+        if (reference != null) {
+            bundle = "00" + reference.getBundle().getBundleId();
+            bundle = " [" + bundle.substring(bundle.length() - 3) + "]";
+            Object objectClass = reference.getProperty(Constants.OBJECTCLASS);
+            if (objectClass instanceof String[]) {
+                StringBuffer buffer = new StringBuffer();
+                String[] objClassArr = ((String[]) objectClass);
+                for (int i = 0; i < objClassArr.length; i++) {
+                    String svc = objClassArr[i];
+                    if (buffer.length() > 0) {
+                        buffer.append(';');
+                    }
+                    buffer.append(svc);
+                    service = buffer.toString() + ": ";
+                }
+            }
+            else {
+                service = objectClass.toString() + ": ";
+            }
+        }
+        System.out.println("[" + LEVEL[level] + "]" + bundle + service + message);
+        if (throwable != null) {
+            throwable.printStackTrace();
+        }
+    }
+}
\ No newline at end of file

Added: ace/sandbox/marrs/org.apache.ace.deployment.api/.classpath
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.deployment.api/.classpath?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.deployment.api/.classpath (added)
+++ ace/sandbox/marrs/org.apache.ace.deployment.api/.classpath Thu Jul  5 12:09:30 2012
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: ace/sandbox/marrs/org.apache.ace.deployment.api/.project
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.deployment.api/.project?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.deployment.api/.project (added)
+++ ace/sandbox/marrs/org.apache.ace.deployment.api/.project Thu Jul  5 12:09:30 2012
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.ace.deployment.api</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>

Added: ace/sandbox/marrs/org.apache.ace.deployment.api/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.deployment.api/bnd.bnd?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.deployment.api/bnd.bnd (added)
+++ ace/sandbox/marrs/org.apache.ace.deployment.api/bnd.bnd Thu Jul  5 12:09:30 2012
@@ -0,0 +1,3 @@
+-buildpath: osgi.core,\
+	osgi.cmpn
+Export-Package: org.apache.ace.deployment
\ No newline at end of file

Added: ace/sandbox/marrs/org.apache.ace.deployment.api/build.xml
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.deployment.api/build.xml?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.deployment.api/build.xml (added)
+++ ace/sandbox/marrs/org.apache.ace.deployment.api/build.xml Thu Jul  5 12:09:30 2012
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build"> 
+	<import file="../cnf/build.xml"/>
+</project>

Added: ace/sandbox/marrs/org.apache.ace.deployment.api/pom.xml
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.deployment.api/pom.xml?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.deployment.api/pom.xml (added)
+++ ace/sandbox/marrs/org.apache.ace.deployment.api/pom.xml Thu Jul  5 12:09:30 2012
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ace</groupId>
+        <artifactId>ace-pom</artifactId>
+        <version>0.8.1-SNAPSHOT</version>
+        <relativePath>../pom/pom.xml</relativePath>
+    </parent>
+
+    <version>0.8.1-SNAPSHOT</version>
+    <artifactId>org.apache.ace.deployment.api</artifactId>
+    <packaging>bundle</packaging>
+
+    <name>Apache ACE :: Deployment :: API</name>
+    <description />
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/ace/trunk/ace-deployment-api</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/ace/trunk/ace-deployment-api</developerConnection>
+        <url>http://svn.apache.org/repos/asf/ace/trunk/ace-deployment-api</url>
+    </scm>
+
+    <properties>
+        <export.package>
+            org.apache.ace.deployment;version=${project.version}
+        </export.package>
+        <import.package>
+            !org.apache.ace.deployment,
+            *
+        </import.package>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

Added: ace/sandbox/marrs/org.apache.ace.deployment.api/src/org/apache/ace/deployment/Deployment.java
URL: http://svn.apache.org/viewvc/ace/sandbox/marrs/org.apache.ace.deployment.api/src/org/apache/ace/deployment/Deployment.java?rev=1357570&view=auto
==============================================================================
--- ace/sandbox/marrs/org.apache.ace.deployment.api/src/org/apache/ace/deployment/Deployment.java (added)
+++ ace/sandbox/marrs/org.apache.ace.deployment.api/src/org/apache/ace/deployment/Deployment.java Thu Jul  5 12:09:30 2012
@@ -0,0 +1,68 @@
+/*
+ * 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.ace.deployment;
+
+import java.io.InputStream;
+import org.osgi.framework.Version;
+
+/**
+ * Service that abstracts the actual implementation that manages components that are to be deployed.
+ * Implementations of this interface could for example make use of the <code>DeploymentAdmin</code>
+ * from the OSGi spec to actually deploy packages. The objects used as arguments and return values
+ * must all be of the same type, which type depends on the implementation.
+ */
+public interface Deployment {
+
+    /**
+     * Deploys the contents of the stream onto the system.
+     *
+     * @param inputStream Stream containing new components.
+     * @return The update package that was installed, may be null if the implementation does not support this.
+     * @throws Exception If the specified stream could not be deployed.
+     */
+    public Object install(InputStream inputStream) throws Exception;
+
+    /**
+     * Gets the name of the specified update package. Guaranteed to work with <code>Object</code>s returned
+     * by the same implementation of this interface.
+     *
+     * @param object The update package
+     * @return the name
+     * @throws IllegalArgumentException when the specified object is an invalid update package, only Objects returned by the same implementation of this interface should be used.
+     */
+    public String getName(Object object) throws IllegalArgumentException;
+
+    /**
+     * Gets the version of the specified update package. Guaranteed to work with <code>Object</code>s returned
+     * by the same implementation of this interface.
+     *
+     * @param object The update package
+     * @return the version
+     * @throws IllegalArgumentException when the specified object is an invalid update package, only Objects returned by the same implementation of this interface should be used.
+     */
+    public Version getVersion(Object object) throws IllegalArgumentException;
+
+    /**
+     * Retrieve a list of installed update packages.
+     *
+     * @return list of installed update packages or an empty array if none are available.
+     */
+    public Object[] list();
+
+}
\ No newline at end of file