[jboss-cvs] JBossAS SVN: r97150 - in projects/embedded/trunk: api/src/main/java/org/jboss/embedded/api/server and 9 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Nov 30 00:42:18 EST 2009


Author: ALRubinger
Date: 2009-11-30 00:42:18 -0500 (Mon, 30 Nov 2009)
New Revision: 97150

Added:
   projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/server/JBossHomeClassLoader.java
   projects/embedded/trunk/testsuite-jbosshomecl/
   projects/embedded/trunk/testsuite-jbosshomecl/pom.xml
   projects/embedded/trunk/testsuite-jbosshomecl/src/
   projects/embedded/trunk/testsuite-jbosshomecl/src/test/
   projects/embedded/trunk/testsuite-jbosshomecl/src/test/java/
   projects/embedded/trunk/testsuite-jbosshomecl/src/test/java/org/
   projects/embedded/trunk/testsuite-jbosshomecl/src/test/java/org/jboss/
   projects/embedded/trunk/testsuite-jbosshomecl/src/test/java/org/jboss/embedded/
   projects/embedded/trunk/testsuite-jbosshomecl/src/test/java/org/jboss/embedded/testsuite/
   projects/embedded/trunk/testsuite-jbosshomecl/src/test/java/org/jboss/embedded/testsuite/jbosshomecl/
   projects/embedded/trunk/testsuite-jbosshomecl/src/test/java/org/jboss/embedded/testsuite/jbosshomecl/JBossHomeClassLoaderIntegrationTest.java
Modified:
   projects/embedded/trunk/pom.xml
Log:
[EMB-73] Create a mechanism (custom ClassLoader) and testsuite allowing AS to be booted with a very minimal dependency set upon the application classpath, and the rest coming in from JBOSS_HOME

