DefaultGrailsPluginManager.java

Index Score
org.codehaus.groovy.grails.plugins
Grails

View: Reasons, Metrics, Source Code

These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.

MetricDescription
/* * Copyright 2004-2005 the original author or authors. * * 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.codehaus.groovy.grails.plugins; import grails.util.GrailsUtil; import groovy.lang.*; import groovy.util.ConfigObject; import groovy.util.ConfigSlurper; import groovy.util.XmlSlurper; import groovy.util.slurpersupport.GPathResult; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.control.CompilationFailedException; import org.codehaus.groovy.grails.commons.ConfigurationHolder; import org.codehaus.groovy.grails.commons.GrailsApplication; import org.codehaus.groovy.grails.commons.spring.WebRuntimeSpringConfiguration; import org.codehaus.groovy.grails.plugins.exceptions.PluginException; import org.codehaus.groovy.grails.support.ParentApplicationContextAware; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.support.StaticApplicationContext; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.xml.sax.EntityResolver; import org.xml.sax.SAXException; import org.xml.sax.InputSource; import javax.servlet.ServletContext; import javax.xml.parsers.ParserConfigurationException; import java.io.*; import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.util.*; /** * <p>A class that handles the loading and management of plug-ins in the Grails system. * A plugin a just like a normal Grails application except that it contains a file ending * in *Plugin.groovy in the root of the directory. * * <p>A Plugin class is a Groovy class that has a version and optionally closures * called doWithSpring, doWithContext and doWithWebDescriptor * * <p>The doWithSpring closure uses the BeanBuilder syntax (@see grails.spring.BeanBuilder) to * provide runtime configuration of Grails via Spring * * <p>The doWithContext closure is called after the Spring ApplicationContext is built and accepts * a single argument (the ApplicationContext) * * <p>The doWithWebDescriptor uses mark-up building to provide additional functionality to the web.xml * file * *<p> Example: * <pre> * class ClassEditorGrailsPlugin { * def version = 1.1 * def doWithSpring = { application -> * classEditor(org.springframework.beans.propertyeditors.ClassEditor, application.classLoader) * } * } * </pre> * * <p>A plugin can also define "dependsOn" and "evict" properties that specify what plugins the plugin * depends on and which ones it is incompatable with and should evict * * @author Graeme Rocher * @since 0.4 * */ public class DefaultGrailsPluginManager extends AbstractGrailsPluginManager implements GrailsPluginManager { private static final Log LOG = LogFactory.getLog(DefaultGrailsPluginManager.class); private static final Class[] COMMON_CLASSES = new Class[]{Boolean.class, Byte.class, Character.class, Class.class, Double.class,Float.class, Integer.class, Long.class, Number.class, Short.class, String.class, BigInteger.class, BigDecimal.class, URL.class, URI.class}; private final GrailsPluginChangeChecker pluginChangeScanner = new GrailsPluginChangeChecker(this); private static final int SCAN_INTERVAL = 1000; //in ms private List delayedLoadPlugins = new LinkedList(); private ApplicationContext parentCtx; private PathMatchingResourcePatternResolver resolver; private Map delayedEvictions = new HashMap(); private ServletContext servletContext; private Map pluginToObserverMap = new HashMap(); private long configLastModified; private PluginFilter pluginFilter; private static final String GRAILS_PLUGIN_SUFFIX = "GrailsPlugin"; public DefaultGrailsPluginManager(String resourcePath, GrailsApplication application) throws IOException { super(application); if(application == null) throw new IllegalArgumentException("Argument [application] cannot be null!"); resolver = new PathMatchingResourcePatternResolver(); try { this.pluginResources = resolver.getResources(resourcePath); } catch(IOException ioe) { LOG.debug("Unable to load plugins for resource path " + resourcePath, ioe); } //this.corePlugins = new PathMatchingResourcePatternResolver().getResources("classpath:org/codehaus/groovy/grails/**/plugins/**GrailsPlugin.groovy"); this.application = application; setPluginFilter(); startPluginChangeScanner(); } public DefaultGrailsPluginManager(String[] pluginResources, GrailsApplication application) { super(application); resolver = new PathMatchingResourcePatternResolver(); List resourceList = new ArrayList(); for (int i = 0; i < pluginResources.length; i++) { String resourcePath = pluginResources[i]; try { Resource[] resources = resolver.getResources(resourcePath); for (int j = 0; j < resources.length; j++) { Resource resource = resources[j]; resourceList.add(resource); } } catch(IOException ioe) { LOG.debug("Unable to load plugins for resource path " + resourcePath, ioe); } } this.pluginResources = (Resource[])resourceList.toArray(new Resource[resourceList.size()]); this.application = application; setPluginFilter(); startPluginChangeScanner(); } public DefaultGrailsPluginManager(Class[] plugins, GrailsApplication application) throws IOException { super(application); this.pluginClasses = plugins; resolver = new PathMatchingResourcePatternResolver(); //this.corePlugins = new PathMatchingResourcePatternResolver().getResources("classpath:org/codehaus/groovy/grails/**/plugins/**GrailsPlugin.groovy"); this.application = application; setPluginFilter(); startPluginChangeScanner(); } public DefaultGrailsPluginManager(Resource[] pluginFiles, GrailsApplication application) { super(application); resolver = new PathMatchingResourcePatternResolver(); this.pluginResources = pluginFiles; this.application = application; setPluginFilter(); startPluginChangeScanner(); } private void setPluginFilter() { this.pluginFilter = new PluginFilterRetriever().getPluginFilter(this.application.getConfig().toProperties()); } private void startPluginChangeScanner(){ boolean inTestSuite = System.getProperty("grails.cli.testing") != null; if(!application.isWarDeployed() && GrailsUtil.isDevelopmentEnv() && !inTestSuite) { this.pluginChangeScanner.start(); LOG.info("Started to scan for plugin changes in every " + SCAN_INTERVAL + "ms."); } } public void refreshPlugin(String name) { if(hasGrailsPlugin(name)) { GrailsPlugin plugin = getGrailsPlugin(name); plugin.refresh(); } } public Collection getPluginObservers(GrailsPlugin plugin) { if(plugin == null) throw new IllegalArgumentException("Argument [plugin] cannot be null"); Collection c = (Collection)this.pluginToObserverMap.get(plugin.getName()); // Add any wildcard observers. Collection wildcardObservers = (Collection)this.pluginToObserverMap.get("*"); if(wildcardObservers != null) { if(c != null) { c.addAll(wildcardObservers); } else { c = wildcardObservers; } } if(c != null) { // Make sure this plugin is not observing itself! c.remove(plugin); return c; } return Collections.EMPTY_SET; } public void informObservers(String pluginName, Map event) { GrailsPlugin plugin = getGrailsPlugin(pluginName); if(plugin != null) { Collection observers = getPluginObservers(plugin); for (Iterator i = observers.iterator(); i.hasNext();) { GrailsPlugin observingPlugin = (GrailsPlugin) i.next(); observingPlugin.notifyOfEvent(event); } } } /* (non-Javadoc) * @see org.codehaus.groovy.grails.plugins.GrailsPluginManager#loadPlugins() */ public void loadPlugins() throws PluginException { if(!this.initialised) { GroovyClassLoader gcl = application.getClassLoader(); attemptLoadPlugins(gcl); if(!delayedLoadPlugins.isEmpty()) { loadDelayedPlugins(); } if(!delayedEvictions.isEmpty()) { processDelayedEvictions(); } initializePlugins(); initialised = true; } } private void attemptLoadPlugins(GroovyClassLoader gcl) { // retrieve load core plugins first List grailsCorePlugins = findCorePlugins(); List grailsUserPlugins = findUserPlugins(gcl); List allPlugins = new ArrayList(grailsCorePlugins); allPlugins.addAll(grailsUserPlugins); //filtering applies to user as well as core plugins List filteredPlugins = getPluginFilter().filterPluginList(allPlugins); //make sure core plugins are loaded first List orderedCorePlugins = new ArrayList(); List orderedUserPlugins = new ArrayList(); for (Iterator iter = filteredPlugins.iterator(); iter.hasNext();) { GrailsPlugin plugin = (GrailsPlugin) iter.next(); if (grailsCorePlugins.contains(plugin)) { orderedCorePlugins.add(plugin); } else { orderedUserPlugins.add(plugin); } } List orderedPlugins = new ArrayList(); orderedPlugins.addAll(orderedCorePlugins); orderedPlugins.addAll(orderedUserPlugins); for (Iterator iter = orderedPlugins.iterator(); iter.hasNext();) { GrailsPlugin plugin = (GrailsPlugin) iter.next(); attemptPluginLoad(plugin); } } private List findCorePlugins() { CorePluginFinder finder = new CorePluginFinder(application); Set classes = finder.getPluginClasses(); Iterator classesIterator = classes.iterator(); List grailsCorePlugins = new ArrayList(); while (classesIterator.hasNext()) { Class pluginClass = (Class) classesIterator.next(); if(pluginClass != null && !Modifier.isAbstract(pluginClass.getModifiers()) && pluginClass != DefaultGrailsPlugin.class) { GrailsPlugin plugin = new DefaultGrailsPlugin(pluginClass, application); plugin.setApplicationContext(applicationContext); grailsCorePlugins.add(plugin); } } return grailsCorePlugins; } private List findUserPlugins(GroovyClassLoader gcl) { List grailsUserPlugins = new ArrayList(); LOG.info("Attempting to load ["+pluginResources.length+"] user defined plugins"); for (int i = 0; i < pluginResources.length; i++) { Resource r = pluginResources[i]; Class pluginClass = loadPluginClass(gcl, r); if(isGrailsPlugin(pluginClass)) { GrailsPlugin plugin = new DefaultGrailsPlugin(pluginClass, r, application); //attemptPluginLoad(plugin); grailsUserPlugins.add(plugin); } else { LOG.warn("Class ["+pluginClass+"] not loaded as plug-in. Grails plug-ins must end with the convention 'GrailsPlugin'!"); } } for (int i = 0; i < pluginClasses.length; i++) { Class pluginClass = pluginClasses[i]; if(isGrailsPlugin(pluginClass)) { GrailsPlugin plugin = new DefaultGrailsPlugin(pluginClass, application); //attemptPluginLoad(plugin); grailsUserPlugins.add(plugin); } else { LOG.warn("Class ["+pluginClass+"] not loaded as plug-in. Grails plug-ins must end with the convention 'GrailsPlugin'!"); } } return grailsUserPlugins; } private boolean isGrailsPlugin(Class pluginClass) { return pluginClass != null && pluginClass.getName().endsWith(GRAILS_PLUGIN_SUFFIX); } private void processDelayedEvictions() { for (Iterator i = delayedEvictions.keySet().iterator(); i.hasNext();) { GrailsPlugin plugin = (GrailsPlugin) i.next(); String[] pluginToEvict = (String[])delayedEvictions.get(plugin); for (int j = 0; j < pluginToEvict.length; j++) { String pluginName = pluginToEvict[j]; evictPlugin(plugin, pluginName); } } } private void initializePlugins() { for (Iterator i = plugins.values().iterator(); i.hasNext();) { Object plugin = i.next(); if(plugin instanceof ApplicationContextAware) { ((ApplicationContextAware)plugin).setApplicationContext(applicationContext); } } } /** * This method will search the classpath for .class files inside the org.codehaus.groovy.grails package * which are the core plugins. The ones found will be loaded automatically * */ /** * This method will attempt to load that plug-ins not loaded in the first pass * */ private void loadDelayedPlugins() { while(!delayedLoadPlugins.isEmpty()) { GrailsPlugin plugin = (GrailsPlugin)delayedLoadPlugins.remove(0); if(areDependenciesResolved(plugin)) { if(!hasValidPluginsToLoadBefore(plugin)) { registerPlugin(plugin); } else { delayedLoadPlugins.add(plugin); } } else { // ok, it still hasn't resolved the dependency after the initial // load of all plugins. All hope is not lost, however, so lets first // look inside the remaining delayed loads before giving up boolean foundInDelayed = false; for (Iterator i = delayedLoadPlugins.iterator(); i.hasNext();) { GrailsPlugin remainingPlugin = (GrailsPlugin) i.next(); if(isDependentOn(plugin, remainingPlugin)) { foundInDelayed = true; break; } } if(foundInDelayed) delayedLoadPlugins.add(plugin); else { failedPlugins.put(plugin.getName(),plugin); LOG.warn("WARNING: Plugin ["+plugin.getName()+"] cannot be loaded because its dependencies ["+ArrayUtils.toString(plugin.getDependencyNames())+"] cannot be resolved"); } } } } private boolean hasValidPluginsToLoadBefore(GrailsPlugin plugin) { String[] loadAfterNames = plugin.getLoadAfterNames(); for (Iterator i = this.delayedLoadPlugins.iterator(); i.hasNext();) { GrailsPlugin other = (GrailsPlugin) i.next(); for (int j = 0; j < loadAfterNames.length; j++) { String name = loadAfterNames[j]; if(other.getName().equals(name)) { return hasDelayedDependencies(other) || areDependenciesResolved(other); } } } return false; } private boolean hasDelayedDependencies(GrailsPlugin other) { String[] dependencyNames = other.getDependencyNames(); for (int i = 0; i < dependencyNames.length; i++) { String dependencyName = dependencyNames[i]; for (Iterator j = delayedLoadPlugins.iterator(); j.hasNext();) { GrailsPlugin grailsPlugin = (GrailsPlugin) j.next(); if(grailsPlugin.getName().equals(dependencyName)) return true; } } return false; } /** * Checks whether the first plugin is dependant on the second plugin * @param plugin The plugin to check * @param dependancy The plugin which the first argument may be dependant on * @return True if it is */ private boolean isDependentOn(GrailsPlugin plugin, GrailsPlugin dependancy) { String[] dependencies = plugin.getDependencyNames(); for (int i = 0; i < dependencies.length; i++) { String name = dependencies[i]; String requiredVersion = plugin.getDependentVersion(name); if(name.equals(dependancy.getName()) && GrailsPluginUtils.isValidVersion(dependancy.getVersion(), requiredVersion)) return true; } return false; } private boolean areDependenciesResolved(GrailsPlugin plugin) { String[] dependencies = plugin.getDependencyNames(); if(dependencies.length > 0) { for (int i = 0; i < dependencies.length; i++) { String name = dependencies[i]; String version = plugin.getDependentVersion(name); if(!hasGrailsPlugin(name, version)) { return false; } } } return true; } /** * Returns true if there are no plugins left that should, if possible, be loaded before this plugin * * @param plugin The plugin * @return True if there are */ private boolean areNoneToLoadBefore(GrailsPlugin plugin) { String[] loadAfterNames = plugin.getLoadAfterNames(); if(loadAfterNames.length > 0) { for (int i = 0; i < loadAfterNames.length; i++) { String name = loadAfterNames[i]; if(getGrailsPlugin(name) == null) return false; } } return true; } private Class loadPluginClass(GroovyClassLoader gcl, Resource r) { Class pluginClass; try { pluginClass = gcl.parseClass(r.getInputStream()); } catch (CompilationFailedException e) { throw new PluginException("Error compiling plugin ["+r.getFilename()+"] " + e.getMessage(), e); } catch (IOException e) { throw new PluginException("Error reading plugin ["+r.getFilename()+"] " + e.getMessage(), e); } return pluginClass; } /** * This method attempts to load a plugin based on its dependencies. If a plugin's * dependencies cannot be resolved it will add it to the list of dependencies to * be resolved later * * @param plugin The plugin */ private void attemptPluginLoad(GrailsPlugin plugin) { if(areDependenciesResolved(plugin) && areNoneToLoadBefore(plugin)) { registerPlugin(plugin); } else { delayedLoadPlugins.add(plugin); } } private void registerPlugin(GrailsPlugin plugin) { if(plugin.isEnabled()) { if(LOG.isInfoEnabled()) { LOG.info("Grails plug-in ["+plugin.getName()+"] with version ["+plugin.getVersion()+"] loaded successfully"); } if(plugin instanceof ParentApplicationContextAware) { ((ParentApplicationContextAware)plugin).setParentApplicationContext(parentCtx); } plugin.setManager(this); String[] evictionNames = plugin.getEvictionNames(); if(evictionNames.length > 0) delayedEvictions.put(plugin, evictionNames); String[] observedPlugins = plugin.getObservedPluginNames(); for (int i = 0; i < observedPlugins.length; i++) { String observedPlugin = observedPlugins[i]; Set observers = (Set)pluginToObserverMap.get(observedPlugin); if(observers == null) { observers = new HashSet(); pluginToObserverMap.put(observedPlugin, observers); } observers.add(plugin); } pluginList.add(plugin); plugins.put(plugin.getName(), plugin); } else { if(LOG.isInfoEnabled()) { LOG.info("Grails plugin " + plugin + " is disabled and was not loaded"); } } } protected void evictPlugin(GrailsPlugin evictor, String evicteeName) { GrailsPlugin pluginToEvict = (GrailsPlugin)plugins.get(evicteeName); if(pluginToEvict!=null) { pluginList.remove(pluginToEvict); plugins.remove(pluginToEvict.getName()); if(LOG.isInfoEnabled()) { LOG.info("Grails plug-in "+pluginToEvict+" was evicted by " + evictor); } } } private boolean hasGrailsPlugin(String name, String version) { return getGrailsPlugin(name, version) != null; } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; for (Iterator i = pluginList.iterator(); i.hasNext();) { GrailsPlugin plugin = (GrailsPlugin) i.next(); plugin.setApplicationContext(applicationContext); } } public void setParentApplicationContext(ApplicationContext parent) { this.parentCtx = parent; } public void checkForChanges() { checkForConfigChanges(); for (Iterator i = pluginList.iterator(); i.hasNext();) { GrailsPlugin plugin = (GrailsPlugin) i.next(); if(plugin.checkForChanges()) { LOG.info("Plugin "+plugin+" changed, re-registering beans..."); reloadPlugin(plugin); } } } private void checkForConfigChanges() { ConfigObject config = application.getConfig(); URL configURL = config.getConfigFile(); if(configURL != null) { URLConnection connection; try { connection = configURL.openConnection(); } catch (IOException e) { LOG.error("I/O error obtaining URL connection for configuration ["+configURL+"]: " + e.getMessage(),e); return; } long lastModified = connection.getLastModified(); if(configLastModified == 0) { configLastModified = lastModified; } else { if(configLastModified<lastModified) { LOG.info("Configuration ["+configURL+"] changed, reloading changes.."); ConfigSlurper slurper = new ConfigSlurper(GrailsUtil.getEnvironment()); try { config = slurper.parse(configURL); ConfigurationHolder.setConfig(config); configLastModified = lastModified; informPluginsOfConfigChange(); } catch (GroovyRuntimeException gre) { LOG.error("Unable to reload configuration. Please correct problem and try again: " + gre.getMessage(),gre); } } } } } private void informPluginsOfConfigChange() { LOG.info("Informing plug-ins of configuration change.."); for (Iterator i = pluginList.iterator(); i.hasNext();) { GrailsPlugin plugin = (GrailsPlugin) i.next(); plugin.notifyOfEvent(GrailsPlugin.EVENT_ON_CONFIG_CHANGE, application.getConfig()); } } private void reloadPlugin(GrailsPlugin plugin) { plugin.doArtefactConfiguration(); WebRuntimeSpringConfiguration springConfig = new WebRuntimeSpringConfiguration(this.parentCtx); springConfig.setServletContext(getServletContext()); this.doRuntimeConfiguration(plugin.getName(), springConfig); springConfig.registerBeansWithContext((StaticApplicationContext)this.applicationContext); plugin.doWithApplicationContext(this.applicationContext); plugin.doWithDynamicMethods(this.applicationContext); } public void doWebDescriptor(Resource descriptor, Writer target) { try { doWebDescriptor( descriptor.getInputStream(), target); } catch (IOException e) { throw new PluginException("Unable to read web.xml ["+descriptor+"]: " + e.getMessage(),e); } } private void doWebDescriptor(InputStream inputStream, Writer target) { checkInitialised(); try { XmlSlurper slurper = new XmlSlurper(); slurper.setEntityResolver(new EntityResolver() { public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { if (systemId != null && systemId.equals("http://java.sun.com/dtd/web-app_2_3.dtd")) { return new InputSource(new StringReader(getWeb23DTD())); } return null; } }); GPathResult result = slurper.parse(inputStream); for (Iterator i = pluginList.iterator(); i.hasNext();) { GrailsPlugin plugin = (GrailsPlugin) i.next(); plugin.doWithWebDescriptor(result); } Binding b = new Binding(); b.setVariable("node", result); // this code takes the XML parsed by XmlSlurper and writes it out using StreamingMarkupBuilder // don't ask me how it works, refer to John Wilson ;-) Writable w = (Writable)new GroovyShell(b) .evaluate("new groovy.xml.StreamingMarkupBuilder().bind { mkp.declareNamespace(\"\": \"http://java.sun.com/xml/ns/j2ee\"); mkp.yield node}"); w.writeTo(target); } catch (ParserConfigurationException e) { throw new PluginException("Unable to configure web.xml due to parser configuration problem: " + e.getMessage(),e); } catch (SAXException e) { throw new PluginException("XML parsing error configuring web.xml: " + e.getMessage(),e); } catch (IOException e) { throw new PluginException("Unable to read web.xml" + e.getMessage(),e); } } public void doWebDescriptor(File descriptor, Writer target) { try { doWebDescriptor(new FileInputStream(descriptor), target); } catch (FileNotFoundException e) { throw new PluginException("Unable to read web.xml ["+descriptor+"]: " + e.getMessage(),e); } } public void setApplication(GrailsApplication application) { if(application == null) throw new IllegalArgumentException("Argument [application] cannot be null"); this.application = application; for (Iterator i = pluginList.iterator(); i.hasNext();) { GrailsPlugin plugin = (GrailsPlugin) i.next(); plugin.setApplication(application); } } public void doDynamicMethods() { checkInitialised(); // remove common meta classes just to be sure MetaClassRegistry registry = GroovySystem.getMetaClassRegistry(); for (int i = 0; i < COMMON_CLASSES.length; i++) { Class commonClass = COMMON_CLASSES[i]; registry.removeMetaClass(commonClass); } for (Iterator i = pluginList.iterator(); i.hasNext();) { GrailsPlugin plugin = (GrailsPlugin) i.next(); plugin.doWithDynamicMethods(applicationContext); } } public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; } public ServletContext getServletContext() { return servletContext; } void setPluginFilter(PluginFilter pluginFilter) { this.pluginFilter = pluginFilter; } private PluginFilter getPluginFilter() { if (pluginFilter == null) { pluginFilter = new IdentityPluginFilter(); } return pluginFilter; } List getPluginList() { return Collections.unmodifiableList(pluginList); } public static String getWeb23DTD(){ return "<!--\n" + "DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.\n" + "\n" + "Copyright 2000-2007 Sun Microsystems, Inc. All rights reserved.\n" + "\n" + "The contents of this file are subject to the terms of either the GNU\n" + "General Public License Version 2 only (\"GPL\") or the Common Development\n" + "and Distribution License(\"CDDL\") (collectively, the \"License\"). You\n" + "may not use this file except in compliance with the License. You can obtain\n" + "a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html\n" + "or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific\n" + "language governing permissions and limitations under the License.\n" + "\n" + "When distributing the software, include this License Header Notice in each\n" + "file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.\n" + "Sun designates this particular file as subject to the \"Classpath\" exception\n" + "as provided by Sun in the GPL Version 2 section of the License file that\n" + "accompanied this code. If applicable, add the following below the License\n" + "Header, with the fields enclosed by brackets [] replaced by your own\n" + "identifying information: \"Portions Copyrighted [year]\n" + "[name of copyright owner]\"\n" + "\n" + "Contributor(s):\n" + "\n" + "If you wish your version of this file to be governed by only the CDDL or\n" + "only the GPL Version 2, indicate your decision by adding \"[Contributor]\n" + "elects to include this software in this distribution under the [CDDL or GPL\n" + "Version 2] license.\" If you don't indicate a single choice of license, a\n" + "recipient has the option to distribute your version of this file under\n" + "either the CDDL, the GPL Version 2 or to extend the choice of license to\n" + "its licensees as provided above. However, if you add GPL Version 2 code\n" + "and therefore, elected the GPL Version 2 license, then the option applies\n" + "only if the new code is made subject to such option by the copyright\n" + "holder.\n" + "-->\n" + "\n" + "<!--\n" + "This is the XML DTD for the Servlet 2.3 deployment descriptor.\n" + "All Servlet 2.3 deployment descriptors must include a DOCTYPE\n" + "of the following form:\n" + "\n" + " <!DOCTYPE web-app PUBLIC\n" + "\t\"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN\"\n" + "\t\"http://java.sun.com/dtd/web-app_2_3.dtd\">\n" + "\n" + "-->\n" + "\n" + "<!--\n" + "The following conventions apply to all J2EE deployment descriptor\n" + "elements unless indicated otherwise.\n" + "\n" + "- In elements that contain PCDATA, leading and trailing whitespace\n" + " in the data may be ignored.\n" + "\n" + "- In elements whose value is an \"enumerated type\", the value is\n" + " case sensitive.\n" + "\n" + "- In elements that specify a pathname to a file within the same\n" + " JAR file, relative filenames (i.e., those not starting with \"/\")\n" + " are considered relative to the root of the JAR file's namespace.\n" + " Absolute filenames (i.e., those starting with \"/\") also specify\n" + " names in the root of the JAR file's namespace. In general, relative\n" + " names are preferred. The exception is .war files where absolute\n" + " names are preferred for consistency with the servlet API.\n" + "-->\n" + "\n" + "\n" + "<!--\n" + "The web-app element is the root of the deployment descriptor for\n" + "a web application.\n" + "-->\n" + "<!ELEMENT web-app (icon?, display-name?, description?, distributable?,\n" + "context-param*, filter*, filter-mapping*, listener*, servlet*,\n" + "servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?,\n" + "error-page*, taglib*, resource-env-ref*, resource-ref*, security-constraint*,\n" + "login-config?, security-role*, env-entry*, ejb-ref*, ejb-local-ref*)>\n" + "\n" + "<!--\n" + "The auth-constraint element indicates the user roles that should\n" + "be permitted access to this resource collection. The role-name\n" + "used here must either correspond to the role-name of one of the\n" + "security-role elements defined for this web application, or be\n" + "the specially reserved role-name \"*\" that is a compact syntax for\n" + "indicating all roles in the web application. If both \"*\" and\n" + "rolenames appear, the container interprets this as all roles.\n" + "If no roles are defined, no user is allowed access to the portion of\n" + "the web application described by the containing security-constraint.\n" + "The container matches role names case sensitively when determining\n" + "access.\n" + "\n" + "\n" + "Used in: security-constraint\n" + "-->\n" + "<!ELEMENT auth-constraint (description?, role-name*)>\n" + "\n" + "<!--\n" + "The auth-method element is used to configure the authentication\n" + "mechanism for the web application. As a prerequisite to gaining access to any web resources which are protected by an authorization\n" + "constraint, a user must have authenticated using the configured\n" + "mechanism. Legal values for this element are \"BASIC\", \"DIGEST\",\n" + "\"FORM\", or \"CLIENT-CERT\".\n" + "\n" + "Used in: login-config\n" + "-->\n" + "<!ELEMENT auth-method (#PCDATA)>\n" + "\n" + "<!--\n" + "The context-param element contains the declaration of a web\n" + "application's servlet context initialization parameters.\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT context-param (param-name, param-value, description?)>\n" + "\n" + "<!--\n" + "The description element is used to provide text describing the parent\n" + "element. The description element should include any information that\n" + "the web application war file producer wants to provide to the consumer of\n" + "the web application war file (i.e., to the Deployer). Typically, the tools\n" + "used by the web application war file consumer will display the description\n" + "when processing the parent element that contains the description.\n" + "\n" + "Used in: auth-constraint, context-param, ejb-local-ref, ejb-ref,\n" + "env-entry, filter, init-param, resource-env-ref, resource-ref, run-as,\n" + "security-role, security-role-ref, servlet, user-data-constraint,\n" + "web-app, web-resource-collection\n" + "-->\n" + "<!ELEMENT description (#PCDATA)>\n" + "\n" + "<!--\n" + "The display-name element contains a short name that is intended to be\n" + "displayed by tools. The display name need not be unique.\n" + "\n" + "Used in: filter, security-constraint, servlet, web-app\n" + "\n" + "Example:\n" + "\n" + "<display-name>Employee Self Service</display-name>\n" + "-->\n" + "<!ELEMENT display-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The distributable element, by its presence in a web application\n" + "deployment descriptor, indicates that this web application is\n" + "programmed appropriately to be deployed into a distributed servlet\n" + "container\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT distributable EMPTY>\n" + "\n" + "<!--\n" + "The ejb-link element is used in the ejb-ref or ejb-local-ref\n" + "elements to specify that an EJB reference is linked to an\n" + "enterprise bean.\n" + "\n" + "The name in the ejb-link element is composed of a\n" + "path name specifying the ejb-jar containing the referenced enterprise\n" + "bean with the ejb-name of the target bean appended and separated from\n" + "the path name by \"#\". The path name is relative to the war file\n" + "containing the web application that is referencing the enterprise bean.\n" + "This allows multiple enterprise beans with the same ejb-name to be\n" + "uniquely identified.\n" + "\n" + "Used in: ejb-local-ref, ejb-ref\n" + "\n" + "Examples:\n" + "\n" + "\t<ejb-link>EmployeeRecord</ejb-link>\n" + "\n" + "\t<ejb-link>../products/product.jar#ProductEJB</ejb-link>\n" + "\n" + "-->\n" + "<!ELEMENT ejb-link (#PCDATA)>\n" + "\n" + "<!--\n" + "The ejb-local-ref element is used for the declaration of a reference to\n" + "an enterprise bean's local home. The declaration consists of:\n" + "\n" + "\t- an optional description\n" + "\t- the EJB reference name used in the code of the web application\n" + "\t that's referencing the enterprise bean\n" + "\t- the expected type of the referenced enterprise bean\n" + "\t- the expected local home and local interfaces of the referenced\n" + "\t enterprise bean\n" + "\t- optional ejb-link information, used to specify the referenced\n" + "\t enterprise bean\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT ejb-local-ref (description?, ejb-ref-name, ejb-ref-type,\n" + "\t\tlocal-home, local, ejb-link?)>\n" + "\n" + "<!--\n" + "The ejb-ref element is used for the declaration of a reference to\n" + "an enterprise bean's home. The declaration consists of:\n" + "\n" + "\t- an optional description\n" + "\t- the EJB reference name used in the code of\n" + "\t the web application that's referencing the enterprise bean\n" + "\t- the expected type of the referenced enterprise bean\n" + "\t- the expected home and remote interfaces of the referenced\n" + "\t enterprise bean\n" + "\t- optional ejb-link information, used to specify the referenced\n" + "\t enterprise bean\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT ejb-ref (description?, ejb-ref-name, ejb-ref-type,\n" + "\t\thome, remote, ejb-link?)>\n" + "\n" + "<!--\n" + "The ejb-ref-name element contains the name of an EJB reference. The\n" + "EJB reference is an entry in the web application's environment and is\n" + "relative to the java:comp/env context. The name must be unique\n" + "within the web application.\n" + "\n" + "It is recommended that name is prefixed with \"ejb/\".\n" + "\n" + "Used in: ejb-local-ref, ejb-ref\n" + "\n" + "Example:\n" + "\n" + "<ejb-ref-name>ejb/Payroll</ejb-ref-name>\n" + "-->\n" + "<!ELEMENT ejb-ref-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The ejb-ref-type element contains the expected type of the\n" + "referenced enterprise bean.\n" + "\n" + "The ejb-ref-type element must be one of the following:\n" + "\n" + "\t<ejb-ref-type>Entity</ejb-ref-type>\n" + "\t<ejb-ref-type>Session</ejb-ref-type>\n" + "\n" + "Used in: ejb-local-ref, ejb-ref\n" + "-->\n" + "<!ELEMENT ejb-ref-type (#PCDATA)>\n" + "\n" + "<!--\n" + "The env-entry element contains the declaration of a web application's\n" + "environment entry. The declaration consists of an optional\n" + "description, the name of the environment entry, and an optional\n" + "value. If a value is not specified, one must be supplied\n" + "during deployment.\n" + "-->\n" + "<!ELEMENT env-entry (description?, env-entry-name, env-entry-value?,\n" + "env-entry-type)>\n" + "\n" + "<!--\n" + "The env-entry-name element contains the name of a web applications's\n" + "environment entry. The name is a JNDI name relative to the\n" + "java:comp/env context. The name must be unique within a web application.\n" + "\n" + "Example:\n" + "\n" + "<env-entry-name>minAmount</env-entry-name>\n" + "\n" + "Used in: env-entry\n" + "-->\n" + "<!ELEMENT env-entry-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The env-entry-type element contains the fully-qualified Java type of\n" + "the environment entry value that is expected by the web application's\n" + "code.\n" + "\n" + "The following are the legal values of env-entry-type:\n" + "\n" + "\tjava.lang.Boolean\n" + "\tjava.lang.Byte\n" + "\tjava.lang.Character\n" + "\tjava.lang.String\n" + "\tjava.lang.Short\n" + "\tjava.lang.Integer\n" + "\tjava.lang.Long\n" + "\tjava.lang.Float\n" + "\tjava.lang.Double\n" + "\n" + "Used in: env-entry\n" + "-->\n" + "<!ELEMENT env-entry-type (#PCDATA)>\n" + "\n" + "<!--\n" + "The env-entry-value element contains the value of a web application's\n" + "environment entry. The value must be a String that is valid for the\n" + "constructor of the specified type that takes a single String\n" + "parameter, or for java.lang.Character, a single character.\n" + "\n" + "Example:\n" + "\n" + "<env-entry-value>100.00</env-entry-value>\n" + "\n" + "Used in: env-entry\n" + "-->\n" + "<!ELEMENT env-entry-value (#PCDATA)>\n" + "\n" + "<!--\n" + "The error-code contains an HTTP error code, ex: 404\n" + "\n" + "Used in: error-page\n" + "-->\n" + "<!ELEMENT error-code (#PCDATA)>\n" + "\n" + "<!--\n" + "The error-page element contains a mapping between an error code\n" + "or exception type to the path of a resource in the web application\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT error-page ((error-code | exception-type), location)>\n" + "\n" + "<!--\n" + "The exception type contains a fully qualified class name of a\n" + "Java exception type.\n" + "\n" + "Used in: error-page\n" + "-->\n" + "<!ELEMENT exception-type (#PCDATA)>\n" + "\n" + "<!--\n" + "The extension element contains a string describing an\n" + "extension. example: \"txt\"\n" + "\n" + "Used in: mime-mapping\n" + "-->\n" + "<!ELEMENT extension (#PCDATA)>\n" + "\n" + "<!--\n" + "Declares a filter in the web application. The filter is mapped to\n" + "either a servlet or a URL pattern in the filter-mapping element, using\n" + "the filter-name value to reference. Filters can access the\n" + "initialization parameters declared in the deployment descriptor at\n" + "runtime via the FilterConfig interface.\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT filter (icon?, filter-name, display-name?, description?,\n" + "filter-class, init-param*)>\n" + "\n" + "<!--\n" + "The fully qualified classname of the filter.\n" + "\n" + "Used in: filter\n" + "-->\n" + "<!ELEMENT filter-class (#PCDATA)>\n" + "\n" + "<!--\n" + "Declaration of the filter mappings in this web application. The\n" + "container uses the filter-mapping declarations to decide which filters\n" + "to apply to a request, and in what order. The container matches the\n" + "request URI to a Servlet in the normal way. To determine which filters\n" + "to apply it matches filter-mapping declarations either on servlet-name,\n" + "or on url-pattern for each filter-mapping element, depending on which\n" + "style is used. The order in which filters are invoked is the order in\n" + "which filter-mapping declarations that match a request URI for a\n" + "servlet appear in the list of filter-mapping elements.The filter-name\n" + "value must be the value of the <filter-name> sub-elements of one of the\n" + "<filter> declarations in the deployment descriptor.\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT filter-mapping (filter-name, (url-pattern | servlet-name))>\n" + "\n" + "<!--\n" + "The logical name of the filter. This name is used to map the filter.\n" + "Each filter name is unique within the web application.\n" + "\n" + "Used in: filter, filter-mapping\n" + "-->\n" + "<!ELEMENT filter-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The form-error-page element defines the location in the web app\n" + "where the error page that is displayed when login is not successful\n" + "can be found. The path begins with a leading / and is interpreted\n" + "relative to the root of the WAR.\n" + "\n" + "Used in: form-login-config\n" + "-->\n" + "<!ELEMENT form-error-page (#PCDATA)>\n" + "\n" + "<!--\n" + "The form-login-config element specifies the login and error pages\n" + "that should be used in form based login. If form based authentication\n" + "is not used, these elements are ignored.\n" + "\n" + "Used in: login-config\n" + "-->\n" + "<!ELEMENT form-login-config (form-login-page, form-error-page)>\n" + "\n" + "<!--\n" + "The form-login-page element defines the location in the web app\n" + "where the page that can be used for login can be found. The path\n" + "begins with a leading / and is interpreted relative to the root of the WAR.\n" + "\n" + "Used in: form-login-config\n" + "-->\n" + "<!ELEMENT form-login-page (#PCDATA)>\n" + "\n" + "<!--\n" + "The home element contains the fully-qualified name of the enterprise\n" + "bean's home interface.\n" + "\n" + "Used in: ejb-ref\n" + "\n" + "Example:\n" + "\n" + "<home>com.aardvark.payroll.PayrollHome</home>\n" + "-->\n" + "<!ELEMENT home (#PCDATA)>\n" + "\n" + "<!--\n" + "The http-method contains an HTTP method (GET | POST |...).\n" + "\n" + "Used in: web-resource-collection\n" + "-->\n" + "<!ELEMENT http-method (#PCDATA)>\n" + "\n" + "<!--\n" + "The icon element contains small-icon and large-icon elements that\n" + "specify the file names for small and a large GIF or JPEG icon images\n" + "used to represent the parent element in a GUI tool.\n" + "\n" + "Used in: filter, servlet, web-app\n" + "-->\n" + "<!ELEMENT icon (small-icon?, large-icon?)>\n" + "\n" + "<!--\n" + "The init-param element contains a name/value pair as an\n" + "initialization param of the servlet\n" + "\n" + "Used in: filter, servlet\n" + "-->\n" + "<!ELEMENT init-param (param-name, param-value, description?)>\n" + "\n" + "<!--\n" + "The jsp-file element contains the full path to a JSP file within\n" + "the web application beginning with a `/'.\n" + "\n" + "Used in: servlet\n" + "-->\n" + "<!ELEMENT jsp-file (#PCDATA)>\n" + "\n" + "<!--\n" + "The large-icon element contains the name of a file\n" + "containing a large (32 x 32) icon image. The file\n" + "name is a relative path within the web application's\n" + "war file.\n" + "\n" + "The image may be either in the JPEG or GIF format.\n" + "The icon can be used by tools.\n" + "\n" + "Used in: icon\n" + "\n" + "Example:\n" + "\n" + "<large-icon>employee-service-icon32x32.jpg</large-icon>\n" + "-->\n" + "<!ELEMENT large-icon (#PCDATA)>\n" + "\n" + "<!--\n" + "The listener element indicates the deployment properties for a web\n" + "application listener bean.\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT listener (listener-class)>\n" + "\n" + "<!--\n" + "The listener-class element declares a class in the application must be\n" + "registered as a web application listener bean. The value is the fully qualified classname of the listener class.\n" + "\n" + "\n" + "Used in: listener\n" + "-->\n" + "<!ELEMENT listener-class (#PCDATA)>\n" + "\n" + "<!--\n" + "The load-on-startup element indicates that this servlet should be\n" + "loaded (instantiated and have its init() called) on the startup\n" + "of the web application. The optional contents of\n" + "these element must be an integer indicating the order in which\n" + "the servlet should be loaded. If the value is a negative integer,\n" + "or the element is not present, the container is free to load the\n" + "servlet whenever it chooses. If the value is a positive integer\n" + "or 0, the container must load and initialize the servlet as the\n" + "application is deployed. The container must guarantee that\n" + "servlets marked with lower integers are loaded before servlets\n" + "marked with higher integers. The container may choose the order\n" + "of loading of servlets with the same load-on-start-up value.\n" + "\n" + "Used in: servlet\n" + "-->\n" + "<!ELEMENT load-on-startup (#PCDATA)>\n" + "\n" + "<!--\n" + "\n" + "The local element contains the fully-qualified name of the\n" + "enterprise bean's local interface.\n" + "\n" + "Used in: ejb-local-ref\n" + "\n" + "-->\n" + "<!ELEMENT local (#PCDATA)>\n" + "\n" + "<!--\n" + "\n" + "The local-home element contains the fully-qualified name of the\n" + "enterprise bean's local home interface.\n" + "\n" + "Used in: ejb-local-ref\n" + "-->\n" + "<!ELEMENT local-home (#PCDATA)>\n" + "\n" + "<!--\n" + "The location element contains the location of the resource in the web\n" + "application relative to the root of the web application. The value of\n" + "the location must have a leading `/'.\n" + "\n" + "Used in: error-page\n" + "-->\n" + "<!ELEMENT location (#PCDATA)>\n" + "\n" + "<!--\n" + "The login-config element is used to configure the authentication\n" + "method that should be used, the realm name that should be used for\n" + "this application, and the attributes that are needed by the form login\n" + "mechanism.\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT login-config (auth-method?, realm-name?, form-login-config?)>\n" + "\n" + "<!--\n" + "The mime-mapping element defines a mapping between an extension\n" + "and a mime type.\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT mime-mapping (extension, mime-type)>\n" + "\n" + "<!--\n" + "The mime-type element contains a defined mime type. example:\n" + "\"text/plain\"\n" + "\n" + "Used in: mime-mapping\n" + "-->\n" + "<!ELEMENT mime-type (#PCDATA)>\n" + "\n" + "<!--\n" + "The param-name element contains the name of a parameter. Each parameter\n" + "name must be unique in the web application.\n" + "\n" + "\n" + "Used in: context-param, init-param\n" + "-->\n" + "<!ELEMENT param-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The param-value element contains the value of a parameter.\n" + "\n" + "Used in: context-param, init-param\n" + "-->\n" + "<!ELEMENT param-value (#PCDATA)>\n" + "\n" + "<!--\n" + "The realm name element specifies the realm name to use in HTTP\n" + "Basic authorization.\n" + "\n" + "Used in: login-config\n" + "-->\n" + "<!ELEMENT realm-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The remote element contains the fully-qualified name of the enterprise\n" + "bean's remote interface.\n" + "\n" + "Used in: ejb-ref\n" + "\n" + "Example:\n" + "\n" + "<remote>com.wombat.empl.EmployeeService</remote>\n" + "-->\n" + "<!ELEMENT remote (#PCDATA)>\n" + "\n" + "<!--\n" + "The res-auth element specifies whether the web application code signs\n" + "on programmatically to the resource manager, or whether the Container\n" + "will sign on to the resource manager on behalf of the web application. In the\n" + "latter case, the Container uses information that is supplied by the\n" + "Deployer.\n" + "\n" + "The value of this element must be one of the two following:\n" + "\n" + "\t<res-auth>Application</res-auth>\n" + "\t<res-auth>Container</res-auth>\n" + "\n" + "Used in: resource-ref\n" + "-->\n" + "<!ELEMENT res-auth (#PCDATA)>\n" + "\n" + "<!--\n" + "The res-ref-name element specifies the name of a resource manager\n" + "connection factory reference. The name is a JNDI name relative to the\n" + "java:comp/env context. The name must be unique within a web application.\n" + "\n" + "Used in: resource-ref\n" + "-->\n" + "<!ELEMENT res-ref-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The res-sharing-scope element specifies whether connections obtained\n" + "through the given resource manager connection factory reference can be\n" + "shared. The value of this element, if specified, must be one of the\n" + "two following:\n" + "\n" + "\t<res-sharing-scope>Shareable</res-sharing-scope>\n" + "\t<res-sharing-scope>Unshareable</res-sharing-scope>\n" + "\n" + "The default value is Shareable.\n" + "\n" + "Used in: resource-ref\n" + "-->\n" + "<!ELEMENT res-sharing-scope (#PCDATA)>\n" + "\n" + "<!--\n" + "The res-type element specifies the type of the data source. The type\n" + "is specified by the fully qualified Java language class or interface\n" + "expected to be implemented by the data source.\n" + "\n" + "Used in: resource-ref\n" + "-->\n" + "<!ELEMENT res-type (#PCDATA)>\n" + "\n" + "<!--\n" + "The resource-env-ref element contains a declaration of a web application's\n" + "reference to an administered object associated with a resource\n" + "in the web application's environment. It consists of an optional\n" + "description, the resource environment reference name, and an\n" + "indication of the resource environment reference type expected by\n" + "the web application code.\n" + "\n" + "Used in: web-app\n" + "\n" + "Example:\n" + "\n" + "<resource-env-ref>\n" + " <resource-env-ref-name>jms/StockQueue</resource-env-ref-name>\n" + " <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>\n" + "</resource-env-ref>\n" + "-->\n" + "<!ELEMENT resource-env-ref (description?, resource-env-ref-name,\n" + "\t\tresource-env-ref-type)>\n" + "\n" + "<!--\n" + "The resource-env-ref-name element specifies the name of a resource\n" + "environment reference; its value is the environment entry name used in\n" + "the web application code. The name is a JNDI name relative to the\n" + "java:comp/env context and must be unique within a web application.\n" + "\n" + "Used in: resource-env-ref\n" + "-->\n" + "<!ELEMENT resource-env-ref-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The resource-env-ref-type element specifies the type of a resource\n" + "environment reference. It is the fully qualified name of a Java\n" + "language class or interface.\n" + "\n" + "Used in: resource-env-ref\n" + "-->\n" + "<!ELEMENT resource-env-ref-type (#PCDATA)>\n" + "\n" + "<!--\n" + "The resource-ref element contains a declaration of a web application's\n" + "reference to an external resource. It consists of an optional\n" + "description, the resource manager connection factory reference name,\n" + "the indication of the resource manager connection factory type\n" + "expected by the web application code, the type of authentication\n" + "(Application or Container), and an optional specification of the\n" + "shareability of connections obtained from the resource (Shareable or\n" + "Unshareable).\n" + "\n" + "Used in: web-app\n" + "\n" + "Example:\n" + "\n" + " <resource-ref>\n" + "\t<res-ref-name>jdbc/EmployeeAppDB</res-ref-name>\n" + "\t<res-type>javax.sql.DataSource</res-type>\n" + "\t<res-auth>Container</res-auth>\n" + "\t<res-sharing-scope>Shareable</res-sharing-scope>\n" + " </resource-ref>\n" + "-->\n" + "<!ELEMENT resource-ref (description?, res-ref-name, res-type, res-auth,\n" + "\t\tres-sharing-scope?)>\n" + "\n" + "<!--\n" + "The role-link element is a reference to a defined security role. The\n" + "role-link element must contain the name of one of the security roles\n" + "defined in the security-role elements.\n" + "\n" + "Used in: security-role-ref\n" + "-->\n" + "<!ELEMENT role-link (#PCDATA)>\n" + "\n" + "<!--\n" + "The role-name element contains the name of a security role.\n" + "\n" + "The name must conform to the lexical rules for an NMTOKEN.\n" + "\n" + "Used in: auth-constraint, run-as, security-role, security-role-ref\n" + "-->\n" + "<!ELEMENT role-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The run-as element specifies the run-as identity to be used for the\n" + "execution of the web application. It contains an optional description, and\n" + "the name of a security role.\n" + "\n" + "Used in: servlet\n" + "-->\n" + "<!ELEMENT run-as (description?, role-name)>\n" + "\n" + "<!--\n" + "The security-constraint element is used to associate security\n" + "constraints with one or more web resource collections\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT security-constraint (display-name?, web-resource-collection+,\n" + "auth-constraint?, user-data-constraint?)>\n" + "\n" + "<!--\n" + "The security-role element contains the definition of a security\n" + "role. The definition consists of an optional description of the\n" + "security role, and the security role name.\n" + "\n" + "Used in: web-app\n" + "\n" + "Example:\n" + "\n" + " <security-role>\n" + "\t<description>\n" + "\t This role includes all employees who are authorized\n" + "\t to access the employee service application.\n" + "\t</description>\n" + "\t<role-name>employee</role-name>\n" + " </security-role>\n" + "-->\n" + "<!ELEMENT security-role (description?, role-name)>\n" + "\n" + "<!--\n" + "The security-role-ref element contains the declaration of a security\n" + "role reference in the web application's code. The declaration consists\n" + "of an optional description, the security role name used in the code,\n" + "and an optional link to a security role. If the security role is not\n" + "specified, the Deployer must choose an appropriate security role.\n" + "\n" + "The value of the role-name element must be the String used as the\n" + "parameter to the EJBContext.isCallerInRole(String roleName) method\n" + "or the HttpServletRequest.isUserInRole(String role) method.\n" + "\n" + "Used in: servlet\n" + "\n" + "-->\n" + "<!ELEMENT security-role-ref (description?, role-name, role-link?)>\n" + "\n" + "<!--\n" + "The servlet element contains the declarative data of a\n" + "servlet. If a jsp-file is specified and the load-on-startup element is\n" + "present, then the JSP should be precompiled and loaded.\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT servlet (icon?, servlet-name, display-name?, description?,\n" + "(servlet-class|jsp-file), init-param*, load-on-startup?, run-as?, security-role-ref*)>\n" + "\n" + "<!--\n" + "The servlet-class element contains the fully qualified class name\n" + "of the servlet.\n" + "\n" + "Used in: servlet\n" + "-->\n" + "<!ELEMENT servlet-class (#PCDATA)>\n" + "\n" + "<!--\n" + "The servlet-mapping element defines a mapping between a servlet\n" + "and a url pattern\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT servlet-mapping (servlet-name, url-pattern)>\n" + "\n" + "<!--\n" + "The servlet-name element contains the canonical name of the\n" + "servlet. Each servlet name is unique within the web application.\n" + "\n" + "Used in: filter-mapping, servlet, servlet-mapping\n" + "-->\n" + "<!ELEMENT servlet-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The session-config element defines the session parameters for\n" + "this web application.\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT session-config (session-timeout?)>\n" + "\n" + "<!--\n" + "The session-timeout element defines the default session timeout\n" + "interval for all sessions created in this web application. The\n" + "specified timeout must be expressed in a whole number of minutes.\n" + "If the timeout is 0 or less, the container ensures the default\n" + "behaviour of sessions is never to time out.\n" + "\n" + "Used in: session-config\n" + "-->\n" + "<!ELEMENT session-timeout (#PCDATA)>\n" + "\n" + "<!--\n" + "The small-icon element contains the name of a file\n" + "containing a small (16 x 16) icon image. The file\n" + "name is a relative path within the web application's\n" + "war file.\n" + "\n" + "The image may be either in the JPEG or GIF format.\n" + "The icon can be used by tools.\n" + "\n" + "Used in: icon\n" + "\n" + "Example:\n" + "\n" + "<small-icon>employee-service-icon16x16.jpg</small-icon>\n" + "-->\n" + "<!ELEMENT small-icon (#PCDATA)>\n" + "\n" + "<!--\n" + "The taglib element is used to describe a JSP tag library.\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT taglib (taglib-uri, taglib-location)>\n" + "\n" + "<!--\n" + "the taglib-location element contains the location (as a resource\n" + "relative to the root of the web application) where to find the Tag\n" + "Libary Description file for the tag library.\n" + "\n" + "Used in: taglib\n" + "-->\n" + "<!ELEMENT taglib-location (#PCDATA)>\n" + "\n" + "<!--\n" + "The taglib-uri element describes a URI, relative to the location\n" + "of the web.xml document, identifying a Tag Library used in the Web\n" + "Application.\n" + "\n" + "Used in: taglib\n" + "-->\n" + "<!ELEMENT taglib-uri (#PCDATA)>\n" + "\n" + "<!--\n" + "The transport-guarantee element specifies that the communication\n" + "between client and server should be NONE, INTEGRAL, or\n" + "CONFIDENTIAL. NONE means that the application does not require any\n" + "transport guarantees. A value of INTEGRAL means that the application\n" + "requires that the data sent between the client and server be sent in\n" + "such a way that it can't be changed in transit. CONFIDENTIAL means\n" + "that the application requires that the data be transmitted in a\n" + "fashion that prevents other entities from observing the contents of\n" + "the transmission. In most cases, the presence of the INTEGRAL or\n" + "CONFIDENTIAL flag will indicate that the use of SSL is required.\n" + "\n" + "Used in: user-data-constraint\n" + "-->\n" + "<!ELEMENT transport-guarantee (#PCDATA)>\n" + "\n" + "<!--\n" + "The url-pattern element contains the url pattern of the mapping. Must\n" + "follow the rules specified in Section 11.2 of the Servlet API\n" + "Specification.\n" + "\n" + "Used in: filter-mapping, servlet-mapping, web-resource-collection\n" + "-->\n" + "<!ELEMENT url-pattern (#PCDATA)>\n" + "\n" + "<!--\n" + "The user-data-constraint element is used to indicate how data\n" + "communicated between the client and container should be protected.\n" + "\n" + "Used in: security-constraint\n" + "-->\n" + "<!ELEMENT user-data-constraint (description?, transport-guarantee)>\n" + "\n" + "<!--\n" + "The web-resource-collection element is used to identify a subset\n" + "of the resources and HTTP methods on those resources within a web\n" + "application to which a security constraint applies. If no HTTP methods\n" + "are specified, then the security constraint applies to all HTTP\n" + "methods.\n" + "\n" + "Used in: security-constraint\n" + "-->\n" + "<!ELEMENT web-resource-collection (web-resource-name, description?,\n" + "url-pattern*, http-method*)>\n" + "\n" + "<!--\n" + "The web-resource-name contains the name of this web resource\n" + "collection.\n" + "\n" + "Used in: web-resource-collection\n" + "-->\n" + "<!ELEMENT web-resource-name (#PCDATA)>\n" + "\n" + "<!--\n" + "The welcome-file element contains file name to use as a default\n" + "welcome file, such as index.html\n" + "\n" + "Used in: welcome-file-list\n" + "-->\n" + "<!ELEMENT welcome-file (#PCDATA)>\n" + "\n" + "<!--\n" + "The welcome-file-list contains an ordered list of welcome files\n" + "elements.\n" + "\n" + "Used in: web-app\n" + "-->\n" + "<!ELEMENT welcome-file-list (welcome-file+)>\n" + "\n" + "<!--\n" + "The ID mechanism is to allow tools that produce additional deployment\n" + "information (i.e., information beyond the standard deployment\n" + "descriptor information) to store the non-standard information in a\n" + "separate file, and easily refer from these tool-specific files to the\n" + "information in the standard deployment descriptor.\n" + "\n" + "Tools are not allowed to add the non-standard information into the\n" + "standard deployment descriptor.\n" + "-->\n" + "\n" + "<!ATTLIST auth-constraint id ID #IMPLIED>\n" + "<!ATTLIST auth-method id ID #IMPLIED>\n" + "<!ATTLIST context-param id ID #IMPLIED>\n" + "<!ATTLIST description id ID #IMPLIED>\n" + "<!ATTLIST display-name id ID #IMPLIED>\n" + "<!ATTLIST distributable id ID #IMPLIED>\n" + "<!ATTLIST ejb-link id ID #IMPLIED>\n" + "<!ATTLIST ejb-local-ref id ID #IMPLIED>\n" + "<!ATTLIST ejb-ref id ID #IMPLIED>\n" + "<!ATTLIST ejb-ref-name id ID #IMPLIED>\n" + "<!ATTLIST ejb-ref-type id ID #IMPLIED>\n" + "<!ATTLIST env-entry id ID #IMPLIED>\n" + "<!ATTLIST env-entry-name id ID #IMPLIED>\n" + "<!ATTLIST env-entry-type id ID #IMPLIED>\n" + "<!ATTLIST env-entry-value id ID #IMPLIED>\n" + "<!ATTLIST error-code id ID #IMPLIED>\n" + "<!ATTLIST error-page id ID #IMPLIED>\n" + "<!ATTLIST exception-type id ID #IMPLIED>\n" + "<!ATTLIST extension id ID #IMPLIED>\n" + "<!ATTLIST filter id ID #IMPLIED>\n" + "<!ATTLIST filter-class id ID #IMPLIED>\n" + "<!ATTLIST filter-mapping id ID #IMPLIED>\n" + "<!ATTLIST filter-name id ID #IMPLIED>\n" + "<!ATTLIST form-error-page id ID #IMPLIED>\n" + "<!ATTLIST form-login-config id ID #IMPLIED>\n" + "<!ATTLIST form-login-page id ID #IMPLIED>\n" + "<!ATTLIST home id ID #IMPLIED>\n" + "<!ATTLIST http-method id ID #IMPLIED>\n" + "<!ATTLIST icon id ID #IMPLIED>\n" + "<!ATTLIST init-param id ID #IMPLIED>\n" + "<!ATTLIST jsp-file id ID #IMPLIED>\n" + "<!ATTLIST large-icon id ID #IMPLIED>\n" + "<!ATTLIST listener id ID #IMPLIED>\n" + "<!ATTLIST listener-class id ID #IMPLIED>\n" + "<!ATTLIST load-on-startup id ID #IMPLIED>\n" + "<!ATTLIST local id ID #IMPLIED>\n" + "<!ATTLIST local-home id ID #IMPLIED>\n" + "<!ATTLIST location id ID #IMPLIED>\n" + "<!ATTLIST login-config id ID #IMPLIED>\n" + "<!ATTLIST mime-mapping id ID #IMPLIED>\n" + "<!ATTLIST mime-type id ID #IMPLIED>\n" + "<!ATTLIST param-name id ID #IMPLIED>\n" + "<!ATTLIST param-value id ID #IMPLIED>\n" + "<!ATTLIST realm-name id ID #IMPLIED>\n" + "<!ATTLIST remote id ID #IMPLIED>\n" + "<!ATTLIST res-auth id ID #IMPLIED>\n" + "<!ATTLIST res-ref-name id ID #IMPLIED>\n" + "<!ATTLIST res-sharing-scope id ID #IMPLIED>\n" + "<!ATTLIST res-type id ID #IMPLIED>\n" + "<!ATTLIST resource-env-ref id ID #IMPLIED>\n" + "<!ATTLIST resource-env-ref-name id ID #IMPLIED>\n" + "<!ATTLIST resource-env-ref-type id ID #IMPLIED>\n" + "<!ATTLIST resource-ref id ID #IMPLIED>\n" + "<!ATTLIST role-link id ID #IMPLIED>\n" + "<!ATTLIST role-name id ID #IMPLIED>\n" + "<!ATTLIST run-as id ID #IMPLIED>\n" + "<!ATTLIST security-constraint id ID #IMPLIED>\n" + "<!ATTLIST security-role id ID #IMPLIED>\n" + "<!ATTLIST security-role-ref id ID #IMPLIED>\n" + "<!ATTLIST servlet id ID #IMPLIED>\n" + "<!ATTLIST servlet-class id ID #IMPLIED>\n" + "<!ATTLIST servlet-mapping id ID #IMPLIED>\n" + "<!ATTLIST servlet-name id ID #IMPLIED>\n" + "<!ATTLIST session-config id ID #IMPLIED>\n" + "<!ATTLIST session-timeout id ID #IMPLIED>\n" + "<!ATTLIST small-icon id ID #IMPLIED>\n" + "<!ATTLIST taglib id ID #IMPLIED>\n" + "<!ATTLIST taglib-location id ID #IMPLIED>\n" + "<!ATTLIST taglib-uri id ID #IMPLIED>\n" + "<!ATTLIST transport-guarantee id ID #IMPLIED>\n" + "<!ATTLIST url-pattern id ID #IMPLIED>\n" + "<!ATTLIST user-data-constraint id ID #IMPLIED>\n" + "<!ATTLIST web-app id ID #IMPLIED>\n" + "<!ATTLIST web-resource-collection id ID #IMPLIED>\n" + "<!ATTLIST web-resource-name id ID #IMPLIED>\n" + "<!ATTLIST welcome-file id ID #IMPLIED>\n" + "<!ATTLIST welcome-file-list id ID #IMPLIED>"; } private class GrailsPluginChangeChecker extends Thread{ DefaultGrailsPluginManager pluginManager; boolean enabled = true; GrailsPluginChangeChecker(DefaultGrailsPluginManager pluginManager){ this.pluginManager = pluginManager; } public void run(){ try{ sleep(15000); // delay start of scanner while(enabled){ pluginManager.checkForChanges(); sleep(DefaultGrailsPluginManager.SCAN_INTERVAL); } }catch(Exception e){ LOG.error("Error occured scanning for changes: " + e.getMessage(),e); } } } }

The table below shows all metrics for DefaultGrailsPluginManager.java.

MetricValueDescription