📄 webapploader.java
字号:
// Process this property change
boolean oldReloadable = this.reloadable;
this.reloadable = reloadable;
support.firePropertyChange("reloadable",
new Boolean(oldReloadable),
new Boolean(this.reloadable));
}
// --------------------------------------------------------- Public Methods
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
/**
* Add a new repository to the set of repositories for this class loader.
*
* @param repository Repository to be added
*/
public void addRepository(String repository) {
if (log.isDebugEnabled())
log.debug(sm.getString("webappLoader.addRepository", repository));
for (int i = 0; i < repositories.length; i++) {
if (repository.equals(repositories[i]))
return;
}
String results[] = new String[repositories.length + 1];
for (int i = 0; i < repositories.length; i++)
results[i] = repositories[i];
results[repositories.length] = repository;
repositories = results;
if (started && (classLoader != null)) {
classLoader.addRepository(repository);
if( loaderRepositories != null ) loaderRepositories.add(repository);
setClassPath();
}
}
/**
* Return the set of repositories defined for this class loader.
* If none are defined, a zero-length array is returned.
* For security reason, returns a clone of the Array (since
* String are immutable).
*/
public String[] findRepositories() {
return ((String[])repositories.clone());
}
public String[] getRepositories() {
return ((String[])repositories.clone());
}
/** Extra repositories for this loader
*/
public String getRepositoriesString() {
StringBuffer sb=new StringBuffer();
for( int i=0; i<repositories.length ; i++ ) {
sb.append( repositories[i]).append(":");
}
return sb.toString();
}
public String[] getLoaderRepositories() {
if( loaderRepositories==null ) return null;
String res[]=new String[ loaderRepositories.size()];
loaderRepositories.toArray(res);
return res;
}
public String getLoaderRepositoriesString() {
String repositories[]=getLoaderRepositories();
StringBuffer sb=new StringBuffer();
for( int i=0; i<repositories.length ; i++ ) {
sb.append( repositories[i]).append(":");
}
return sb.toString();
}
/**
* Classpath, as set in org.apache.catalina.jsp_classpath context
* property
*
* @return The classpath
*/
public String getClasspath() {
return classpath;
}
/**
* Has the internal repository associated with this Loader been modified,
* such that the loaded classes should be reloaded?
*/
public boolean modified() {
return (classLoader.modified());
}
/**
* Used to periodically signal to the classloader to release JAR resources.
*/
public void closeJARs(boolean force) {
if (classLoader !=null){
classLoader.closeJARs(force);
}
}
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
/**
* Return a String representation of this component.
*/
public String toString() {
StringBuffer sb = new StringBuffer("WebappLoader[");
if (container != null)
sb.append(container.getName());
sb.append("]");
return (sb.toString());
}
// ------------------------------------------------------ Lifecycle Methods
/**
* Add a lifecycle event listener to this component.
*
* @param listener The listener to add
*/
public void addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}
/**
* Get the lifecycle listeners associated with this lifecycle. If this
* Lifecycle has no listeners registered, a zero-length array is returned.
*/
public LifecycleListener[] findLifecycleListeners() {
return lifecycle.findLifecycleListeners();
}
/**
* Remove a lifecycle event listener from this component.
*
* @param listener The listener to remove
*/
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
private boolean initialized=false;
public void init() {
initialized=true;
if( oname==null ) {
// not registered yet - standalone or API
if( container instanceof StandardContext) {
// Register ourself. The container must be a webapp
try {
StandardContext ctx=(StandardContext)container;
Engine eng=(Engine)ctx.getParent().getParent();
String path = ctx.getPath();
if (path.equals("")) {
path = "/";
}
oname=new ObjectName(ctx.getEngineName() + ":type=Loader,path=" +
path + ",host=" + ctx.getParent().getName());
Registry.getRegistry(null, null).registerComponent(this, oname, null);
controller=oname;
} catch (Exception e) {
log.error("Error registering loader", e );
}
}
}
if( container == null ) {
// JMX created the loader
// TODO
}
}
public void destroy() {
if( controller==oname ) {
// Self-registration, undo it
Registry.getRegistry(null, null).unregisterComponent(oname);
oname = null;
}
initialized = false;
}
/**
* Start this component, initializing our associated class loader.
*
* @exception LifecycleException if a lifecycle error occurs
*/
public void start() throws LifecycleException {
// Validate and update our current component state
if( ! initialized ) init();
if (started)
throw new LifecycleException
(sm.getString("webappLoader.alreadyStarted"));
if (log.isDebugEnabled())
log.debug(sm.getString("webappLoader.starting"));
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
if (container.getResources() == null) {
log.info("No resources for " + container);
return;
}
// Register a stream handler factory for the JNDI protocol
URLStreamHandlerFactory streamHandlerFactory =
new DirContextURLStreamHandlerFactory();
if (first) {
first = false;
try {
URL.setURLStreamHandlerFactory(streamHandlerFactory);
} catch (Exception e) {
// Log and continue anyway, this is not critical
log.error("Error registering jndi stream handler", e);
} catch (Throwable t) {
// This is likely a dual registration
log.info("Dual registration of jndi stream handler: "
+ t.getMessage());
}
}
// Construct a class loader based on our current repositories list
try {
classLoader = createClassLoader();
classLoader.setResources(container.getResources());
classLoader.setDebug(this.debug);
classLoader.setDelegate(this.delegate);
for (int i = 0; i < repositories.length; i++) {
classLoader.addRepository(repositories[i]);
}
// Configure our repositories
setRepositories();
setClassPath();
setPermissions();
if (classLoader instanceof Lifecycle)
((Lifecycle) classLoader).start();
// Binding the Webapp class loader to the directory context
DirContextURLStreamHandler.bind
((ClassLoader) classLoader, this.container.getResources());
} catch (Throwable t) {
log.error( "LifecycleException ", t );
throw new LifecycleException("start: ", t);
}
}
/**
* Stop this component, finalizing our associated class loader.
*
* @exception LifecycleException if a lifecycle error occurs
*/
public void stop() throws LifecycleException {
// Validate and update our current component state
if (!started)
throw new LifecycleException
(sm.getString("webappLoader.notStarted"));
if (log.isDebugEnabled())
log.debug(sm.getString("webappLoader.stopping"));
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
// Remove context attributes as appropriate
if (container instanceof Context) {
ServletContext servletContext =
((Context) container).getServletContext();
servletContext.removeAttribute(Globals.CLASS_PATH_ATTR);
}
// Throw away our current class loader
if (classLoader instanceof Lifecycle)
((Lifecycle) classLoader).stop();
DirContextURLStreamHandler.unbind((ClassLoader) classLoader);
classLoader = null;
destroy();
}
// ----------------------------------------- PropertyChangeListener Methods
/**
* Process property change events from our associated Context.
*
* @param event The property change event that has occurred
*/
public void propertyChange(PropertyChangeEvent event) {
// Validate the source of this event
if (!(event.getSource() instanceof Context))
return;
Context context = (Context) event.getSource();
// Process a relevant property change
if (event.getPropertyName().equals("reloadable")) {
try {
setReloadable
( ((Boolean) event.getNewValue()).booleanValue() );
} catch (NumberFormatException e) {
log.error(sm.getString("webappLoader.reloadable",
event.getNewValue().toString()));
}
}
}
// ------------------------------------------------------- Private Methods
/**
* Create associated classLoader.
*/
private WebappClassLoader createClassLoader()
throws Exception {
Class clazz = Class.forName(loaderClass);
WebappClassLoader classLoader = null;
if (parentClassLoader == null) {
parentClassLoader = Thread.currentThread().getContextClassLoader();
}
Class[] argTypes = { ClassLoader.class };
Object[] args = { parentClassLoader };
Constructor constr = clazz.getConstructor(argTypes);
classLoader = (WebappClassLoader) constr.newInstance(args);
return classLoader;
}
/**
* Log a message on the Logger associated with our Container (if any)
*
* @param message Message to be logged
*/
private void log(String message) {
Logger logger = null;
if (container != null)
logger = container.getLogger();
if (logger != null)
logger.log("WebappLoader[" + container.getName() + "]: "
+ message);
else {
String containerName = null;
if (container != null)
containerName = container.getName();
System.out.println("WebappLoader[" + containerName
+ "]: " + message);
}
}
/**
* Log a message on the Logger associated with our Container (if any)
*
* @param message Message to be logged
* @param throwable Associated exception
*/
private void log(String message, Throwable throwable) {
Logger logger = null;
if (container != null)
logger = container.getLogger();
if (logger != null) {
logger.log("WebappLoader[" + container.getName() + "] "
+ message, throwable);
} else {
String containerName = null;
if (container != null)
containerName = container.getName();
System.out.println("WebappLoader[" + containerName
+ "]: " + message);
System.out.println("" + throwable);
throwable.printStackTrace(System.out);
}
}
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -