Hi,
2015-03-18 11:35 GMT+02:00 Mark Thomas :
>
> On 18/03/2015 09:00, Violeta Georgieva wrote:
> > Hi,
> >
> > I have an issue that I investigate and it led me to the implementation
> > of org.apache.catalina.startup.WebappServiceLoader.load(Class)
> >
> > So I have two scenarios:
> > - web application with web fragment inside the archive (WEB-INF/lib)
> > - web application with functionality of the fragment copied directly to
the
> > WEB-INF classes i.e. there is no web fragment.
> >
> > In the first scenario we (WebappServiceLoader.load) will search for
SCIs in
> > the web fragment using web app loader and then on row 121 we will
switch to
> > the paren loader and then continue searching the SCIs in other
locations.
> > In the second scenario we will search for SCIs always with the web app
> > loader.
> >
> > The problem that I'm investigating is in OSGi environment where the
parent
> > loader of the web app loader does not mean the same as in non OSGi
> > environment. When there is no web fragment I can find the container SCIs
> > (e.g. Web Socket implementation), but when there is web fragment I
cannot
> > find the SCIs anymore because of the switch of the loaders.
> >
> > Can you give me an advice how to overcome this issue?
> > I'm trying to use as much as possible from Tomcat implementation and to
> > plug only here and there in order to support OSGi environment.
>
> Hmm. Either we find a way to patch the WebappServiceLoader so it works
> with non-OSGI and OSGI environments or it looks like you'd have to use a
> custom ContextConfig implementation that used a different
> WebappServiceLoader.
>
> I've no objections to considering patching - with the usual caveats
> about the final decision coming down to what the actual patch looks like.
>
> If I have understood you correctly, the problematic line is:
> loader = loader.getParent()
>
> In the non-OSGI case loader.getParent() is the shared class loader (the
> Tomcat 5.5 class loader docs [1] are probably the better ones to look at
> in this case as it shows the full hierarchy which was collapsed in later
> versions).
>
> If this line was changed to:
> loader = context.getParentClassLoader()
I tried with quick patches in Tomcat and on my side and with one very basic
scenario and it is working.
I'll test a little bit more but at the moment this is the change that I
made in WebappServiceLoader (based on Tomcat 7 trunk):
Index: java/org/apache/catalina/startup/ContextConfig.java
===
--- java/org/apache/catalina/startup/ContextConfig.java (revision 1667469)
+++ java/org/apache/catalina/startup/ContextConfig.java (working copy)
@@ -1278,7 +1278,7 @@
// Step 3. Look for ServletContainerInitializer implementations
if (ok) {
-
processServletContainerInitializers(context.getServletContext());
+processServletContainerInitializers();
}
if (!webXml.isMetadataComplete() || typeInitializerMap.size() >
0) {
@@ -1567,13 +1567,13 @@
/**
* Scan JARs for ServletContainerInitializer implementations.
*/
-protected void processServletContainerInitializers(ServletContext
servletContext) {
+protected void processServletContainerInitializers() {
List detectedScis;
try {
WebappServiceLoader loader =
new WebappServiceLoader(
-servletContext,
context.getContainerSciFilter());
+context, context.getContainerSciFilter());
detectedScis = loader.load(ServletContainerInitializer.class);
} catch (IOException e) {
log.error(sm.getString(
Index: java/org/apache/catalina/startup/WebappServiceLoader.java
===
--- java/org/apache/catalina/startup/WebappServiceLoader.java (revision
1667469)
+++ java/org/apache/catalina/startup/WebappServiceLoader.java (working copy)
@@ -33,6 +33,8 @@
import javax.servlet.ServletContext;
+import org.apache.catalina.Context;
+
/**
* A variation of Java's JAR ServiceLoader that respects exclusion rules
for
* web applications.
@@ -57,7 +59,8 @@
private static final String SERVICES = "META-INF/services/";
private static final Charset UTF8 = Charset.forName("UTF-8");
-private final ServletContext context;
+private final ServletContext servletContext;
+private final Context context;
private final Pattern containerSciFilterPattern;
/**
@@ -65,8 +68,9 @@
*
* @param context the context to use
*/
-public WebappServiceLoader(ServletContext context, String
containerSciFilter) {
+public WebappServiceLoader(Context context, String containerSciFilter)
{
this.context = context;
+this.servletContext = context.getServletContext();
if (containerSciFilter != null && containerSciFilter.length() > 0)
{
containerSciFilterPattern =
P