Added: projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/server/JBossHomeClassLoader.java
===================================================================
--- projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/server/JBossHomeClassLoader.java	                        (rev 0)
+++ projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/server/JBossHomeClassLoader.java	2009-11-30 05:42:18 UTC (rev 97150)
@@ -0,0 +1,232 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed 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.jboss.embedded.api.server;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * {@link ClassLoader} implementation which is capable of booting
+ * the JBoss Application Server installation located at a known
+ * $JBOSS_HOME 
+ * 
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class JBossHomeClassLoader extends URLClassLoader
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(JBossHomeClassLoader.class.getName());
+
+   /**
+    * Name of the boot library directory, relative to $JBOSS_HOME
+    */
+   private static final String DIR_NAME_LIB = "lib/";
+
+   /**
+    * Libraries, relative to $JBOSS_HOME/lib, which must be visible to 
+    * the context ClassLoader (and the loading CL of the server)
+    * in order to boot the Application Server.  This is a carefully
+    * pruned list in order to not leak out class references, which would
+    * in turn result in {@link NoClassDefFoundError}
+    */
+   public static final String[] JBOSS_LIB_BOOT_LIST =
+   {
+         // Concurrent
+         "concurrent.jar",
+         // Logging
+         "log4j-boot.jar",
+         "jboss-logging-spi.jar",
+         "jboss-logging-log4j.jar",
+         "jboss-logging-jdk.jar",
+         "jboss-logmanager.jar",
+         "jboss-logbridge.jar",
+         // Common jars
+         "jboss-common-core.jar",
+         "jboss-xml-binding.jar",
+         // Bootstrap
+         "jboss-bootstrap-spi.jar", "jboss-bootstrap-spi-as.jar", "jboss-bootstrap-spi-mc.jar",
+         "jboss-bootstrap-impl-base.jar", "jboss-bootstrap-impl-as.jar", "jboss-bootstrap-impl-mc.jar",
+         "jboss-bootstrap-api-as.jar", "jboss-bootstrap-api-mc.jar",
+         "jboss-bootstrap-api.jar",
+         // Microcontainer
+         "javassist.jar", "jboss-reflect.jar", "jboss-mdr.jar", "jboss-dependency.jar", "jboss-kernel.jar",
+         "jboss-metatype.jar", "jboss-managed.jar",
+         // Deployers
+         "jboss-deployers-core-spi.jar", "jboss-deployers-client-spi.jar",
+         // Fixme ClassLoading
+         "jboss-vfs.jar", "jboss-classloading-spi.jar", "jboss-classloader.jar", "jboss-classloading.jar",
+         "jboss-classloading-vfs.jar",
+         // Fixme aop
+         "jboss-aop.jar", "jboss-aop-mc-int.jar", "trove.jar"};
+
+   /**
+    * Libraries, relative to $JBOSS_HOME/bin, which must be visible to 
+    * the context ClassLoader (and the loading CL of the server)
+    * in order to boot the Application Server.  This is a carefully
+    * pruned list in order to not leak out class references, which would
+    * in turn result in {@link NoClassDefFoundError}
+    */
+   public static final String[] JBOSS_BIN_BOOT_LIST =
+   {"run.jar"};
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Constructs a new instance using the specified URLs; not exposed publicly, instead use
+    * {@link JBossHomeClassLoader#newInstance(URL, URL[])} outside this class
+    */
+   private JBossHomeClassLoader(final URL[] urls, final ClassLoader parent) throws IllegalArgumentException,
+         IllegalStateException
+   {
+      // Invoke super
+      super(urls, parent);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Factory Methods --------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Constructs a new instance, using the required boot libraries of the specified $JBOSS_HOME
+    * as well as the the additional URLs specified (optional)
+    * 
+    * @param jbossHome The location to JBOSS_HOME
+    * @param urls Additional URLs which this ClassLoader should use; may be null
+    * @param parent The parent to assign to the new ClassLoader
+    */
+   public static JBossHomeClassLoader newInstance(final URL jbossHome, final URL[] urls, final ClassLoader parent)
+   {
+      // Get $JBOSS_HOME/lib URLs
+      final URL[] jbossLibBootUrls = getJBossLibBootUrls(jbossHome);
+
+      // Merge with the specified URLs passed in
+      final URL[] merged = merge(jbossLibBootUrls, urls);
+
+      // Create and return a new instance
+      return new JBossHomeClassLoader(merged, parent);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods ------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Merges the arrays of all URLs into a unified view, with no duplicate 
+    * elements
+    * 
+    * @param urls Any number of arrays to be represented as a union
+    * @throws IllegalArgumentException If the URLs specified are null
+    */
+   private static URL[] merge(final URL[]... urls) throws IllegalArgumentException
+   {
+      // Precondition check
+      assert urls != null : "URLs must be specified";
+
+      // Create a set
+      final Set<URL> urlSet = new HashSet<URL>();
+
+      // Merge
+      for (final URL[] current : urls)
+      {
+         for (final URL single : current)
+         {
+            urlSet.add(single);
+         }
+      }
+
+      // Return
+      return urlSet.toArray(new URL[]
+      {});
+
+   }
+
+   /**
+    * Obtains all boot libraries for which ClassLoader
+    * visibility is required given the specified $JBOSS_HOME
+    */
+   private static URL[] getJBossLibBootUrls(final URL jbossHome)
+   {
+      // Get a URL to $JBOSS_HOME/lib
+      final URL jbossLib;
+      try
+      {
+         jbossLib = new URL(jbossHome, DIR_NAME_LIB);
+      }
+      catch (final MalformedURLException murle)
+      {
+         throw new RuntimeException("Error in constructing $JBOSS_HOME/lib URL", murle);
+      }
+
+      final Collection<URL> urls = new HashSet<URL>();
+      // Add all appropriate JBOSS_HOME/lib binaries
+      for (final String bootLib : JBOSS_LIB_BOOT_LIST)
+      {
+         final URL url;
+         try
+         {
+            url = new URL(jbossLib, bootLib);
+         }
+         catch (final MalformedURLException murle)
+         {
+            throw new RuntimeException("Could not construct full URL for $JBOSS_HOME boot library: " + bootLib, murle);
+         }
+         urls.add(url);
+         log.finer("Using: " + url);
+
+         // Check file for existence 
+         final URI uri;
+         try
+         {
+            uri = url.toURI();
+         }
+         catch (final URISyntaxException urise)
+         {
+            throw new RuntimeException(urise);
+         }
+         final File file = new File(uri);
+         if (!file.exists())
+         {
+            throw new IllegalStateException("Attempting to add a library to the ClassLoader which does not exist: "
+                  + file + "; perhaps a corrupt $JBOSS_HOME installation? ");
+         }
+      }
+
+      // Return
+      log.fine("Using: " + urls);
+      return urls.toArray(new URL[]
+      {});
+   }
+
+}

Modified: projects/embedded/trunk/pom.xml
===================================================================
--- projects/embedded/trunk/pom.xml	2009-11-30 05:05:43 UTC (rev 97149)
+++ projects/embedded/trunk/pom.xml	2009-11-30 05:42:18 UTC (rev 97150)
@@ -42,6 +42,7 @@
     <module>core</module>
     <module>depchain</module>
     <module>testsuite</module>
+    <module>testsuite-jbosshomecl</module>
   </modules>
 
 </project>


Property changes on: projects/embedded/trunk/testsuite-jbosshomecl
___________________________________________________________________
Name: svn:ignore
   + target
eclipse-target
target-eclipse
bin
.settings
.classpath
.project


Added: projects/embedded/trunk/testsuite-jbosshomecl/pom.xml
===================================================================
--- projects/embedded/trunk/testsuite-jbosshomecl/pom.xml	                        (rev 0)
+++ projects/embedded/trunk/testsuite-jbosshomecl/pom.xml	2009-11-30 05:42:18 UTC (rev 97150)
@@ -0,0 +1,138 @@
+<?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/maven-v4_0_0.xsd">
+
+  <!-- Parent -->
+  <parent>
+    <groupId>org.jboss.embedded</groupId>
+    <artifactId>jboss-embedded-build</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>../build/pom.xml</relativePath>
+  </parent>
+
+  <!-- Model Version -->
+  <modelVersion>4.0.0</modelVersion>
+
+  <!-- Artifact Configuration -->
+  <artifactId>jboss-embedded-testsuite-jbosshomecl</artifactId>
+  <name>JBossAS Embedded TestSuite using JBOSS_HOME ClassLoading</name>
+  <description>JBoss Application Server Embedded TestSuite for JBOSS_HOME ClassLoading</description>
+
+  <!-- Properties -->
+  <properties>
+
+    <!-- JBOSS_HOME (We'll unpack into here -->
+    <JBOSS_HOME>${project.build.directory}/jboss-as-distribution-${version.org.jboss.jbossas}</JBOSS_HOME>
+
+    <!-- Versioning -->
+
+  </properties>
+
+  <!-- Build Configuration -->
+  <build>
+
+    <plugins>
+
+      <!-- Surefire -->
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>integration-test</id>
+            <phase>integration-test</phase>
+            <goals>
+              <goal>test</goal>
+            </goals>
+            <configuration>
+              <additionalClasspathElements>
+                <additionalClasspathElement>${JBOSS_HOME}/bin/run.jar</additionalClasspathElement>
+              </additionalClasspathElements>
+              <redirectTestOutputToFile>true</redirectTestOutputToFile>
+              <trimStackTrace>false</trimStackTrace>
+              <printSummary>true</printSummary>
+              <includes>
+                <include>**/*IntegrationTest.java</include>
+              </includes>
+              <forkMode>always</forkMode>
+              <argLine>-XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djava.endorsed.dirs=${JBOSS_HOME}/lib/endorsed -Djboss.home=${JBOSS_HOME}</argLine>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <!-- Get AS and put into "target" -->
+          <execution>
+            <id>unpack</id>
+            <phase>pre-integration-test</phase> <!-- So run before testing -->
+            <goals>
+              <goal>unpack</goal>
+            </goals>
+            <configuration>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>org.jboss.jbossas</groupId>
+                  <artifactId>jboss-as-distribution</artifactId>
+                  <version>${version.org.jboss.jbossas}</version>
+                  <type>zip</type>
+                  <overWrite>false</overWrite>
+                  <outputDirectory>${project.build.directory}</outputDirectory>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </execution>
+          <!-- Other deps, not part of AS, into "target/deps" -->
+          <execution>
+            <id>copy</id>
+            <phase>pre-integration-test</phase>
+            <goals>
+              <goal>copy</goal>
+            </goals>
+            <configuration>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>org.jboss.embedded</groupId>
+                  <artifactId>jboss-embedded-core</artifactId>
+                  <version>${version}</version>
+                  <overWrite>false</overWrite>
+                  <outputDirectory>${project.build.directory}/deps</outputDirectory>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+
+  </build>
+
+  <!-- Dependencies -->
+  <dependencies>
+
+    <!--
+
+      Here we define an ultra-minimal dependency set; just enough to
+      compile/load the test class (ie. EmbeddedAS API only). In the test
+      we'll use a URL ClassLoader to get the necessary libraries from
+      JBOSS_HOME and launch from there.
+    -->
+
+    <dependency>
+      <groupId>org.jboss.embedded</groupId>
+      <artifactId>jboss-embedded-api</artifactId>
+      <version>${version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- JUnit -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+
+  </dependencies>
+
+</project>

Added: projects/embedded/trunk/testsuite-jbosshomecl/src/test/java/org/jboss/embedded/testsuite/jbosshomecl/JBossHomeClassLoaderIntegrationTest.java
===================================================================
--- projects/embedded/trunk/testsuite-jbosshomecl/src/test/java/org/jboss/embedded/testsuite/jbosshomecl/JBossHomeClassLoaderIntegrationTest.java	                        (rev 0)
+++ projects/embedded/trunk/testsuite-jbosshomecl/src/test/java/org/jboss/embedded/testsuite/jbosshomecl/JBossHomeClassLoaderIntegrationTest.java	2009-11-30 05:42:18 UTC (rev 97150)
@@ -0,0 +1,164 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+  *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.embedded.testsuite.jbosshomecl;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import junit.framework.TestCase;
+
+import org.jboss.bootstrap.api.lifecycle.LifecycleState;
+import org.jboss.embedded.api.server.JBossASEmbeddedServer;
+import org.jboss.embedded.api.server.JBossASEmbeddedServerFactory;
+import org.jboss.embedded.api.server.JBossHomeClassLoader;
+import org.junit.Test;
+
+/**
+ * Test Cases to ensure that the JBossAS Server may 
+ * be booted via the Embedded APIs using a minimal 
+ * dependency set upon the classpath, bolstered
+ * by the {@link JBossHomeClassLoader} to make the rest of
+ * the binaries visible for a full boot.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class JBossHomeClassLoaderIntegrationTest
+{
+
+   //-------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------||
+   //-------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(JBossHomeClassLoaderIntegrationTest.class.getName());
+
+   /**
+    * The server instance
+    */
+   private static JBossASEmbeddedServer server;
+
+   /**
+    * Name of the server configuration to use
+    */
+   private static final String NAME_SERVER_CONFIG = "all";
+
+   //-------------------------------------------------------------------------------||
+   // Tests ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------||
+
+   /**
+    * Tests that we can start up and shut down cleanly using a minimal
+    * dependency set, and the {@link JBossHomeClassLoader} to bring
+    * in the required visibility
+    */
+   @Test
+   public void startEmbeddedUsingJBossHomeClassLoader() throws Exception
+   {
+      // Get JBOSS_HOME
+      final URL jbossHome = this.getJBossHome();
+
+      // Get additional binaries which need CL visibility (ie. jboss-embedded-core,
+      // which is placed under "target/deps" by the build).  These
+      // binaries are not presently available under $JBOSS_HOME
+      final Set<URL> additionalUrls = new HashSet<URL>();
+      final URL source = this.getClass().getProtectionDomain().getCodeSource().getLocation();
+      final URL target = new URL(source, "..");
+      final URL additionalDeps = new URL(target, "deps");
+      final File deps = new File(additionalDeps.toURI());
+      TestCase.assertTrue("Dependencies location does not exist: " + deps, deps.exists());
+      TestCase.assertTrue("Dependencies location is not a directory: " + deps, deps.isDirectory());
+      for (final File child : deps.listFiles())
+      {
+         additionalUrls.add(child.toURI().toURL());
+         log.info("Booting with: " + child);
+      }
+
+      // Make the new ClassLoader
+      final ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
+      final ClassLoader jbossHomeClassLoader = JBossHomeClassLoader.newInstance(jbossHome, additionalUrls
+            .toArray(new URL[]
+            {}), oldCl);
+
+      // Make Server
+      server = JBossASEmbeddedServerFactory.createServer(jbossHomeClassLoader);
+      log.info("Created: " + server);
+
+      // Start
+      log.info("Starting Server: " + server);
+      server.getConfiguration().serverName(NAME_SERVER_CONFIG);
+
+      // Set TCCL
+      Thread.currentThread().setContextClassLoader(jbossHomeClassLoader);
+
+      try
+      {
+         // Start the Server
+         server.start();
+         log.info("...started.");
+
+         // Test
+         TestCase.assertEquals("Server did not report started as expected", LifecycleState.STARTED, server.getState());
+
+         // Shutdown if started
+         if (server != null && server.getState().equals(LifecycleState.STARTED))
+         {
+            // Shutdown
+            log.info("Shutting down server: " + server);
+            server.shutdown();
+         }
+      }
+      finally
+      {
+         // Reset the TCCL 
+         Thread.currentThread().setContextClassLoader(oldCl);
+      }
+   }
+
+   //-------------------------------------------------------------------------------||
+   // Internal Helper Methods ------------------------------------------------------||
+   //-------------------------------------------------------------------------------||
+
+   /**
+    * Obtains $JBOSS_HOME from the system property
+    * 
+    * @return
+    */
+   private URL getJBossHome()
+   {
+      try
+      {
+         return new File(System.getProperty("jboss.home")).toURI().toURL();
+      }
+      catch (final MalformedURLException murle)
+      {
+         throw new RuntimeException("Could not get JBOSS_HOME", murle);
+      }
+   }
+
+}




More information about the jboss-cvs-commits mailing list