|
What this is
Other links
The source code
/*
* Copyright 1999-2004 The Apache Sofware Foundation.
*
* 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.apache.tomcat.modules.config;
import java.io.File;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.tomcat.core.BaseInterceptor;
import org.apache.tomcat.core.Context;
import org.apache.tomcat.core.ContextManager;
import org.apache.tomcat.core.Request;
import org.apache.tomcat.core.TomcatException;
import org.apache.tomcat.util.compat.Jdk11Compat;
import org.apache.tomcat.util.compat.SimpleClassLoader;
/**
* Set class loader based on WEB-INF/classes, lib.
* Compatible with JDK1.1, but takes advantage of URLClassLoader if
* java2 is detected.
*
* Note. LoaderInterceptor must be the first in the reload and contextInit
* chains.
*
* @author costin@dnt.ro
*/
public class LoaderInterceptor11 extends BaseInterceptor {
boolean useAppsL=true;
boolean useParentL=false;
boolean useCommonL=false;
boolean useContainerL=false;
boolean useNoParent=false;
boolean use11Loader=false;
boolean addJaxp=true;
private int attributeInfo;
String loader=null;
Vector jaxpJars=new Vector();
String jaxpJarsSDefault="jaxp.jar:crimson.jar:xalan.jar:xerces.jar";
String jaxpJarsS=null;
String jaxpDir=null;
Vector additionalJars=new Vector();
String additionalJarsS=null;
String jarSeparator=":";
static final String clAttribute = "org.apache.tomcat.classloader";
public LoaderInterceptor11() {
}
/** Use ContextManager.getParentLoader() - typlically the class loader
* that is set by the application embedding tomcat.
*/
public void setUseApplicationLoader( boolean b ) {
useAppsL=b;
}
/** Use no parent loader. The contexts will be completely isolated.
*/
public void setUseNoParent( boolean b ) {
useNoParent=b;
}
/** Use the 1.1 loader even if running under Java2.
* This allows for a work-around to the currently broken URLClassLoader
* which can't reload classes from changed jar files.
*/
public void setUse11Loader( boolean b ) {
use11Loader = b;
}
/** Directory where jaxp jars are installed. Defaults to
tomcat_install/lib/container, where the parser used by
tomcat internally is located.
*/
public void setJaxpDir(String dir ) {
jaxpDir=dir;
}
/** Name of the jars that compose jaxp.
Defaults to jaxp.jar:crimson.jar:xalan.jar:xerces.jar,
it'll match either crimson or xerces.
*/
public void setJaxpJars(String jars ) {
jaxpJarsS=jars;
}
/** List of additional jars to add to each web application.
*/
public void setAdditionalJars(String jars ) {
additionalJarsS=jars;
}
/** Character to use to separate jars in the jaxpJars list.
It also applies to the additionalJars context property
list.
*/
public void setJarSeparator(String sep) {
if( sep != null && sep.length() > 0 ) {
if( sep.length() > 1 )
sep = sep.substring(0,1);
char oldSep[]=new char[1];
char newSep[]=new char[1];
jarSeparator.getChars(0,1,oldSep,0 );
sep.getChars(0,1,newSep,0);
jaxpJarsSDefault=jaxpJarsSDefault.replace(oldSep[0],newSep[0]);
jarSeparator=sep;
}
}
/** Check if the webapp contains jaxp , and add one if not.
This allow apps to include their own parser if they want,
while using the normal delegation model.
A future module will extend this and implement a more
advanced and generic mechanism
*/
public void setJaxp( boolean b ) {
addJaxp=b;
}
public void setLoader( String name ) {
loader=name;
}
public void engineInit( ContextManager cm )
throws TomcatException
{
attributeInfo=cm.getNoteId(ContextManager.REQUEST_NOTE,
"req.attribute");
initJaxpJars();
initAdditionalJars();
}
/** Add all WEB-INF/classes and WEB-INF/lib to the context
* path
*/
public void addContext( ContextManager cm, Context context)
throws TomcatException
{
String base = context.getAbsolutePath();
// Add "WEB-INF/classes"
File dir = new File(base + "/WEB-INF/classes");
// GS, Fix for the jar@lib directory problem.
// Thanks for Kevin Jones for providing the fix.
if( dir.exists() ) {
try {
// Note: URLClassLoader in JDK1.2.2 doesn't work with file URLs
// that contain '\' characters. Insure only '/' is used.
URL url=new URL( "file", null,
dir.getAbsolutePath().replace('\\','/') + "/" );
context.addClassPath( url );
} catch( MalformedURLException ex ) {
}
}
File f = new File(base + "/WEB-INF/lib");
Vector jars = new Vector();
getJars(jars, f);
for(int i=0; i < jars.size(); ++i) {
String jarfile = (String) jars.elementAt(i);
File jf=new File(f, jarfile );
// Note: URLClassLoader in JDK1.2.2 doesn't work with file URLs
// that contain '\' characters. Insure only '/' is used.
String absPath=jf.getAbsolutePath().replace('\\','/');
try {
URL url=new URL( "file", null, absPath );
context.addClassPath( url );
} catch( MalformedURLException ex ) {
}
}
}
/** setup the ClassLoader for this context.
* If this is a re-loaded context, do nothing.
*/
public void contextInit( Context ctx )
throws TomcatException
{
// jsp will add it's own stuff
if(ctx.getAttribute(clAttribute) == null) {
prepareClassLoader( ctx );
}
}
public void copyContext(Request req, Context oldC, Context newC)
throws TomcatException {
if(debug > 0)
log( "Reload event " + newC.getPath() );
// construct a new loader
ClassLoader oldLoader=oldC.getClassLoader();
// will be used by reloader or other modules to try to
// migrate the data.
newC.getContainer().setNote( "oldLoader", oldLoader);
}
/** Construct another class loader, when the context is reloaded.
*/
public void reload( Request req, Context context) throws TomcatException {
if( debug > 0 )
log( "Reload event " + context.getPath() );
// construct a new loader
ClassLoader oldLoader=context.getClassLoader();
// will be used by reloader or other modules to try to
// migrate the data.
context.getContainer().setNote( "oldLoader", oldLoader);
ClassLoader loader=constructLoader( context );
if( debug>5 ) {
URL classP[]=context.getClassPath();
log(" Context classpath URLs:");
for (int i = 0; i < classP.length; i++)
log(" " + classP[i].toString() );
}
context.setClassLoader( loader );
context.setAttribute( clAttribute, loader);
}
/** Initialize the class loader.
*
*/
public void prepareClassLoader(Context context) throws TomcatException {
String list = context.getProperty("additionalJars");
if( list != null ) {
Vector urls=new Vector();
getUrls( null, list, urls );
Enumeration en=urls.elements();
while( en.hasMoreElements() ) {
URL url=(URL)en.nextElement();
if( debug > 0 ) log(context + " adding: " + url);
context.addClassPath( url );
}
}
Enumeration en=additionalJars.elements();
while( en.hasMoreElements() ) {
URL url=(URL)en.nextElement();
if( debug > 0 ) log(context + " adding: " + url);
context.addClassPath( url );
}
ClassLoader loader=constructLoader( context );
if( addJaxp ) {
boolean hasJaxp=checkJaxp( loader, context );
if( ! hasJaxp ) {
en=jaxpJars.elements();
while( en.hasMoreElements() ) {
URL url=(URL)en.nextElement();
if( debug > 0 ) log(context + " adding jaxp: " + url);
context.addClassPath( url );
}
loader=constructLoader( context );
}
}
if( debug>5 ) {
URL classP[]=context.getClassPath();
log(" Context classpath URLs:");
for (int i = 0; i < classP.length; i++)
log(" " + classP[i].toString() );
}
context.setClassLoader( loader );
// support for jasper and other applications
context.setAttribute(clAttribute, loader);
}
/** Override this method to provide an alternate loader
* (or create a new interceptor )
*/
protected ClassLoader constructLoader(Context context )
throws TomcatException
{
URL classP[]=context.getClassPath();
ClassLoader parent=null;
if( useNoParent ) {
if( debug > 0 ) log( "Using no parent loader ");
parent=null;
} else if( useAppsL && !context.isTrusted() ) {
if( debug > 0 ) log( "Using webapp loader ");
parent=cm.getAppsLoader();
} else {
if( debug > 0 ) log( "Using container loader ");
parent=this.getClass().getClassLoader();
}
ClassLoader loader=null;
if( use11Loader ) {
loader = new SimpleClassLoader(classP, parent);
} else {
loader=jdk11Compat.newClassLoaderInstance( classP, parent);
}
if( debug > 0 )
log("Loader " + loader.getClass().getName() + " " + parent);
// If another reloading scheme is implemented, you'll
// have to plug it in here.
return loader;
}
private void initJaxpJars() {
if( jaxpJarsS == null )
jaxpJarsS=jaxpJarsSDefault;
getUrls( jaxpDir, jaxpJarsS, jaxpJars );
}
private void initAdditionalJars() {
if( additionalJarsS != null )
getUrls( null, additionalJarsS, additionalJars );
}
private void getUrls( String dir, String jarList, Vector jars ) {
if( dir == null ) dir=cm.getInstallDir() + "/lib/container";
File base=new File( dir );
if( debug > 5 ) log( "Scanning \"" + jarList + "\" with base directory " + base);
StringTokenizer st=new StringTokenizer( jarList, jarSeparator );
while( st.hasMoreElements() ) {
String s=(String)st.nextElement();
File f=new File( s );
if( ! f.isAbsolute() )
f=new File( base, s);
if( ! f.exists() ) continue;
try {
URL url=new URL( "file", null,
f.getAbsolutePath().replace('\\','/'));
jars.addElement( url );
if( debug > 5 ) log( "Adding " + url );
} catch( MalformedURLException ex ) {
}
}
}
private boolean checkJaxp( ClassLoader loader, Context context ) {
try {
loader.loadClass("javax.xml.parsers.SAXParserFactory");
return true;
} catch( Exception ex) {
// Add jaxp to classP.
if( debug > 0 ) context.log( "Jaxp not detected, adding jaxp ");
return false;
}
}
// --------------------
private static final String separator =
System.getProperty("path.separator", ":");
public final Object getInfo( Context ctx, Request req,
int info, String k )
{
if( req!=null )
return null;
if( info== attributeInfo ) {
// request for a context attribute, handled by tomcat
if( ! k.startsWith( "org.apache.tomcat" ) )
return null;
if (k.equals("org.apache.tomcat.jsp_classpath")) {
return getClassPath(ctx);
}
if(k.equals(clAttribute)) {
return ctx.getClassLoader();
}
}
return null;
}
static Jdk11Compat jdkProxy=Jdk11Compat.getJdkCompat();
private String getClassPath(Context ctx) {
StringBuffer cpath=new StringBuffer();
// local context class path
URL classPaths[]=ctx.getClassPath();
convertClassPath( cpath , classPaths );
ClassLoader Loader=ctx.getClassLoader();
// apps class loader
convertClassPath(cpath, jdkProxy.getURLs(Loader,1));
// common class loader
convertClassPath(cpath, jdkProxy.getURLs(Loader,2));
if( debug>9 )
log("Getting classpath " + cpath);
return cpath.toString();
}
private void convertClassPath( StringBuffer cpath, URL classPaths[] ) {
if( classPaths==null ) return;
for(int i=0; i< classPaths.length ; i++ ) {
URL cp = classPaths[i];
if (cpath.length()>0) cpath.append( separator );
cpath.append(cp.getFile());
}
}
static final Jdk11Compat jdk11Compat=Jdk11Compat.getJdkCompat();
private void getJars(Vector v, File f) {
FilenameFilter jarfilter = new FilenameFilter() {
public boolean accept(File dir, String fname) {
if(fname.endsWith(".jar"))
return true;
return false;
}
};
FilenameFilter dirfilter = new FilenameFilter() {
public boolean accept(File dir, String fname) {
File f1 = new File(dir, fname);
if(f1.isDirectory())
return true;
return false;
}
};
if(f.exists() && f.isDirectory() && f.isAbsolute()) {
String[] jarlist = f.list(jarfilter);
for(int i=0; (jarlist != null) && (i < jarlist.length); ++i) {
v.addElement(jarlist[i]);
}
String[] dirlist = f.list(dirfilter);
for(int i=0; (dirlist != null) && (i < dirlist.length); ++i) {
File dir = new File(f, dirlist[i]);
getJars(v, dir);
}
}
}
}
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.