<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<body link="#355491" alink="#4262a1" vlink="#355491" style="background: #e2e2e2; margin: 0; padding: 20px;">

<div>
        <table cellpadding="0" bgcolor="#FFFFFF" border="0" cellspacing="0" style="border: 1px solid #dadada; margin-bottom: 30px; width: 100%; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
                <tbody>
                        <tr>

                                <td>

                                        <table border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" style="border: solid 2px #ccc; background: #dadada; width: 100%; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
                                                <tbody>
                                                        <tr>
                                                                <td bgcolor="#000000" valign="middle" height="58px" style="border-bottom: 1px solid #ccc; padding: 20px; -moz-border-radius-topleft: 3px; -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 5px; -webkit-border-top-left-radius: 5px;">
                                                                        <h1 style="color: #333333; font: bold 22px Arial, Helvetica, sans-serif; margin: 0; display: block !important;">
                                                                        <!-- To have a header image/logo replace the name below with your img tag -->
                                                                        <!-- Email clients will render the images when the message is read so any image -->
                                                                        <!-- must be made available on a public server, so that all recipients can load the image. -->
                                                                        <a href="https://community.jboss.org/index.jspa" style="text-decoration: none; color: #E1E1E1">JBoss Community</a></h1>
                                                                </td>

                                                        </tr>
                                                        <tr>
                                                                <td bgcolor="#FFFFFF" style="font: normal 12px Arial, Helvetica, sans-serif; color:#333333; padding: 20px;  -moz-border-radius-bottomleft: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 5px; -webkit-border-bottom-left-radius: 5px;"><h3 style="margin: 10px 0 5px; font-size: 17px; font-weight: normal;">
    jboss-modules: Module Repository SPI and Extensibility
</h3>
<span style="margin-bottom: 10px;">
    created by <a href="https://community.jboss.org/people/ALRubinger">Andrew Rubinger</a> in <i>JBoss AS 7 Development</i> - <a href="https://community.jboss.org/message/772203#772203">View the full discussion</a>
</span>
<hr style="margin: 20px 0; border: none; background-color: #dadada; height: 1px;">

<div class="jive-rendered-content"><p>I have the following use cases I'd like to fulfill:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>1) Boot JBossAS from a single-JAR distribution</p><p>2) Boot JBossAS from a slim executable JAR, using module libraries located on a remote repository (if not already in a user's local module repository)</p><p>3) Create a modular Arquillian Server Daemon executable JAR, with module root located inside of this JAR under META-INF/modules</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>From my prototyping, all of these are possible using jboss-modules, though the SPI is a bit restrictive when it comes to abstracting out the module repository.&#160; With some improvements to the jboss-modules SPI, we could promote better extensibility.&#160; In particular, I'm finding ModuleLoader difficult to work with.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>Reasoning:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><pre class="jive-pre"><code class="jive-code jive-java"><font color="navy"><b>protected</b></font> <font color="navy"><b>abstract</b></font> ModuleSpec findModule(<font color="navy"><b>final</b></font> ModuleIdentifier moduleIdentifier) <font color="navy"><b>throws</b></font> ModuleLoadException;
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>Fulfilling this contract is required of ModuleLoader subtypes.&#160; Typically this amounts to finding and parsing a "module.xml" file from the given ModuleIdentifier, but the mechanism for doing this (ModuleXmlParser) is package-private.&#160; It's therefore not very intuitive (or possible) for users outside of jboss-modules to meet the demands of the method signature.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>David points out that ModuleLoader implementations are instead encouraged to use a delagation mechanism, via something like:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><pre class="jive-pre"><code class="jive-code jive-java">@Override
<font color="navy"><b>protected</b></font> Module preloadModule(<font color="navy"><b>final</b></font> ModuleIdentifier identifier) <font color="navy"><b>throws</b></font> ModuleLoadException <font color="navy">{</font>
&#160; <font color="navy"><b>return</b></font> ModuleLoader.preloadModule(identifier, this.delegate);
<font color="navy">}</font>
</code></pre><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>The issue here is that we need a delegate capable of servicing the request.&#160; LocalModuleLoader is fine for filesystem-based repositories (though it's final and cannot be extended), but modules could conceivably be located anywhere (and may even have some descriptor format other than module.xml).&#160; This is exacerbated by the unavailability of other ModuleLoader implementations which are not visible outside jboss-modules:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>ClassPathModuleLoader</p><p>JarModuleLoader</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>For for my use cases 1) and 3) above, I believe my only options are to resort to a bit of a hack which unpacks the module root in a JAR to something that can be read by LocalModuleLoader. I'll paste that code below the fold[1].</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p><span>Use case 2) I hope to see more discussion on; I have a patch in </span><a class="jive-link-external-small" href="https://issues.jboss.org/browse/MODULES-146:" target="_blank">https://issues.jboss.org/browse/MODULES-146:</a><span> </span><a class="jive-link-external-small" href="https://github.com/jbossas/jboss-modules/pull/22">https://github.com/jbossas/jboss-modules/pull/22</a>.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>Because we probably don't want to be changing the existing SPI much, perhaps introducing a new ModuleRepository SPI layer would make sense looking forward?&#160; David has mentioned an "install" SPI, but I think "installation" is still an implementation detail with respect to module loading.&#160; I believe an abstraction between jboss-modules and any backing module repository (which is a VFS) will do.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>S,</p><p>ALR</p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>PS - I could even make a ShrinkWrap-based ModuleRepository. <span> :) </span></p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><p>[1] </p><p style="min-height: 8pt; height: 8pt; padding: 0px;">&#160;</p><pre class="jive-pre"><code class="jive-code jive-java"><font color="darkgreen">/*
 * JBoss, Home of Professional Open Source
 * Copyright 2012, 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.
 */</font>
