| Method from org.jboss.web.AbstractWebContainer Detail: |
public boolean accepts(DeploymentInfo sdi) {
String warFile = sdi.url.getFile();
return warFile.endsWith("war") || warFile.endsWith("war/");
}
|
protected void addEnvEntries(Iterator envEntries,
Context envCtx) throws NamingException, ClassNotFoundException {
while( envEntries.hasNext() )
{
EnvEntryMetaData entry = (EnvEntryMetaData) envEntries.next();
log.debug("Binding env-entry: "+entry.getName()+" of type: " +
entry.getType()+" to value:"+entry.getValue());
EnvEntryMetaData.bindEnvEntry(envCtx, entry);
}
}
|
protected URL[] getClassLoaderURLs(ClassLoader cl) {
URL[] urls = {};
try
{
Class returnType = urls.getClass();
Class[] parameterTypes = {};
Method getURLs = cl.getClass().getMethod("getURLs", parameterTypes);
if( returnType.isAssignableFrom(getURLs.getReturnType()) )
{
Object[] args = {};
urls = (URL[]) getURLs.invoke(cl, args);
}
if( urls == null || urls.length == 0 )
{
getURLs = cl.getClass().getMethod("getAllURLs", parameterTypes);
if( returnType.isAssignableFrom(getURLs.getReturnType()) )
{
Object[] args = {};
urls = (URL[]) getURLs.invoke(cl, args);
}
}
}
catch(Exception ignore)
{
}
return urls;
}
Use reflection to access a URL[] getURLs method so that non-URLClassLoader
class loaders that support this method can provide info. |
public String[] getCompileClasspath(ClassLoader loader) {
HashSet tmp = new HashSet();
ClassLoader cl = loader;
while( cl != null )
{
URL[] urls = getClassLoaderURLs(cl);
addURLs(tmp, urls);
cl = cl.getParent();
}
try
{
URL[] globalUrls = (URL[])getServer().getAttribute(LoaderRepositoryFactory.DEFAULT_LOADER_REPOSITORY,
"URLs");
addURLs(tmp, globalUrls);
}
catch (Exception e)
{
log.warn("Could not get global URL[] from default loader repository!");
} // end of try-catch
log.trace("JSP CompileClasspath: " + tmp);
String[] cp = new String[tmp.size()];
tmp.toArray(cp);
return cp;
}
A utility method that walks up the ClassLoader chain starting at
the given loader and queries each ClassLoader for a 'URL[] getURLs()'
method from which a complete classpath of URL strings is built. |
public Element getConfig() {
return null;
}
An accessor for any configuration element set via setConfig. This
method always returns null and must be overriden by subclasses to
return a valid value. |
public WebApplication getDeployedApp(String warUrl) {
WebApplication appInfo = (WebApplication) deploymentMap.get(warUrl);
return appInfo;
}
Get the WebApplication object for a deployed war. |
public Iterator getDeployedApplications() {
return deploymentMap.values().iterator();
}
Returns the applications deployed by the web container subclasses. |
public boolean getJava2ClassLoadingCompliance() {
return java2ClassLoadingCompliance;
}
Get the flag indicating if the normal Java2 parent first class loading
model should be used over the servlet 2.3 web container first model. |
public boolean getLenientEjbLink() {
return lenientEjbLink;
}
Get the flag indicating if ejb-link errors should be ignored
in favour of trying the jndi-name in jboss-web.xml |
public String[] getStandardCompileClasspath(ClassLoader loader) {
String[] jspResources = {
"javax/servlet/resources/web-app_2_3.dtd",
"org/apache/jasper/resources/jsp12.dtd",
"javax/ejb/EJBHome.class"
};
ArrayList tmp = new ArrayList();
for(int j = 0; j < jspResources.length; j ++)
{
URL rsrcURL = loader.getResource(jspResources[j]);
if( rsrcURL != null )
{
String url = rsrcURL.toExternalForm();
if( rsrcURL.getProtocol().equals("jar") )
{
// Parse the jar:< url >!/{entry} URL
url = url.substring(4);
int seperator = url.indexOf('!");
url = url.substring(0, seperator);
}
tmp.add(url);
}
else
{
log.warn("Failed to fin jsp rsrc: "+jspResources[j]);
}
}
log.trace("JSP StandardCompileClasspath: " + tmp);
String[] cp = new String[tmp.size()];
tmp.toArray(cp);
return cp;
}
A utility method that searches the given loader for the
resources: "javax/servlet/resources/web-app_2_3.dtd",
"org/apache/jasper/resources/jsp12.dtd", and "javax/ejb/EJBHome.class"
and returns an array of URL strings. Any jar: urls are reduced to the
underlying portion of the 'jar:!/{entry}' construct. |
public boolean getUnpackWars() {
return unpackWars;
}
Set the flag indicating if war archives should be unpacked. This may
need to be set to false as long extraction paths under deploy can
show up as deployment failures on some platforms. |
public synchronized void init(DeploymentInfo di) throws DeploymentException {
log.debug("Begin init");
try
{
if (di.url.getPath().endsWith("/"))
{
// the URL is a unpacked collection, watch the deployment descriptor
di.watch = new URL(di.url, "WEB-INF/web.xml");
}
else
{
// just watch the original URL
di.watch = di.url;
}
// Make sure the war is unpacked if unpackWars is true
File warFile = new File(di.localUrl.getFile());
if( warFile.isDirectory() == false && unpackWars == true )
{
File tmp = new File(warFile.getAbsolutePath()+".tmp");
if( warFile.renameTo(tmp) == false )
throw new DeploymentException("Was unable to move war to: "+tmp);
if( warFile.mkdir() == false )
throw new DeploymentException("Was unable to mkdir: "+warFile);
log.debug("Unpacking war to: "+warFile);
FileInputStream fis = new FileInputStream(tmp);
JarUtils.unjar(fis, warFile);
fis.close();
log.debug("Replaced war with unpacked contents");
if( tmp.delete() == false )
log.debug("Was unable to delete war tmp file");
else
log.debug("Deleted war archive");
// Reset the localUrl to end in a '/'
di.localUrl = warFile.toURL();
// Reset the localCl to point to the file
URL[] localCP = {di.localUrl};
di.localCl = new URLClassLoader(localCP);
}
WebMetaData metaData = new WebMetaData();
metaData.setJava2ClassLoadingCompliance(this.java2ClassLoadingCompliance);
di.metaData = metaData;
// Check for a loader-repository
XmlFileLoader xfl = new XmlFileLoader();
InputStream in = di.localCl.getResourceAsStream("WEB-INF/jboss-web.xml");
if( in != null )
{
Element jbossWeb = xfl.getDocument(in, "WEB-INF/jboss-web.xml").getDocumentElement();
in.close();
// Check for a war level class loading config
Element classLoading = MetaData.getOptionalChild(jbossWeb, "class-loading");
if( classLoading != null )
{
String flagString = classLoading.getAttribute("java2ClassLoadingCompliance");
if( flagString.length() == 0 )
flagString = "true";
boolean flag = Boolean.valueOf(flagString).booleanValue();
metaData.setJava2ClassLoadingCompliance(flag);
// Check for a loader-repository for scoping
Element loader = MetaData.getOptionalChild(classLoading, "loader-repository");
if( loader != null )
{
LoaderRepositoryConfig config = LoaderRepositoryFactory.parseRepositoryConfig(loader);
di.setRepositoryInfo(config);
}
}
}
// Generate an event for the initialization
super.init(di);
}
catch (Exception e)
{
log.error("Problem in init ", e);
throw new DeploymentException(e);
}
log.debug("End init");
}
|
public boolean isDeployed(String warUrl) {
return deploymentMap.containsKey(warUrl);
}
See if a war is deployed. |
protected void linkEjbLocalRefs(Iterator ejbRefs,
Context envCtx,
DeploymentInfo di) throws NamingException {
while( ejbRefs.hasNext() )
{
EjbLocalRefMetaData ejb = (EjbLocalRefMetaData) ejbRefs.next();
String name = ejb.getName();
String linkName = ejb.getLink();
String jndiName = null;
//use the ejb-link field if it is specified
if ( linkName != null )
{
jndiName = EjbUtil.findLocalEjbLink(server, di, linkName);
//if flag does not allow misconfigured ejb-links, it is an error
if ( ( jndiName == null ) && !(getLenientEjbLink()) )
throw new NamingException("ejb-ref: "+name+", no ejb-link match");
}
if (jndiName == null)
{
jndiName = ejb.getJndiName();
if ( jndiName == null )
{
String msg = null;
if( linkName == null )
{
msg = "ejb-local-ref: '"+name+"', no ejb-link in web.xml and "
+ "no local-jndi-name in jboss-web.xml";
}
else
{
msg = "ejb-local-ref: '"+name+"', with web.xml ejb-link: '"
+ linkName + "' failed to resolve to an ejb with a LocalHome";
}
throw new NamingException(msg);
}
}
log.debug("Linking ejb-local-ref: "+name+" to JNDI name: "+jndiName);
Util.bind(envCtx, name, new LinkRef(jndiName));
}
}
|
protected void linkEjbRefs(Iterator ejbRefs,
Context envCtx,
DeploymentInfo di) throws NamingException {
while( ejbRefs.hasNext() )
{
EjbRefMetaData ejb = (EjbRefMetaData) ejbRefs.next();
String name = ejb.getName();
String linkName = ejb.getLink();
String jndiName = null;
//use ejb-link if it is specified
if ( linkName != null )
{
jndiName = EjbUtil.findEjbLink(server, di, linkName);
//if flag does not allow misconfigured ejb-links, it is an error
if ( ( jndiName == null ) && !(getLenientEjbLink()) )
throw new NamingException("ejb-ref: "+name+", no ejb-link match");
}
//fall through to the jndiName
if ( jndiName == null )
{
jndiName = ejb.getJndiName();
if (jndiName == null )
throw new NamingException("ejb-ref: "+name+", no ejb-link in web.xml and no jndi-name in jboss-web.xml");
}
log.debug("Linking ejb-ref: "+name+" to JNDI name: "+jndiName);
Util.bind(envCtx, name, new LinkRef(jndiName));
}
}
|
protected void linkResourceEnvRefs(Iterator resourceEnvRefs,
Context envCtx) throws NamingException {
while( resourceEnvRefs.hasNext() )
{
ResourceEnvRefMetaData ref = (ResourceEnvRefMetaData) resourceEnvRefs.next();
String resourceName = ref.getJndiName();
String refName = ref.getRefName();
if( ref.getType().equals("java.net.URL") )
{
try
{
log.debug("Binding '"+refName+"' to URL: "+resourceName);
URL url = new URL(resourceName);
Util.bind(envCtx, refName, url);
}
catch(MalformedURLException e)
{
throw new NamingException("Malformed URL:"+e.getMessage());
}
}
else if( resourceName != null )
{
log.debug("Linking '"+refName+"' to JNDI name: "+resourceName);
Util.bind(envCtx, refName, new LinkRef(resourceName));
}
else
{
throw new NamingException("resource-env-ref: "+refName
+" has no valid JNDI binding. Check the jboss-web/resource-env-ref.");
}
}
}
|
protected void linkResourceRefs(Iterator resourceRefs,
Context envCtx) throws NamingException {
while( resourceRefs.hasNext() )
{
ResourceRefMetaData ref = (ResourceRefMetaData) resourceRefs.next();
String jndiName = ref.getJndiName();
String refName = ref.getRefName();
if( ref.getType().equals("java.net.URL") )
{
try
{
log.debug("Binding '"+refName+"' to URL: "+jndiName);
URL url = new URL(jndiName);
Util.bind(envCtx, refName, url);
}
catch(MalformedURLException e)
{
throw new NamingException("Malformed URL:"+e.getMessage());
}
}
else if( jndiName != null )
{
log.debug("Linking '"+refName+"' to JNDI name: "+jndiName);
Util.bind(envCtx, refName, new LinkRef(jndiName));
}
else
{
throw new NamingException("resource-ref: "+refName
+" has no valid JNDI binding. Check the jboss-web/resource-ref.");
}
}
}
|
protected void linkSecurityDomain(String securityDomain,
Context envCtx) throws NamingException {
if( securityDomain == null )
{
log.debug("Binding security/securityMgr to NullSecurityManager");
Object securityMgr = new NullSecurityManager("java:/jaas/null");
Util.bind(envCtx, "security/securityMgr", securityMgr);
Util.bind(envCtx, "security/realmMapping", securityMgr);
Util.bind(envCtx, "security/security-domain", new LinkRef("java:/jaas/null"));
Util.bind(envCtx, "security/subject", new LinkRef("java:/jaas/null/subject"));
}
else
{
log.debug("Linking security/securityMgr to JNDI name: "+securityDomain);
Util.bind(envCtx, "security/securityMgr", new LinkRef(securityDomain));
Util.bind(envCtx, "security/realmMapping", new LinkRef(securityDomain));
Util.bind(envCtx, "security/security-domain", new LinkRef(securityDomain));
Util.bind(envCtx, "security/subject", new LinkRef(securityDomain+"/subject"));
}
}
This creates a java:comp/env/security context that contains a
securityMgr binding pointing to an AuthenticationManager implementation
and a realmMapping binding pointing to a RealmMapping implementation.
If the jboss-web.xml descriptor contained a security-domain element
then the bindings are LinkRefs to the jndi name specified by the
security-domain element. If there was no security-domain element then
the bindings are to NullSecurityManager instance which simply allows
all access. |
protected void parseMetaData(String ctxPath,
URL warURL,
String warName,
WebMetaData metaData) throws DeploymentException {
InputStream jbossWebIS = null;
InputStream webIS = null;
// Parse the war deployment descriptors, web.xml and jboss-web.xml
try
{
// See if the warUrl is a directory
File warDir = new File(warURL.getFile());
if( warURL.getProtocol().equals("file") && warDir.isDirectory() == true )
{
File webDD = new File(warDir, "WEB-INF/web.xml");
if( webDD.exists() == true )
webIS = new FileInputStream(webDD);
File jbossWebDD = new File(warDir, "WEB-INF/jboss-web.xml");
if( jbossWebDD.exists() == true )
jbossWebIS = new FileInputStream(jbossWebDD);
}
else
{
// First check for a WEB-INF/web.xml and a WEB-INF/jboss-web.xml
InputStream warIS = warURL.openStream();
java.util.zip.ZipInputStream zipIS = new java.util.zip.ZipInputStream(warIS);
java.util.zip.ZipEntry entry;
byte[] buffer = new byte[512];
int bytes;
while( (entry = zipIS.getNextEntry()) != null )
{
if( entry.getName().equals("WEB-INF/web.xml") )
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while( (bytes = zipIS.read(buffer)) > 0 )
{
baos.write(buffer, 0, bytes);
}
webIS = new ByteArrayInputStream(baos.toByteArray());
}
else if( entry.getName().equals("WEB-INF/jboss-web.xml") )
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while( (bytes = zipIS.read(buffer)) > 0 )
{
baos.write(buffer, 0, bytes);
}
jbossWebIS = new ByteArrayInputStream(baos.toByteArray());
}
}
zipIS.close();
}
XmlFileLoader xmlLoader = new XmlFileLoader();
String warURI = warURL.toExternalForm();
try
{
if( webIS != null )
{
Document webDoc = xmlLoader.getDocument(webIS, warURI+"/WEB-INF/web.xml");
Element web = webDoc.getDocumentElement();
metaData.importXml(web);
}
}
catch(Exception e)
{
throw new DeploymentException("Failed to parse WEB-INF/web.xml", e);
}
try
{
if( jbossWebIS != null )
{
Document jbossWebDoc = xmlLoader.getDocument(jbossWebIS, warURI+"/WEB-INF/jboss-web.xml");
Element jbossWeb = jbossWebDoc.getDocumentElement();
metaData.importXml(jbossWeb);
}
}
catch(Exception e)
{
throw new DeploymentException("Failed to parse WEB-INF/jboss-web.xml", e);
}
}
catch(Exception e)
{
log.warn("Failed to parse descriptors for war("+warURL+")", e);
}
// Build a war root context from the war name if one was not specified
String webContext = ctxPath;
if( webContext == null )
webContext = metaData.getContextRoot();
if( webContext == null )
{
// Build the context from the war name, strip the .war suffix
webContext = warName;
webContext = webContext.replace('\\", '/");
if( webContext.endsWith("/") )
webContext = webContext.substring(0, webContext.length()-1);
int prefix = webContext.lastIndexOf('/");
if( prefix > 0 )
webContext = webContext.substring(prefix+1);
int suffix = webContext.lastIndexOf(".war");
if( suffix > 0 )
webContext = webContext.substring(0, suffix);
// Strip any '< int-value >.' prefix
int index = 0;
for(; index < webContext.length(); index ++)
{
char c = webContext.charAt(index);
if( Character.isDigit(c) == false && c != '." )
break;
}
webContext = webContext.substring(index);
}
// Servlet containers are anal about the web context starting with '/'
if( webContext.length() > 0 && webContext.charAt(0) != '/" )
webContext = "/" + webContext;
// And also the default root context must be an empty string, not '/'
else if( webContext.equals("/") )
webContext = "";
metaData.setContextRoot(webContext);
}
This method creates a context-root string from either the
WEB-INF/jboss-web.xml context-root element is one exists, or the
filename portion of the warURL. It is called if the DeploymentInfo
webContext value is null which indicates a standalone war deployment.
A war name of ROOT.war is handled as a special case of a war that
should be installed as the default web context. |
protected void parseWebAppDescriptors(DeploymentInfo di,
ClassLoader loader,
WebMetaData metaData) throws Exception {
log.debug("AbstractWebContainer.parseWebAppDescriptors, Begin");
InitialContext iniCtx = new InitialContext();
Context envCtx = null;
Thread currentThread = Thread.currentThread();
ClassLoader currentLoader = currentThread.getContextClassLoader();
try
{
// Create a java:comp/env environment unique for the web application
log.debug("Creating ENC using ClassLoader: "+loader);
ClassLoader parent = loader.getParent();
while( parent != null )
{
log.debug(".."+parent);
parent = parent.getParent();
}
currentThread.setContextClassLoader(loader);
metaData.setENCLoader(loader);
envCtx = (Context) iniCtx.lookup("java:comp");
// Add a link to the global transaction manager
envCtx.bind("UserTransaction", new LinkRef("UserTransaction"));
log.debug("Linked java:comp/UserTransaction to JNDI name: UserTransaction");
envCtx = envCtx.createSubcontext("env");
}
finally
{
currentThread.setContextClassLoader(currentLoader);
}
Iterator envEntries = metaData.getEnvironmentEntries();
log.debug("addEnvEntries");
addEnvEntries(envEntries, envCtx);
Iterator resourceEnvRefs = metaData.getResourceEnvReferences();
log.debug("linkResourceEnvRefs");
linkResourceEnvRefs(resourceEnvRefs, envCtx);
Iterator resourceRefs = metaData.getResourceReferences();
log.debug("linkResourceRefs");
linkResourceRefs(resourceRefs, envCtx);
Iterator ejbRefs = metaData.getEjbReferences();
log.debug("linkEjbRefs");
linkEjbRefs(ejbRefs, envCtx, di);
Iterator ejbLocalRefs = metaData.getEjbLocalReferences();
log.debug("linkEjbLocalRefs");
linkEjbLocalRefs(ejbLocalRefs, envCtx, di);
String securityDomain = metaData.getSecurityDomain();
log.debug("linkSecurityDomain");
linkSecurityDomain(securityDomain, envCtx);
log.debug("AbstractWebContainer.parseWebAppDescriptors, End");
}
This method is invoked from within subclass performDeploy() method
implementations when they invoke WebDescriptorParser.parseWebAppDescriptors(). |
abstract protected void performDeploy(WebApplication webApp,
String warUrl,
AbstractWebContainer.WebDescriptorParser webAppParser) throws Exception
This method is called by the deploy() method template and must be overriden by
subclasses to perform the web container specific deployment steps. |
abstract protected void performUndeploy(String warUrl) throws Exception
Called as part of the undeploy() method template to ask the
subclass for perform the web container specific undeployment steps. |
protected void processNestedDeployments(DeploymentInfo di) {
}
WARs do not have nested deployments |
public void setConfig(Element config) {
}
This method is invoked to import an arbitrary XML configuration tree.
Subclasses should override this method if they support such a configuration
capability. This implementation does nothing. |
public void setJava2ClassLoadingCompliance(boolean flag) {
java2ClassLoadingCompliance = flag;
}
Set the flag indicating if the normal Java2 parent first class loading
model should be used over the servlet 2.3 web container first model. |
public void setLenientEjbLink(boolean flag) {
lenientEjbLink = flag;
}
Set the flag indicating if ejb-link errors should be ignored
in favour of trying the jndi-name in jboss-web.xml |
public void setUnpackWars(boolean flag) {
this.unpackWars = flag;
}
Get the flag indicating if war archives should be unpacked. This may
need to be set to false as long extraction paths under deploy can
show up as deployment failures on some platforms. |
public synchronized void start(DeploymentInfo di) throws DeploymentException {
Thread thread = Thread.currentThread();
ClassLoader appClassLoader = thread.getContextClassLoader();
try
{
// Create a classloader for the war to ensure a unique ENC
URL[] empty = {};
URLClassLoader warLoader = URLClassLoader.newInstance(empty, di.ucl);
thread.setContextClassLoader(warLoader);
WebDescriptorParser webAppParser = new DescriptorParser(di);
String webContext = di.webContext;
if( webContext != null )
{
if( webContext.length() > 0 && webContext.charAt(0) != '/" )
webContext = "/" + webContext;
}
// Get the war URL
URL warURL = di.localUrl != null ? di.localUrl : di.url;
if (log.isDebugEnabled())
{
log.debug("webContext: " + webContext);
log.debug("warURL: " + warURL);
log.debug("webAppParser: " + webAppParser);
}
// Parse the web.xml and jboss-web.xml descriptors
WebMetaData metaData = (WebMetaData) di.metaData;
parseMetaData(webContext, warURL, di.shortName, metaData);
WebApplication warInfo = new WebApplication(metaData);
warInfo.setDeploymentInfo(di);
performDeploy(warInfo, warURL.toString(), webAppParser);
deploymentMap.put(warURL.toString(), warInfo);
// Generate an event for the startup
super.start(di);
}
catch(DeploymentException e)
{
throw e;
}
catch(Exception e)
{
throw new DeploymentException("Error during deploy", e);
}
finally
{
thread.setContextClassLoader(appClassLoader);
}
}
A template pattern implementation of the deploy() method. This method
calls the performDeploy() method to
perform the container specific deployment steps and registers the
returned WebApplication in the deployment map. The steps performed are:
ClassLoader appClassLoader = thread.getContextClassLoader();
URLClassLoader warLoader = URLClassLoader.newInstance(empty, appClassLoader);
thread.setContextClassLoader(warLoader);
WebDescriptorParser webAppParser = ...;
WebMetaData metaData = di.metaData;
parseMetaData(ctxPath, warUrl, metaData);
WebApplication warInfo = new WebApplication(metaData);
performDeploy(warInfo, warUrl, webAppParser);
deploymentMap.put(warUrl, warInfo);
thread.setContextClassLoader(appClassLoader);
The subclass performDeploy() implementation needs to invoke
webAppParser.parseWebAppDescriptors(loader, warInfo) to have the JNDI
java:comp/env namespace setup before any web app component can access
this namespace.
Also, an MBean for each servlet deployed should be created and its
JMX ObjectName placed into the DeploymentInfo.mbeans list so that the
JSR77 layer can create the approriate model view. The servlet MBean
needs to provide access to the min, max and total time in milliseconds.
Expose this information via MinServiceTime, MaxServiceTime and TotalServiceTime
attributes to integrate seemlessly with the JSR77 factory layer. |
public synchronized void stop(DeploymentInfo di) throws DeploymentException {
URL warURL = di.localUrl != null ? di.localUrl : di.url;
String warUrl = warURL.toString();
try
{
performUndeploy(warUrl);
// Remove the web application ENC...
deploymentMap.remove(warUrl);
// Generate an event for the stop
super.stop(di);
}
catch(DeploymentException e)
{
throw e;
}
catch(Exception e)
{
throw new DeploymentException("Error during deploy", e);
}
}
A template pattern implementation of the undeploy() method. This method
calls the performUndeploy() method to
perform the container specific undeployment steps and unregisters the
the warUrl from the deployment map. |