Author: rfeng
Date: Sat Jan 24 04:58:10 2009
New Revision: 737301

URL: http://svn.apache.org/viewvc?rev=737301&view=rev
Log:
Improve the OSGi based unit testing based on maven-surefire-plugin 2.4.3

Added:
    
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/
    
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/
    
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/
    
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java
   (with props)
    
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java
   (with props)
    
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefirePlugin.java
   (with props)
Removed:
    
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/equinox/
    
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/tools/
Modified:
    tuscany/java/sca/tools/maven/maven-osgi-junit/pom.xml

Modified: tuscany/java/sca/tools/maven/maven-osgi-junit/pom.xml
URL: 
http://svn.apache.org/viewvc/tuscany/java/sca/tools/maven/maven-osgi-junit/pom.xml?rev=737301&r1=737300&r2=737301&view=diff
==============================================================================
--- tuscany/java/sca/tools/maven/maven-osgi-junit/pom.xml (original)
+++ tuscany/java/sca/tools/maven/maven-osgi-junit/pom.xml Sat Jan 24 04:58:10 
2009
@@ -42,19 +42,29 @@
             <artifactId>maven-project</artifactId>
             <version>2.0.8</version>
         </dependency>
-        
+
+        <dependency>
+            <groupId>org.apache.maven.surefire</groupId>
+            <artifactId>surefire-booter</artifactId>
+            <version>2.4.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-core</artifactId>
+            <version>2.0.8</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-toolchain</artifactId>
+            <version>1.0</version>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.tuscany.sca</groupId>
             <artifactId>tuscany-node-launcher-equinox</artifactId>
             <version>2.0-SNAPSHOT</version>
         </dependency>
-        
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.5</version>
-            <scope>compile</scope>
-        </dependency>
 
     </dependencies>
 </project>

Added: 
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java
URL: 
http://svn.apache.org/viewvc/tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java?rev=737301&view=auto
==============================================================================
--- 
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java
 (added)
+++ 
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java
 Sat Jan 24 04:58:10 2009
@@ -0,0 +1,239 @@
+package org.apache.tuscany.sca.maven.plugin.surefire;
+
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.apache.maven.surefire.booter.SurefireBooterForkException;
+import 
org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.cli.Commandline;
+import org.apache.maven.surefire.util.UrlUtils;
+import org.codehaus.plexus.util.StringUtils;
+
+/**
+ * Derived from surefire-booter 2.4.3
+ * Configuration for forking tests.
+ *
+ */
+...@suppresswarnings("unchecked")
+public class ForkConfiguration {
+    public static final String FORK_ONCE = "once";
+
+    public static final String FORK_ALWAYS = "always";
+
+    public static final String FORK_NEVER = "never";
+
+    private String forkMode;
+
+    private boolean useSystemClassLoader;
+    private boolean useManifestOnlyJar;
+
+    private Properties systemProperties;
+
+    private String jvmExecutable;
+
+    private String argLine;
+
+    private Map environmentVariables;
+
+    private File workingDirectory;
+
+    private boolean debug;
+
+    private String debugLine;
+
+    public void setForkMode(String forkMode) {
+        if ("pertest".equalsIgnoreCase(forkMode)) {
+            this.forkMode = FORK_ALWAYS;
+        } else if ("none".equalsIgnoreCase(forkMode)) {
+            this.forkMode = FORK_NEVER;
+        } else if (forkMode.equals(FORK_NEVER) || forkMode.equals(FORK_ONCE) 
|| forkMode.equals(FORK_ALWAYS)) {
+            this.forkMode = forkMode;
+        } else {
+            throw new IllegalArgumentException("Fork mode " + forkMode + " is 
not a legal value");
+        }
+    }
+
+    public boolean isForking() {
+        return !FORK_NEVER.equals(forkMode);
+    }
+
+    public void setUseSystemClassLoader(boolean useSystemClassLoader) {
+        this.useSystemClassLoader = useSystemClassLoader;
+    }
+
+    public boolean isUseSystemClassLoader() {
+        return useSystemClassLoader;
+    }
+
+    public void setSystemProperties(Properties systemProperties) {
+        this.systemProperties = (Properties)systemProperties.clone();
+    }
+
+    public void setJvmExecutable(String jvmExecutable) {
+        this.jvmExecutable = jvmExecutable;
+    }
+
+    public void setArgLine(String argLine) {
+        this.argLine = argLine;
+    }
+
+    public void setDebugLine(String debugLine) {
+        this.debugLine = debugLine;
+    }
+
+    public void setEnvironmentVariables(Map environmentVariables) {
+        this.environmentVariables = new HashMap(environmentVariables);
+    }
+
+    public void setWorkingDirectory(File workingDirectory) {
+        this.workingDirectory = workingDirectory;
+    }
+
+    public String getForkMode() {
+        return forkMode;
+    }
+
+    public Properties getSystemProperties() {
+        return systemProperties;
+    }
+
+    /**
+     * @throws SurefireBooterForkException
+     * @deprecated use the 2-arg alternative.
+     */
+    public Commandline createCommandLine(List classPath) throws 
SurefireBooterForkException {
+        return createCommandLine(classPath, false);
+    }
+
+    public Commandline createCommandLine(List classPath, boolean useJar) 
throws SurefireBooterForkException {
+        Commandline cli = new Commandline();
+
+        cli.setExecutable(jvmExecutable);
+
+        if (argLine != null) {
+            cli.createArg().setLine(argLine);
+        }
+
+        if (environmentVariables != null) {
+            Iterator iter = environmentVariables.keySet().iterator();
+
+            while (iter.hasNext()) {
+                String key = (String)iter.next();
+
+                String value = (String)environmentVariables.get(key);
+
+                cli.addEnvironment(key, value);
+            }
+        }
+
+        if (debugLine != null && !"".equals(debugLine)) {
+            cli.createArg().setLine(debugLine);
+        }
+
+        if (useJar) {
+            File jarFile;
+            try {
+                jarFile = createJar(classPath);
+            } catch (IOException e) {
+                throw new SurefireBooterForkException("Error creating archive 
file", e);
+            }
+
+            cli.createArg().setValue("-jar");
+
+            cli.createArg().setValue(jarFile.getAbsolutePath());
+        } else {
+            cli.createArg().setValue("-classpath");
+
+            cli.createArg().setValue(StringUtils.join(classPath.iterator(), 
File.pathSeparator));
+
+            cli.createArg().setValue(OSGiSurefireBooter.class.getName());
+        }
+
+        cli.setWorkingDirectory(workingDirectory.getAbsolutePath());
+
+        return cli;
+    }
+
+    /**
+     * Create a jar with just a manifest containing a Main-Class entry for 
SurefireBooter and a Class-Path entry
+     * for all classpath elements.
+     *
+     * @param classPath List&lt;String> of all classpath elements.
+     * @return
+     * @throws IOException
+     */
+    private File createJar(List classPath) throws IOException {
+        File file = File.createTempFile("surefirebooter", ".jar");
+        if (!debug) {
+            file.deleteOnExit();
+        }
+        FileOutputStream fos = new FileOutputStream(file);
+        JarOutputStream jos = new JarOutputStream(fos);
+        jos.setLevel(JarOutputStream.STORED);
+        JarEntry je = new JarEntry("META-INF/MANIFEST.MF");
+        jos.putNextEntry(je);
+
+        Manifest man = new Manifest();
+
+        // we can't use StringUtils.join here since we need to add a '/' to
+        // the end of directory entries - otherwise the jvm will ignore them.
+        String cp = "";
+        for (Iterator it = classPath.iterator(); it.hasNext();) {
+            String el = (String)it.next();
+            // NOTE: if File points to a directory, this entry MUST end in '/'.
+            cp += UrlUtils.getURL(new File(el)).toExternalForm() + " ";
+        }
+
+        man.getMainAttributes().putValue("Manifest-Version", "1.0");
+        man.getMainAttributes().putValue("Class-Path", cp.trim());
+        man.getMainAttributes().putValue("Main-Class", 
OSGiSurefireBooter.class.getName());
+
+        man.write(jos);
+        jos.close();
+
+        return file;
+    }
+
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+
+    public boolean isDebug() {
+        return debug;
+    }
+
+    public void setUseManifestOnlyJar(boolean useManifestOnlyJar) {
+        this.useManifestOnlyJar = useManifestOnlyJar;
+    }
+
+    public boolean isUseManifestOnlyJar() {
+        return useManifestOnlyJar;
+    }
+}

Propchange: 
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/ForkConfiguration.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java
URL: 
http://svn.apache.org/viewvc/tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java?rev=737301&view=auto
==============================================================================
--- 
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java
 (added)
+++ 
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java
 Sat Jan 24 04:58:10 2009
@@ -0,0 +1,984 @@
+package org.apache.tuscany.sca.maven.plugin.surefire;
+
+/*
+ * 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.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.maven.surefire.Surefire;
+import org.apache.maven.surefire.booter.SurefireBooterForkException;
+import org.apache.maven.surefire.booter.SurefireExecutionException;
+import org.apache.maven.surefire.booter.output.FileOutputConsumerProxy;
+import org.apache.maven.surefire.booter.output.ForkingStreamConsumer;
+import org.apache.maven.surefire.booter.output.OutputConsumer;
+import org.apache.maven.surefire.booter.output.StandardOutputConsumer;
+import 
org.apache.maven.surefire.booter.output.SupressFooterOutputConsumerProxy;
+import 
org.apache.maven.surefire.booter.output.SupressHeaderOutputConsumerProxy;
+import org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.IOUtil;
+import 
org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.StringUtils;
+import 
org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.cli.Commandline;
+import 
org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.cli.StreamConsumer;
+import org.apache.maven.surefire.testset.TestSetFailedException;
+import org.apache.maven.surefire.util.NestedRuntimeException;
+import org.apache.tuscany.sca.node.equinox.launcher.EquinoxHost;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Derived from surefire-booter 2.4.3
+ */
+public class OSGiSurefireBooter {
+    private static final String TEST_SUITE_PROPERTY_PREFIX = "testSuite.";
+    private static final String REPORT_PROPERTY_PREFIX = "report.";
+    private static final String PARAMS_SUFIX = ".params";
+    private static final String TYPES_SUFIX = ".types";
+
+    /**
+     * A classloader that delegates an OSGi bundle
+     */
+    static class BundleClassLoader extends ClassLoader {
+        private Bundle bundle;
+
+        public BundleClassLoader(Bundle bundle, ClassLoader parent) {
+            super(parent);
+            this.bundle = bundle;
+        }
+
+        @Override
+        protected Class<?> findClass(String name) throws 
ClassNotFoundException {
+            return bundle.loadClass(name);
+        }
+
+        @Override
+        protected URL findResource(String name) {
+            return bundle.getResource(name);
+        }
+
+        @Override
+        protected Enumeration<URL> findResources(String name) throws 
IOException {
+            return bundle.getResources(name);
+        }
+
+    }
+
+    private List reports = new ArrayList();
+
+    /**
+     * Test classpath
+     */
+    private List classPathUrls = new ArrayList();
+
+    /**
+     * surefire provider classpath
+     */
+    private List surefireClassPathUrls = new ArrayList();
+
+    /**
+     * surefire boot classpath
+     */
+    private List surefireBootClassPathUrls = new ArrayList();
+
+    private List testSuites = new ArrayList();
+
+    private boolean failIfNoTests = false;
+
+    private int forkedProcessTimeoutInSeconds = 0;
+
+    private boolean redirectTestOutputToFile = false;
+
+    // ----------------------------------------------------------------------
+    //
+    // ----------------------------------------------------------------------
+
+    private ForkConfiguration forkConfiguration;
+
+    public static final int TESTS_SUCCEEDED_EXIT_CODE = 0;
+
+    public static final int TESTS_FAILED_EXIT_CODE = 255;
+
+    public static final int NO_TESTS_EXIT_CODE = 254;
+
+    private static Method assertionStatusMethod;
+
+    /**
+     * @deprecated because the OSGi classloader is really isolated - no parent.
+     */
+    private boolean childDelegation = true;
+
+    private File reportsDirectory;
+
+    /**
+     * This field is set to true if it's running from main. It's used to help 
decide what classloader to use.
+     */
+    private final boolean isForked;
+
+    /**
+     * Whether to enable assertions or not (can be affected by the fork 
arguments, and the ability to do so based on the
+     * JVM).
+     */
+    private boolean enableAssertions;
+
+    static {
+        try {
+            assertionStatusMethod =
+                ClassLoader.class.getMethod("setDefaultAssertionStatus", new 
Class[] {boolean.class});
+        } catch (NoSuchMethodException e) {
+            assertionStatusMethod = null;
+        }
+    }
+
+    public OSGiSurefireBooter() {
+        isForked = false;
+    }
+
+    private OSGiSurefireBooter(boolean isForked) {
+        this.isForked = isForked;
+    }
+
+    // ----------------------------------------------------------------------
+    // Accessors
+    // ----------------------------------------------------------------------
+
+    public void addReport(String report) {
+        addReport(report, null);
+    }
+
+    public void addReport(String report, Object[] constructorParams) {
+        reports.add(new Object[] {report, constructorParams});
+    }
+
+    public void addTestSuite(String suiteClassName, Object[] 
constructorParams) {
+        testSuites.add(new Object[] {suiteClassName, constructorParams});
+    }
+
+    public void addClassPathUrl(String path) {
+        if (!classPathUrls.contains(path)) {
+            classPathUrls.add(path);
+        }
+    }
+
+    public void addSurefireClassPathUrl(String path) {
+        if (!surefireClassPathUrls.contains(path)) {
+            surefireClassPathUrls.add(path);
+        }
+    }
+
+    public void addSurefireBootClassPathUrl(String path) {
+        if (!surefireBootClassPathUrls.contains(path)) {
+            surefireBootClassPathUrls.add(path);
+        }
+    }
+
+    /**
+     * Setting this to true will cause a failure if there are no tests to run
+     *
+     * @param redirectTestOutputToFile
+     */
+    public void setFailIfNoTests(boolean failIfNoTests) {
+        this.failIfNoTests = failIfNoTests;
+    }
+
+    /**
+     * When forking, setting this to true will make the test output to be 
saved in a file instead of showing it on the
+     * standard output
+     *
+     * @param redirectTestOutputToFile
+     */
+    public void setRedirectTestOutputToFile(boolean redirectTestOutputToFile) {
+        this.redirectTestOutputToFile = redirectTestOutputToFile;
+    }
+
+    /**
+     * Set the directory where reports will be saved
+     *
+     * @param reportsDirectory the directory
+     */
+    public void setReportsDirectory(File reportsDirectory) {
+        this.reportsDirectory = reportsDirectory;
+    }
+
+    /**
+     * Get the directory where reports will be saved
+     */
+    public File getReportsDirectory() {
+        return reportsDirectory;
+    }
+
+    public void setForkConfiguration(ForkConfiguration forkConfiguration) {
+        this.forkConfiguration = forkConfiguration;
+    }
+
+    public boolean isForking() {
+        return forkConfiguration.isForking();
+    }
+
+    public int run() throws SurefireBooterForkException, 
SurefireExecutionException {
+        int result;
+
+        if 
(ForkConfiguration.FORK_NEVER.equals(forkConfiguration.getForkMode())) {
+            result = runSuitesInProcess();
+        } else if 
(ForkConfiguration.FORK_ONCE.equals(forkConfiguration.getForkMode())) {
+            result = runSuitesForkOnce();
+        } else if 
(ForkConfiguration.FORK_ALWAYS.equals(forkConfiguration.getForkMode())) {
+            result = runSuitesForkPerTestSet();
+        } else {
+            throw new SurefireExecutionException("Unknown forkmode: " + 
forkConfiguration.getForkMode(), null);
+        }
+        return result;
+    }
+
+    private int runSuitesInProcess(String testSet, Properties results) throws 
SurefireExecutionException {
+        if (testSuites.size() != 1) {
+            throw new IllegalArgumentException("Cannot only specify testSet 
for single test suites");
+        }
+
+        // TODO: replace with plexus
+
+        // noinspection CatchGenericClass,OverlyBroadCatchBlock
+        ClassLoader oldContextClassLoader = 
Thread.currentThread().getContextClassLoader();
+        start();
+        try {
+            ClassLoader testsClassLoader =
+                useSystemClassLoader() ? ClassLoader.getSystemClassLoader() : 
createClassLoader(classPathUrls,
+                                                                               
                 null,
+                                                                               
                 childDelegation);
+
+            // TODO: assertions = true shouldn't be required for this CL if we 
had proper separation (see TestNG)
+            ClassLoader surefireClassLoader = 
createClassLoader(surefireClassPathUrls, testsClassLoader);
+
+            Class surefireClass = 
surefireClassLoader.loadClass(Surefire.class.getName());
+
+            Object surefire = surefireClass.newInstance();
+
+            Method run =
+                surefireClass.getMethod("run", new Class[] {List.class, 
Object[].class, String.class,
+                                                            ClassLoader.class, 
ClassLoader.class, Properties.class,
+                                                            Boolean.class});
+
+            Thread.currentThread().setContextClassLoader(testsClassLoader);
+
+            Integer result =
+                (Integer)run.invoke(surefire, new Object[] {reports, 
testSuites.get(0), testSet, surefireClassLoader,
+                                                            testsClassLoader, 
results, new Boolean(failIfNoTests)});
+
+            return result.intValue();
+        } catch (InvocationTargetException e) {
+            throw new 
SurefireExecutionException(e.getTargetException().getMessage(), 
e.getTargetException());
+        } catch (Exception e) {
+            throw new SurefireExecutionException("Unable to instantiate and 
execute Surefire", e);
+        } finally {
+            stop();
+            
Thread.currentThread().setContextClassLoader(oldContextClassLoader);
+        }
+    }
+
+    private int runSuitesInProcess() throws SurefireExecutionException {
+        // TODO: replace with plexus
+
+        // noinspection CatchGenericClass,OverlyBroadCatchBlock
+        ClassLoader oldContextClassLoader = 
Thread.currentThread().getContextClassLoader();
+        start();
+
+        try {
+            // The test classloader must be constructed first to avoid issues 
with commons-logging until we properly
+            // separate the TestNG classloader
+            ClassLoader testsClassLoader;
+            String testClassPath = getTestClassPathAsString();
+            System.setProperty("surefire.test.class.path", testClassPath);
+            if (useManifestOnlyJar()) {
+                // testsClassLoader = getClass().getClassLoader(); // 
ClassLoader.getSystemClassLoader()
+                testsClassLoader = createClassLoader(classPathUrls, null, 
childDelegation);
+                // SUREFIRE-459, trick the app under test into thinking its 
classpath was conventional (instead of a single manifest-only jar) 
+                System.setProperty("surefire.real.class.path", 
System.getProperty("java.class.path"));
+                System.setProperty("java.class.path", testClassPath);
+            } else {
+                testsClassLoader = createClassLoader(classPathUrls, null, 
childDelegation);
+            }
+
+            ClassLoader surefireClassLoader = 
createClassLoader(surefireClassPathUrls, testsClassLoader);
+
+            Class surefireClass = 
surefireClassLoader.loadClass(Surefire.class.getName());
+
+            Object surefire = surefireClass.newInstance();
+
+            Method run =
+                surefireClass.getMethod("run", new Class[] {List.class, 
List.class, ClassLoader.class,
+                                                            ClassLoader.class, 
Boolean.class});
+
+            Thread.currentThread().setContextClassLoader(testsClassLoader);
+
+            Integer result =
+                (Integer)run.invoke(surefire, new Object[] {reports, 
testSuites, surefireClassLoader, testsClassLoader,
+                                                            new 
Boolean(failIfNoTests)});
+
+            return result.intValue();
+        } catch (InvocationTargetException e) {
+            throw new 
SurefireExecutionException(e.getTargetException().getMessage(), 
e.getTargetException());
+        } catch (Exception e) {
+            throw new SurefireExecutionException("Unable to instantiate and 
execute Surefire", e);
+        } finally {
+            stop();
+            
Thread.currentThread().setContextClassLoader(oldContextClassLoader);
+        }
+    }
+
+    private String getTestClassPathAsString() {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < classPathUrls.size(); i++) {
+            sb.append(classPathUrls.get(i)).append(File.pathSeparatorChar);
+        }
+        return sb.toString();
+    }
+
+    private int runSuitesForkOnce() throws SurefireBooterForkException {
+        return forkSuites(testSuites, true, true);
+    }
+
+    private int runSuitesForkPerTestSet() throws SurefireBooterForkException {
+        ClassLoader testsClassLoader;
+        ClassLoader surefireClassLoader;
+        try {
+            testsClassLoader = createClassLoader(classPathUrls, null, false);
+            // TODO: assertions = true shouldn't be required if we had proper 
separation (see TestNG)
+            surefireClassLoader = createClassLoader(surefireClassPathUrls, 
testsClassLoader, false);
+        } catch (MalformedURLException e) {
+            throw new SurefireBooterForkException("Unable to create 
classloader to find test suites", e);
+        }
+
+        int globalResult = 0;
+
+        boolean showHeading = true;
+        Properties properties = new Properties();
+        for (Iterator i = testSuites.iterator(); i.hasNext();) {
+            Object[] testSuite = (Object[])i.next();
+
+            Map testSets = getTestSets(testSuite, testsClassLoader, 
surefireClassLoader);
+
+            for (Iterator j = testSets.keySet().iterator(); j.hasNext();) {
+                Object testSet = j.next();
+                boolean showFooter = !j.hasNext() && !i.hasNext();
+                int result = forkSuite(testSuite, testSet, showHeading, 
showFooter, properties);
+                if (result > globalResult) {
+                    globalResult = result;
+                }
+                showHeading = false;
+            }
+        }
+
+        return globalResult;
+    }
+
+    private Map getTestSets(Object[] testSuite, ClassLoader testsClassLoader, 
ClassLoader surefireClassLoader)
+        throws SurefireBooterForkException {
+        String className = (String)testSuite[0];
+
+        Object[] params = (Object[])testSuite[1];
+
+        Object suite;
+        try {
+            suite = Surefire.instantiateObject(className, params, 
surefireClassLoader);
+        } catch (TestSetFailedException e) {
+            throw new SurefireBooterForkException(e.getMessage(), 
e.getCause());
+        } catch (ClassNotFoundException e) {
+            throw new SurefireBooterForkException("Unable to find class for 
test suite '" + className + "'", e);
+        } catch (NoSuchMethodException e) {
+            throw new SurefireBooterForkException("Unable to find appropriate 
constructor for test suite '" + className
+                + "': "
+                + e.getMessage(), e);
+        }
+
+        Map testSets;
+        try {
+            Method m = suite.getClass().getMethod("locateTestSets", new 
Class[] {ClassLoader.class});
+
+            testSets = (Map)m.invoke(suite, new Object[] {testsClassLoader});
+        } catch (IllegalAccessException e) {
+            throw new SurefireBooterForkException("Error obtaining test sets", 
e);
+        } catch (NoSuchMethodException e) {
+            throw new SurefireBooterForkException("Error obtaining test sets", 
e);
+        } catch (InvocationTargetException e) {
+            throw new 
SurefireBooterForkException(e.getTargetException().getMessage(), 
e.getTargetException());
+        }
+        return testSets;
+    }
+
+    private int forkSuites(List testSuites, boolean showHeading, boolean 
showFooter) throws SurefireBooterForkException {
+        Properties properties = new Properties();
+
+        setForkProperties(testSuites, properties);
+
+        return fork(properties, showHeading, showFooter);
+    }
+
+    private int forkSuite(Object[] testSuite,
+                          Object testSet,
+                          boolean showHeading,
+                          boolean showFooter,
+                          Properties properties) throws 
SurefireBooterForkException {
+        setForkProperties(Collections.singletonList(testSuite), properties);
+
+        if (testSet instanceof String) {
+            properties.setProperty("testSet", (String)testSet);
+        }
+
+        return fork(properties, showHeading, showFooter);
+    }
+
+    private void setForkProperties(List testSuites, Properties properties) {
+        addPropertiesForTypeHolder(reports, properties, 
REPORT_PROPERTY_PREFIX);
+        addPropertiesForTypeHolder(testSuites, properties, 
TEST_SUITE_PROPERTY_PREFIX);
+
+        for (int i = 0; i < classPathUrls.size(); i++) {
+            String url = (String)classPathUrls.get(i);
+            properties.setProperty("classPathUrl." + i, url);
+        }
+
+        for (int i = 0; i < surefireClassPathUrls.size(); i++) {
+            String url = (String)surefireClassPathUrls.get(i);
+            properties.setProperty("surefireClassPathUrl." + i, url);
+        }
+
+        properties.setProperty("childDelegation", 
String.valueOf(childDelegation));
+        properties.setProperty("enableAssertions", 
String.valueOf(enableAssertions));
+        properties.setProperty("useSystemClassLoader", 
String.valueOf(useSystemClassLoader()));
+        properties.setProperty("useManifestOnlyJar", 
String.valueOf(useManifestOnlyJar()));
+        properties.setProperty("failIfNoTests", String.valueOf(failIfNoTests));
+        properties.setProperty("mainBundleName", mainBundleName);
+    }
+
+    private File writePropertiesFile(String name, Properties properties) 
throws IOException {
+        File file = File.createTempFile(name, "tmp");
+        if (!forkConfiguration.isDebug()) {
+            file.deleteOnExit();
+        }
+
+        writePropertiesFile(file, name, properties);
+
+        return file;
+    }
+
+    private void writePropertiesFile(File file, String name, Properties 
properties) throws IOException {
+        FileOutputStream out = new FileOutputStream(file);
+
+        try {
+            properties.store(out, name);
+        } finally {
+            IOUtil.close(out);
+        }
+    }
+
+    private void addPropertiesForTypeHolder(List typeHolderList, Properties 
properties, String propertyPrefix) {
+        for (int i = 0; i < typeHolderList.size(); i++) {
+            Object[] report = (Object[])typeHolderList.get(i);
+
+            String className = (String)report[0];
+            Object[] params = (Object[])report[1];
+
+            properties.setProperty(propertyPrefix + i, className);
+
+            if (params != null) {
+                String paramProperty = convert(params[0]);
+                String typeProperty = params[0].getClass().getName();
+                for (int j = 1; j < params.length; j++) {
+                    paramProperty += "|";
+                    typeProperty += "|";
+                    if (params[j] != null) {
+                        paramProperty += convert(params[j]);
+                        typeProperty += params[j].getClass().getName();
+                    }
+                }
+                properties.setProperty(propertyPrefix + i + PARAMS_SUFIX, 
paramProperty);
+                properties.setProperty(propertyPrefix + i + TYPES_SUFIX, 
typeProperty);
+            }
+        }
+    }
+
+    private static String convert(Object param) {
+        if (param instanceof File[]) {
+            File[] files = (File[])param;
+            return "[" + StringUtils.join(files, ",") + "]";
+        } else if (param instanceof Properties) {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            try {
+                ((Properties)param).store(baos, "");
+                return new String(baos.toByteArray(), "8859_1");
+            } catch (Exception e) {
+                throw new RuntimeException("bug in property conversion", e);
+            }
+        } else {
+            return param.toString();
+        }
+    }
+
+    private final boolean useSystemClassLoader() {
+        return forkConfiguration.isUseSystemClassLoader() && (isForked || 
forkConfiguration.isForking());
+    }
+
+    private final boolean useManifestOnlyJar() {
+        return forkConfiguration.isUseSystemClassLoader() && 
forkConfiguration.isUseManifestOnlyJar();
+    }
+
+    private int fork(Properties properties, boolean showHeading, boolean 
showFooter) throws SurefireBooterForkException {
+        File surefireProperties;
+        File systemProperties = null;
+        try {
+            surefireProperties = writePropertiesFile("surefire", properties);
+            if (forkConfiguration.getSystemProperties() != null) {
+                systemProperties = writePropertiesFile("surefire", 
forkConfiguration.getSystemProperties());
+            }
+        } catch (IOException e) {
+            throw new SurefireBooterForkException("Error creating properties 
files for forking", e);
+        }
+
+        /*
+        System.out.println("cp:   " + classPathUrls);
+        System.out.println("scp:  " + surefireClassPathUrls);
+        System.out.println("sbcp: " + surefireBootClassPathUrls);
+        */
+        
+        List bootClasspath = new ArrayList(surefireBootClassPathUrls.size() + 
classPathUrls.size());
+
+        bootClasspath.addAll(surefireBootClassPathUrls);
+
+        if (useSystemClassLoader()) {
+            bootClasspath.addAll(classPathUrls);
+        }
+
+        Commandline cli =
+            forkConfiguration.createCommandLine(bootClasspath, 
useManifestOnlyJar());
+
+        cli.createArg().setFile(surefireProperties);
+
+        if (systemProperties != null) {
+            cli.createArg().setFile(systemProperties);
+        }
+
+        ForkingStreamConsumer out = getForkingStreamConsumer(showHeading, 
showFooter, redirectTestOutputToFile);
+
+        StreamConsumer err;
+
+        if (redirectTestOutputToFile) {
+            err = out;
+        } else {
+            err = getForkingStreamConsumer(showHeading, showFooter, 
redirectTestOutputToFile);
+        }
+
+        if (forkConfiguration.isDebug()) {
+            System.out.println("Forking command line: " + cli);
+        }
+
+        int returnCode;
+
+        try {
+            returnCode =
+                
org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.cli.CommandLineUtils
+                    .executeCommandLine(cli, out, err, 
forkedProcessTimeoutInSeconds);
+        } catch 
(org.apache.maven.surefire.booter.shade.org.codehaus.plexus.util.cli.CommandLineException
 e) {
+            throw new SurefireBooterForkException("Error while executing 
forked tests.", e);
+        }
+
+        if (redirectTestOutputToFile) {
+            // ensure the FileOutputConsumerProxy flushes/closes the output 
file
+            try {
+                out.getOutputConsumer().testSetCompleted();
+            } catch (Exception e) {
+                // the FileOutputConsumerProxy might throw an 
IllegalStateException but that's not of interest now
+            }
+        }
+
+        if (surefireProperties != null && surefireProperties.exists()) {
+            FileInputStream inStream = null;
+            try {
+                inStream = new FileInputStream(surefireProperties);
+
+                properties.load(inStream);
+            } catch (FileNotFoundException e) {
+                throw new SurefireBooterForkException("Unable to reload 
properties file from forked process", e);
+            } catch (IOException e) {
+                throw new SurefireBooterForkException("Unable to reload 
properties file from forked process", e);
+            } finally {
+                IOUtil.close(inStream);
+            }
+        }
+
+        return returnCode;
+    }
+
+    private ClassLoader createClassLoader(List classPathUrls, ClassLoader 
parent) throws MalformedURLException {
+        return createClassLoader(classPathUrls, parent, false);
+    }
+
+    private ClassLoader createClassLoader(List classPathUrls, ClassLoader 
parent, boolean childDelegation)
+        throws MalformedURLException {
+        Set<URL> urls = new HashSet<URL>();
+
+        for (Iterator i = classPathUrls.iterator(); i.hasNext();) {
+            String url = (String)i.next();
+
+            if (url != null) {
+                File f = new File(url);
+                urls.add(f.toURI().toURL());
+            }
+        }
+        return bundleClassLoader;
+    }
+
+    private static List processStringList(String stringList) {
+        String sl = stringList;
+
+        if (sl.startsWith("[") && sl.endsWith("]")) {
+            sl = sl.substring(1, sl.length() - 1);
+        }
+
+        List list = new ArrayList();
+
+        String[] stringArray = StringUtils.split(sl, ",");
+
+        for (int i = 0; i < stringArray.length; i++) {
+            list.add(stringArray[i].trim());
+        }
+        return list;
+    }
+
+    private static Properties loadProperties(File file) throws IOException {
+        Properties p = new Properties();
+
+        if (file != null && file.exists()) {
+            FileInputStream inStream = new FileInputStream(file);
+            try {
+                p.load(inStream);
+            } finally {
+                IOUtil.close(inStream);
+            }
+        }
+
+        return p;
+    }
+
+    private static void setSystemProperties(File file) throws IOException {
+        Properties p = loadProperties(file);
+
+        for (Iterator i = p.keySet().iterator(); i.hasNext();) {
+            String key = (String)i.next();
+
+            System.setProperty(key, p.getProperty(key));
+        }
+    }
+
+    private static Object[] constructParamObjects(String paramProperty, String 
typeProperty) {
+        Object[] paramObjects = null;
+        if (paramProperty != null) {
+            // bit of a glitch that it need sto be done twice to do an odd 
number of vertical bars (eg |||, |||||).
+            String[] params =
+                
StringUtils.split(StringUtils.replace(StringUtils.replace(paramProperty, "||", 
"| |"), "||", "| |"),
+                                  "|");
+            String[] types =
+                StringUtils
+                    
.split(StringUtils.replace(StringUtils.replace(typeProperty, "||", "| |"), 
"||", "| |"), "|");
+
+            paramObjects = new Object[params.length];
+
+            for (int i = 0; i < types.length; i++) {
+                if (types[i].trim().length() == 0) {
+                    params[i] = null;
+                } else if (types[i].equals(String.class.getName())) {
+                    paramObjects[i] = params[i];
+                } else if (types[i].equals(File.class.getName())) {
+                    paramObjects[i] = new File(params[i]);
+                } else if (types[i].equals(File[].class.getName())) {
+                    List stringList = processStringList(params[i]);
+                    File[] fileList = new File[stringList.size()];
+                    for (int j = 0; j < stringList.size(); j++) {
+                        fileList[j] = new File((String)stringList.get(j));
+                    }
+                    paramObjects[i] = fileList;
+                } else if (types[i].equals(ArrayList.class.getName())) {
+                    paramObjects[i] = processStringList(params[i]);
+                } else if (types[i].equals(Boolean.class.getName())) {
+                    paramObjects[i] = Boolean.valueOf(params[i]);
+                } else if (types[i].equals(Integer.class.getName())) {
+                    paramObjects[i] = Integer.valueOf(params[i]);
+                } else if (types[i].equals(Properties.class.getName())) {
+                    final Properties result = new Properties();
+                    final String value = params[i];
+                    try {
+                        ByteArrayInputStream bais = new 
ByteArrayInputStream(value.getBytes("8859_1"));
+                        result.load(bais);
+                    } catch (Exception e) {
+                        throw new RuntimeException("bug in property 
conversion", e);
+                    }
+                    paramObjects[i] = result;
+                } else {
+                    // TODO: could attempt to construct with a String 
constructor if needed
+                    throw new IllegalArgumentException("Unknown parameter 
type: " + types[i]);
+                }
+            }
+        }
+        return paramObjects;
+    }
+
+    /**
+     * This method is invoked when Surefire is forked - this method parses and 
organizes the arguments passed to it and
+     * then calls the Surefire class' run method. <p/> The system exit code 
will be 1 if an exception is thrown.
+     *
+     * @param args
+     */
+    public static void main(String[] args) throws Throwable {
+        // noinspection CatchGenericClass,OverlyBroadCatchBlock
+        try {
+            if (args.length > 1) {
+                setSystemProperties(new File(args[1]));
+            }
+
+            File surefirePropertiesFile = new File(args[0]);
+            Properties p = loadProperties(surefirePropertiesFile);
+
+            SortedMap classPathUrls = new TreeMap();
+
+            SortedMap surefireClassPathUrls = new TreeMap();
+
+            OSGiSurefireBooter surefireBooter = new OSGiSurefireBooter(true);
+
+            ForkConfiguration forkConfiguration = new ForkConfiguration();
+            forkConfiguration.setForkMode("never");
+            surefireBooter.setForkConfiguration(forkConfiguration);
+
+            for (Enumeration e = p.propertyNames(); e.hasMoreElements();) {
+                String name = (String)e.nextElement();
+
+                if (name.startsWith(REPORT_PROPERTY_PREFIX) && 
!name.endsWith(PARAMS_SUFIX)
+                    && !name.endsWith(TYPES_SUFIX)) {
+                    String className = p.getProperty(name);
+
+                    String params = p.getProperty(name + PARAMS_SUFIX);
+                    String types = p.getProperty(name + TYPES_SUFIX);
+                    surefireBooter.addReport(className, 
constructParamObjects(params, types));
+                } else if (name.startsWith(TEST_SUITE_PROPERTY_PREFIX) && 
!name.endsWith(PARAMS_SUFIX)
+                    && !name.endsWith(TYPES_SUFIX)) {
+                    String className = p.getProperty(name);
+
+                    String params = p.getProperty(name + PARAMS_SUFIX);
+                    String types = p.getProperty(name + TYPES_SUFIX);
+                    surefireBooter.addTestSuite(className, 
constructParamObjects(params, types));
+                } else if (name.startsWith("classPathUrl.")) {
+                    
classPathUrls.put(Integer.valueOf(name.substring(name.indexOf('.') + 1)), 
p.getProperty(name));
+                } else if (name.startsWith("surefireClassPathUrl.")) {
+                    
surefireClassPathUrls.put(Integer.valueOf(name.substring(name.indexOf('.') + 
1)), p
+                        .getProperty(name));
+                } else if (name.startsWith("surefireBootClassPathUrl.")) {
+                    
surefireBooter.addSurefireBootClassPathUrl(p.getProperty(name));
+                } else if ("childDelegation".equals(name)) {
+                    surefireBooter.childDelegation = 
Boolean.valueOf(p.getProperty("childDelegation")).booleanValue();
+                } else if ("enableAssertions".equals(name)) {
+                    surefireBooter.enableAssertions = 
Boolean.valueOf(p.getProperty("enableAssertions")).booleanValue();
+                } else if ("useSystemClassLoader".equals(name)) {
+                    
surefireBooter.forkConfiguration.setUseSystemClassLoader(Boolean.valueOf(p
+                        .getProperty("useSystemClassLoader")).booleanValue());
+                } else if ("useManifestOnlyJar".equals(name)) {
+                    
surefireBooter.forkConfiguration.setUseManifestOnlyJar(Boolean.valueOf(p
+                        .getProperty("useManifestOnlyJar")).booleanValue());
+                } else if ("failIfNoTests".equals(name)) {
+                    
surefireBooter.setFailIfNoTests(Boolean.valueOf(p.getProperty("failIfNoTests")).booleanValue());
+                } else if ("mainBundleName".equals(name)) {
+                    
surefireBooter.setMainBundleName(p.getProperty("mainBundleName"));
+                }
+            }
+
+            for (Iterator cpi = classPathUrls.keySet().iterator(); 
cpi.hasNext();) {
+                String url = (String)classPathUrls.get(cpi.next());
+                surefireBooter.addClassPathUrl(url);
+            }
+
+            for (Iterator scpi = surefireClassPathUrls.keySet().iterator(); 
scpi.hasNext();) {
+                String url = (String)surefireClassPathUrls.get(scpi.next());
+                surefireBooter.addSurefireClassPathUrl(url);
+            }
+
+            String testSet = p.getProperty("testSet");
+            int result;
+            if (testSet != null) {
+                result = surefireBooter.runSuitesInProcess(testSet, p);
+            } else {
+                result = surefireBooter.runSuitesInProcess();
+            }
+
+            surefireBooter.writePropertiesFile(surefirePropertiesFile, 
"surefire", p);
+
+            // noinspection CallToSystemExit
+            System.exit(result);
+        } catch (Throwable t) {
+            // Just throwing does getMessage() and a local trace - we want to 
call printStackTrace for a full trace
+            // noinspection UseOfSystemOutOrSystemErr
+            t.printStackTrace(System.err);
+            // noinspection ProhibitedExceptionThrown,CallToSystemExit
+            System.exit(1);
+        }
+    }
+
+    public void setChildDelegation(boolean childDelegation) {
+        this.childDelegation = childDelegation;
+    }
+
+    private ForkingStreamConsumer getForkingStreamConsumer(boolean showHeading,
+                                                           boolean showFooter,
+                                                           boolean 
redirectTestOutputToFile) {
+        OutputConsumer outputConsumer = new StandardOutputConsumer();
+
+        if (redirectTestOutputToFile) {
+            outputConsumer = new FileOutputConsumerProxy(outputConsumer, 
getReportsDirectory());
+        }
+
+        if (!showHeading) {
+            outputConsumer = new 
SupressHeaderOutputConsumerProxy(outputConsumer);
+        }
+        if (!showFooter) {
+            outputConsumer = new 
SupressFooterOutputConsumerProxy(outputConsumer);
+        }
+
+        return new ForkingStreamConsumer(outputConsumer);
+    }
+
+    public void setEnableAssertions(boolean enableAssertions) {
+        this.enableAssertions = enableAssertions;
+    }
+
+    public void setForkedProcessTimeoutInSeconds(int 
forkedProcessTimeoutInSeconds) {
+        this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
+    }
+
+    private String mainBundleName;
+
+    public void setMainBundleName(String mainBundleName) {
+        this.mainBundleName = mainBundleName;
+    }
+
+    private EquinoxHost host;
+    private BundleClassLoader bundleClassLoader;
+
+    public EquinoxHost start() {
+        Set<URL> urls = new HashSet<URL>();
+        
+        // Merge the two classpaths so that all of them will be OSGi-enabled
+        Set<String> cps = new HashSet<String>(classPathUrls);
+        cps.addAll(surefireClassPathUrls);
+
+        for (String url: cps) {
+            if (url != null) {
+                File f = new File(url);
+                try {
+                    urls.add(f.toURI().toURL());
+                } catch (MalformedURLException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        host = new EquinoxHost(urls);
+        BundleContext context = host.start();
+        Bundle mainBundle = null;
+        for (Bundle bundle : context.getBundles()) {
+            // Fragement bundle cannot be used to load class, use the main 
bundle
+            if (mainBundleName.equals(bundle.getSymbolicName())) {
+                mainBundle = bundle;
+                break;
+            }
+        }  
+        
+        bundleClassLoader = new BundleClassLoader(mainBundle, null);
+        if (assertionStatusMethod != null) {
+            try {
+                Object[] args = new Object[] {enableAssertions ? Boolean.TRUE 
: Boolean.FALSE};
+                assertionStatusMethod.invoke(bundleClassLoader, args);
+            } catch (IllegalAccessException e) {
+                throw new NestedRuntimeException("Unable to access the 
assertion enablement method", e);
+            } catch (InvocationTargetException e) {
+                throw new NestedRuntimeException("Unable to invoke the 
assertion enablement method", e);
+            }
+        }
+
+        return host;
+    }
+
+    public void stop() {
+        if (host != null) {
+            host.stop();
+            host = null;
+            bundleClassLoader = null;
+        }
+    }
+
+    /**
+     * Returns a string representation of the given bundle.
+     * 
+     * @param b
+     * @param verbose
+     * @return
+     */
+    static String string(Bundle bundle, boolean verbose) {
+        StringBuffer sb = new StringBuffer();
+        sb.append(bundle.getBundleId()).append(" 
").append(bundle.getSymbolicName());
+        int s = bundle.getState();
+        if ((s & Bundle.UNINSTALLED) != 0) {
+            sb.append(" UNINSTALLED");
+        }
+        if ((s & Bundle.INSTALLED) != 0) {
+            sb.append(" INSTALLED");
+        }
+        if ((s & Bundle.RESOLVED) != 0) {
+            sb.append(" RESOLVED");
+        }
+        if ((s & Bundle.STARTING) != 0) {
+            sb.append(" STARTING");
+        }
+        if ((s & Bundle.STOPPING) != 0) {
+            sb.append(" STOPPING");
+        }
+        if ((s & Bundle.ACTIVE) != 0) {
+            sb.append(" ACTIVE");
+        }
+    
+        if (verbose) {
+            sb.append(" ").append(bundle.getLocation());
+            sb.append(" ").append(bundle.getHeaders());
+        }
+        return sb.toString();
+    }
+
+}

Propchange: 
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tuscany/java/sca/tools/maven/maven-osgi-junit/src/main/java/org/apache/tuscany/sca/maven/plugin/surefire/OSGiSurefireBooter.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date


Reply via email to