<font color="navy"><b>package</b></font> org.jboss.arquillian.daemon.main;
&#160;
<font color="navy"><b>import</b></font> java.io.File;
<font color="navy"><b>import</b></font> java.io.FileOutputStream;
<font color="navy"><b>import</b></font> java.io.IOException;
<font color="navy"><b>import</b></font> java.io.InputStream;
<font color="navy"><b>import</b></font> java.io.OutputStream;
<font color="navy"><b>import</b></font> java.security.AccessController;
<font color="navy"><b>import</b></font> java.security.PrivilegedAction;
<font color="navy"><b>import</b></font> java.util.Enumeration;
<font color="navy"><b>import</b></font> java.util.UUID;
<font color="navy"><b>import</b></font> java.util.jar.JarEntry;
<font color="navy"><b>import</b></font> java.util.jar.JarFile;
&#160;
<font color="navy"><b>import</b></font> org.jboss.modules.LocalModuleLoader;
<font color="navy"><b>import</b></font> org.jboss.modules.Module;
<font color="navy"><b>import</b></font> org.jboss.modules.ModuleIdentifier;
<font color="navy"><b>import</b></font> org.jboss.modules.ModuleLoadException;
<font color="navy"><b>import</b></font> org.jboss.modules.ModuleLoader;
<font color="navy"><b>import</b></font> org.jboss.modules.ModuleSpec;
&#160;
<font color="darkgreen">/**
 * Hack implmentation of a {@link ModuleLoader} capable of loading modules contained in a JAR under a known module root.
 * Explodes the module root into a temporary directory on the filesystem, by which a delegate {@link LocalModuleLoader}
 * may then load the modules. Temporarily necessary due to API restrictions in jboss-modules whereby the JarModuleLoader
 * is not accessible, nor is parsing a {@link ModuleSpec} from a &lt;code&gt;module.xml&lt;/code&gt; file.
 *
 * @author &lt;a href="mailto:alr@jboss.org"&gt;Andrew Lee Rubinger&lt;/a&gt;
 * @deprecated In place until we can work out proper support for this either in jboss-modules or via a new jboss-modules
 *&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; API which lets us load from a JAR
 */</font>
@Deprecated
<font color="navy"><b>final</b></font> <font color="navy"><b>class</b></font> HackJarModuleLoader <font color="navy"><b>extends</b></font> ModuleLoader <font color="navy">{</font>
&#160;
&#160;&#160;&#160; <font color="navy"><b>private</b></font> <font color="navy"><b>static</b></font> <font color="navy"><b>final</b></font> String SYSPROP_NAME_TMP_DIR = <font color="red">"java.io.tmpdir"</font>;
&#160;&#160;&#160; <font color="navy"><b>private</b></font> <font color="navy"><b>static</b></font> <font color="navy"><b>final</b></font> String PREFIX_MODULES_DIR = <font color="red">"modules-"</font>;
&#160;
&#160;&#160;&#160; <font color="darkgreen">/**
&#160;&#160;&#160;&#160; * Local delegate for loading modules once unpacked
&#160;&#160;&#160;&#160; */</font>
&#160;&#160;&#160; <font color="navy"><b>private</b></font> <font color="navy"><b>final</b></font> ModuleLoader delegate;
&#160;
&#160;&#160;&#160; <font color="darkgreen">/**
&#160;&#160;&#160;&#160; * Target location the modules will be unpacked to
&#160;&#160;&#160;&#160; */</font>
&#160;&#160;&#160; <font color="navy"><b>private</b></font> <font color="navy"><b>final</b></font> File localModulesLocation;
&#160;
&#160;&#160;&#160; <font color="darkgreen">/**
&#160;&#160;&#160;&#160; * Creates a new {@link ModuleLoader} instance for the specified JAR file, where modules are located in a root
&#160;&#160;&#160;&#160; * denoted by the specified &lt;code&gt;moduleRoot&lt;/code&gt; parameter (which is relative to the root of the JAR).
&#160;&#160;&#160;&#160; *
&#160;&#160;&#160;&#160; * @param jar
&#160;&#160;&#160;&#160; * @param moduleRoot
&#160;&#160;&#160;&#160; * @throws IllegalArgumentException
&#160;&#160;&#160;&#160; *&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; If either argument is not specified
&#160;&#160;&#160;&#160; */</font>
&#160;&#160;&#160; <font color="navy"><b>public</b></font> HackJarModuleLoader(<font color="navy"><b>final</b></font> JarFile jar, <font color="navy"><b>final</b></font> String moduleRoot) <font color="navy"><b>throws</b></font> IllegalArgumentException <font color="navy">{</font>
&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="darkgreen">// Precondition checks</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (jar == <font color="navy"><b>null</b></font>) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>throw</b></font> <font color="navy"><b>new</b></font> IllegalArgumentException(<font color="red">"JAR file must be specified"</font>);
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (moduleRoot == <font color="navy"><b>null</b></font> || moduleRoot.length() == 0) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>throw</b></font> <font color="navy"><b>new</b></font> IllegalArgumentException(<font color="red">"Module root within the JAR must be specified"</font>);
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="darkgreen">// Set up the local temp modules directory</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> String tempDirName = SecurityActions.getSystemProperty(SYSPROP_NAME_TMP_DIR);
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> File tempDir = <font color="navy"><b>new</b></font> File(tempDirName);
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> File modulesDir = <font color="navy"><b>new</b></font> File(tempDir, PREFIX_MODULES_DIR + UUID.randomUUID().toString());
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (!modulesDir.mkdir()) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>throw</b></font> <font color="navy"><b>new</b></font> IllegalStateException(<font color="red">"Could not create modules directory: "</font> + modulesDir.getAbsolutePath());
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="darkgreen">// Explode</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> Enumeration&lt;JarEntry&gt; entries = jar.entries();
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>while</b></font> (entries.hasMoreElements()) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> JarEntry entry = entries.nextElement();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (entry.isDirectory()) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>continue</b></font>;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> String name = entry.getName();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (name.startsWith(moduleRoot)) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> String parsedFullFileName = name.substring(moduleRoot.length() + 1);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> <font color="navy"><b>int</b></font> lastDirIndex = parsedFullFileName.lastIndexOf(<font color="navy">'/'</font>);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (lastDirIndex &gt; 0) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> String targetRelativeDirName = parsedFullFileName.substring(0, lastDirIndex);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> File targetDir = <font color="navy"><b>new</b></font> File(modulesDir, targetRelativeDirName);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (!targetDir.exists()) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> <font color="navy"><b>boolean</b></font> created = targetDir.mkdirs();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (!created) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>throw</b></font> <font color="navy"><b>new</b></font> IllegalStateException(<font color="red">"Could not create target directory: "</font> + targetDir);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> String fileName = parsedFullFileName.substring(lastDirIndex);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> File targetFile = <font color="navy"><b>new</b></font> File(targetDir, fileName);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; registerRecursiveDeleteOnExit(targetFile, modulesDir);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; InputStream in = <font color="navy"><b>null</b></font>;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; OutputStream out = <font color="navy"><b>null</b></font>;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>try</b></font> <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; in = jar.getInputStream(entry);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; out = <font color="navy"><b>new</b></font> FileOutputStream(targetFile);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> <font color="navy"><b>byte</b></font>[] buffer = <font color="navy"><b>new</b></font> <font color="navy"><b>byte</b></font>[4096];
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>int</b></font> read = 0;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>while</b></font> ((read = in.read(buffer, 0, buffer.length)) != -1) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; out.write(buffer, 0, read);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font> <font color="navy"><b>catch</b></font> (<font color="navy"><b>final</b></font> IOException e) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>throw</b></font> <font color="navy"><b>new</b></font> RuntimeException(<font color="red">"Could not write "</font> + entry.getName() + <font color="red">" to "</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; + targetFile.getAbsolutePath(), e);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font> <font color="navy"><b>finally</b></font> <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (in != <font color="navy"><b>null</b></font>) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>try</b></font> <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; in.close();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font> <font color="navy"><b>catch</b></font> (<font color="navy"><b>final</b></font> IOException ioe) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="darkgreen">// Swallow</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (out != <font color="navy"><b>null</b></font>) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>try</b></font> <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; out.close();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font> <font color="navy"><b>catch</b></font> (<font color="navy"><b>final</b></font> IOException ioe) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="darkgreen">// Swallow</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="darkgreen">// Set</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; this.delegate = <font color="navy"><b>new</b></font> LocalModuleLoader(<font color="navy"><b>new</b></font> File[] <font color="navy">{</font> modulesDir <font color="navy">}</font>);
&#160;&#160;&#160;&#160;&#160;&#160;&#160; this.localModulesLocation = modulesDir;
&#160;
&#160;&#160;&#160; <font color="navy">}</font>
&#160;
&#160;&#160;&#160; <font color="darkgreen">/**
&#160;&#160;&#160;&#160; * {@inheritDoc}
&#160;&#160;&#160;&#160; *
&#160;&#160;&#160;&#160; * @see org.jboss.modules.ModuleLoader#preloadModule(org.jboss.modules.ModuleIdentifier)
&#160;&#160;&#160;&#160; */</font>
&#160;&#160;&#160; @Override
&#160;&#160;&#160; <font color="navy"><b>protected</b></font> Module preloadModule(<font color="navy"><b>final</b></font> ModuleIdentifier identifier) <font color="navy"><b>throws</b></font> ModuleLoadException <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>assert</b></font> identifier != <font color="navy"><b>null</b></font>;
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>return</b></font> ModuleLoader.preloadModule(identifier, delegate);
&#160;&#160;&#160; <font color="navy">}</font>
&#160;
&#160;&#160;&#160; <font color="darkgreen">/**
&#160;&#160;&#160;&#160; * {@inheritDoc}
&#160;&#160;&#160;&#160; *
&#160;&#160;&#160;&#160; * @see org.jboss.modules.ModuleLoader#toString()
&#160;&#160;&#160;&#160; */</font>
&#160;&#160;&#160; @Override
&#160;&#160;&#160; <font color="navy"><b>public</b></font> String toString() <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>return</b></font> HackJarModuleLoader.class.getSimpleName() + <font color="red">" delegating to modules in "</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; + localModulesLocation.getAbsolutePath();
&#160;&#160;&#160; <font color="navy">}</font>
&#160;
&#160;&#160;&#160; <font color="darkgreen">/**
&#160;&#160;&#160;&#160; * {@inheritDoc}
&#160;&#160;&#160;&#160; *
&#160;&#160;&#160;&#160; * @see org.jboss.modules.ModuleLoader#findModule(org.jboss.modules.ModuleIdentifier)
&#160;&#160;&#160;&#160; */</font>
&#160;&#160;&#160; @Override
&#160;&#160;&#160; <font color="navy"><b>protected</b></font> ModuleSpec findModule(<font color="navy"><b>final</b></font> ModuleIdentifier moduleIdentifier) <font color="navy"><b>throws</b></font> ModuleLoadException <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="darkgreen">// Due to incompatible API</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>throw</b></font> <font color="navy"><b>new</b></font> UnsupportedOperationException(<font color="red">"All loading should be done via the delegate in preoadModule"</font>);
&#160;&#160;&#160; <font color="navy">}</font>
&#160;
&#160;&#160;&#160; <font color="navy"><b>private</b></font> <font color="navy"><b>static</b></font> <font color="navy"><b>void</b></font> registerRecursiveDeleteOnExit(<font color="navy"><b>final</b></font> File child, <font color="navy"><b>final</b></font> File root) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (System.getSecurityManager() == <font color="navy"><b>null</b></font>) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; child.deleteOnExit();
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font> <font color="navy"><b>else</b></font> <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AccessController.doPrivileged(<font color="navy"><b>new</b></font> PrivilegedAction&lt;Void&gt;() <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @Override
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>public</b></font> Void run() <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; child.deleteOnExit();
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>return</b></font> <font color="navy"><b>null</b></font>;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>);
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>final</b></font> File parent = child.getParentFile();
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy"><b>if</b></font> (!child.equals(root)) <font color="navy">{</font>
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; registerRecursiveDeleteOnExit(parent, root);
&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="navy">}</font>
&#160;&#160;&#160; <font color="navy">}</font>
&#160;
<font color="navy">}</font>
</code></pre></div>

<div style="background-color: #f4f4f4; padding: 10px; margin-top: 20px;">
    <p style="margin: 0;">Reply to this message by <a href="https://community.jboss.org/message/772203#772203">going to Community</a></p>
        <p style="margin: 0;">Start a new discussion in JBoss AS 7 Development at <a href="https://community.jboss.org/choose-container!input.jspa?contentType=1&containerType=14&container=2225">Community</a></p>
</div></td>
                        </tr>
                    </tbody>
                </table>


                </td>
            </tr>
        </tbody>
    </table>

</div>

</body>
</html>