Author: scheu
Date: Wed Oct 1 03:56:44 2008
New Revision: 700737
URL: http://svn.apache.org/viewvc?rev=700737&view=rev
Log:
WSCOMMONS-394
Contributor:Rich Scheuerle
Add StAXUtils.createNetworkDetachedXMLStreamReader(..) methods
Add validating testcase.
Added:
webservices/commons/trunk/modules/axiom/modules/axiom-tests/test-resources/xml/web_w_dtd.xml
webservices/commons/trunk/modules/axiom/modules/axiom-tests/test-resources/xml/web_w_dtd2.xml
Modified:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/StAXUtils.java
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/OMDTDTest.java
Modified:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
URL:
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java?rev=700737&r1=700736&r2=700737&view=diff
==============================================================================
---
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
(original)
+++
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
Wed Oct 1 03:56:44 2008
@@ -33,6 +33,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
@@ -432,11 +433,45 @@
* @throws OMException
*/
protected OMNode createDTD() throws OMException {
- if (!parser.hasText())
+ if (!parser.hasText()) {
return null;
- lastNode = omfactory.createOMDocType(document, parser.getText());
+ }
+ String dtdText = getDTDText();
+ lastNode = omfactory.createOMDocType(document, dtdText);
return lastNode;
}
+
+ /**
+ * The getText() method for a DOCTYPE returns the
+ * subset of the DOCTYPE (not the direct infoset).
+ * This may force the parser to get information from
+ * the network.
+ * @return doctype subset
+ * @throws OMException
+ */
+ private String getDTDText() throws OMException {
+ String text = null;
+ try {
+ text = parser.getText();
+ } catch (RuntimeException e) {
+ // Woodstox (and perhaps other parsers)
+ // attempts to load the external subset even if
+ // external enties is false. So ignore this error
+ // if external entity support is explicitly disabled.
+ Boolean b = (Boolean) parser.getProperty(
+ XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES);
+ if (b == null || b == Boolean.TRUE) {
+ throw e;
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("An exception occurred while calling getText() for a
DOCTYPE. " +
+ "The exception is ignored because external " +
+ "entites support is disabled. " +
+ "The ignored exception is " + e);
+ }
+ }
+ return text;
+ }
/**
* Method createPI.
Modified:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/StAXUtils.java
URL:
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/StAXUtils.java?rev=700737&r1=700736&r2=700737&view=diff
==============================================================================
---
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/StAXUtils.java
(original)
+++
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/StAXUtils.java
Wed Oct 1 03:56:44 2008
@@ -58,11 +58,13 @@
// These static singletons are used when the XML*Factory is created with
// the StAXUtils classloader.
private static XMLInputFactory inputFactory = null;
+ private static XMLInputFactory inputNDFactory = null;
private static XMLOutputFactory outputFactory = null;
// These maps are used for the isFactoryPerClassLoader==true case
// The maps are synchronized and weak.
private static Map inputFactoryPerCL = Collections.synchronizedMap(new
WeakHashMap());
+ private static Map inputNDFactoryPerCL = Collections.synchronizedMap(new
WeakHashMap());
private static Map outputFactoryPerCL = Collections.synchronizedMap(new
WeakHashMap());
/**
@@ -73,9 +75,9 @@
public static XMLInputFactory getXMLInputFactory() {
if (isFactoryPerClassLoader) {
- return getXMLInputFactory_perClassLoader();
+ return getXMLInputFactory_perClassLoader(false);
} else {
- return getXMLInputFactory_singleton();
+ return getXMLInputFactory_singleton(false);
}
}
@@ -88,9 +90,9 @@
*/
public static XMLInputFactory getXMLInputFactory(boolean
factoryPerClassLoaderPolicy) {
if (factoryPerClassLoaderPolicy) {
- return getXMLInputFactory_perClassLoader();
+ return getXMLInputFactory_perClassLoader(false);
} else {
- return getXMLInputFactory_singleton();
+ return getXMLInputFactory_singleton(false);
}
}
@@ -293,14 +295,21 @@
/**
* @return XMLInputFactory for the current classloader
*/
- private static XMLInputFactory getXMLInputFactory_perClassLoader() {
+ private static XMLInputFactory getXMLInputFactory_perClassLoader(final
boolean isNetworkDetached) {
ClassLoader cl = getContextClassLoader();
XMLInputFactory factory;
if (cl == null) {
- factory = getXMLInputFactory_singleton();
+ factory = getXMLInputFactory_singleton(isNetworkDetached);
} else {
- factory = (XMLInputFactory) inputFactoryPerCL.get(cl);
+ // Check the cache
+ if (isNetworkDetached) {
+ factory = (XMLInputFactory) inputNDFactoryPerCL.get(cl);
+ } else {
+ factory = (XMLInputFactory) inputFactoryPerCL.get(cl);
+ }
+
+ // If not found in the cache map, crate a new factory
if (factory == null) {
if (log.isDebugEnabled()) {
@@ -315,7 +324,12 @@
AccessController.doPrivileged(
new PrivilegedAction() {
public Object run() {
- return XMLInputFactory.newInstance();
+ XMLInputFactory f =
XMLInputFactory.newInstance();
+ if (isNetworkDetached) {
+
f.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES,
+ Boolean.FALSE);
+ }
+ return f;
}
});
} catch (ClassCastException cce) {
@@ -337,6 +351,10 @@
setContextClassLoader(
XMLInputFactory.class.getClassLoader());
f =XMLInputFactory.newInstance();
+ if (isNetworkDetached) {
+
f.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES,
+ Boolean.FALSE);
+ }
} finally {
Thread.currentThread().
setContextClassLoader(saveCL);
@@ -347,14 +365,21 @@
}
if (factory != null) {
- inputFactoryPerCL.put(cl, factory);
+ // Cache the new factory
+ if (isNetworkDetached) {
+ inputNDFactoryPerCL.put(cl, factory);
+ } else {
+ inputFactoryPerCL.put(cl, factory);
+ }
+
if (log.isDebugEnabled()) {
log.debug("Created XMLInputFactory = " +
factory.getClass() +
" with classloader=" + cl);
log.debug("Size of XMLInputFactory map =" +
inputFactoryPerCL.size());
+ log.debug("isNetworkDetached =" + isNetworkDetached);
}
} else {
- factory = getXMLInputFactory_singleton();
+ factory = getXMLInputFactory_singleton(isNetworkDetached);
}
}
@@ -365,10 +390,10 @@
/**
* @return singleton XMLInputFactory loaded with the StAXUtils classloader
*/
- private static XMLInputFactory getXMLInputFactory_singleton() {
+ private static XMLInputFactory getXMLInputFactory_singleton(final boolean
isNetworkDetached) {
if (inputFactory == null) {
- inputFactory = (XMLInputFactory) AccessController.doPrivileged(
+ XMLInputFactory f = (XMLInputFactory)
AccessController.doPrivileged(
new PrivilegedAction() {
public Object run() {
Thread currentThread = Thread.currentThread();
@@ -377,6 +402,10 @@
try {
currentThread.setContextClassLoader(StAXUtils.class.getClassLoader());
factory = XMLInputFactory.newInstance();
+ if (isNetworkDetached) {
+
factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES,
+ Boolean.FALSE);
+ }
}
finally {
currentThread.setContextClassLoader(savedClassLoader);
@@ -384,9 +413,18 @@
return factory;
}
});
+ if (isNetworkDetached) {
+ inputNDFactory = f;
+ } else {
+ inputFactory = f;
+ }
if (log.isDebugEnabled()) {
if (inputFactory != null) {
- log.debug("Created singleton XMLInputFactory = " +
inputFactory.getClass());
+ if (isNetworkDetached) {
+ log.debug("Created singleton network detached
XMLInputFactory = " + f.getClass());
+ } else {
+ log.debug("Created singleton XMLInputFactory = " +
f.getClass());
+ }
}
}
}
@@ -514,4 +552,118 @@
return cl;
}
+
+ /**
+ * Create an XMLStreamReader that will operate when detached from a
network.
+ * The XMLStreamReader is created from a OMInputFactory that has external
+ * entities disabled. This kind of XMLStreamReader is useful for reading
+ * deployment information.
+ * @param in
+ * @param encoding
+ * @return
+ * @throws XMLStreamException
+ */
+ public static XMLStreamReader createNetworkDetachedXMLStreamReader(final
InputStream in, final String encoding)
+ throws XMLStreamException {
+ final XMLInputFactory inputFactory =
getNetworkDetachedXMLInputFactory();
+ try {
+ XMLStreamReader reader =
+ (XMLStreamReader)
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws XMLStreamException {
+ return inputFactory.createXMLStreamReader(in,
encoding);
+ }
+ }
+ );
+ if (isDebugEnabled) {
+ log.debug("XMLStreamReader is " + reader.getClass().getName());
+ }
+ return reader;
+ } catch (PrivilegedActionException pae) {
+ throw (XMLStreamException) pae.getException();
+ } finally {
+ releaseXMLInputFactory(inputFactory);
+ }
+ }
+
+ /**
+ * Gets an XMLInputFactory instance from pool.
+ *
+ * @return an XMLInputFactory instance.
+ */
+ public static XMLInputFactory getNetworkDetachedXMLInputFactory() {
+ if (isFactoryPerClassLoader) {
+ return getXMLInputFactory_perClassLoader(true);
+ } else {
+ return getXMLInputFactory_singleton(true);
+ }
+ }
+
+ /**
+ * Create an XMLStreamReader that will operate when detached from a
network.
+ * The XMLStreamReader is created from a OMInputFactory that has external
+ * entities disabled. This kind of XMLStreamReader is useful for reading
+ * deployment information.
+ *
+ * @param in
+ * @return
+ * @throws XMLStreamException
+ */
+ public static XMLStreamReader createNetworkDetachedXMLStreamReader(final
InputStream in)
+ throws XMLStreamException {
+ final XMLInputFactory inputFactory =
getNetworkDetachedXMLInputFactory();
+ try {
+ XMLStreamReader reader =
+ (XMLStreamReader)
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws XMLStreamException {
+ return inputFactory.createXMLStreamReader(in);
+ }
+ }
+ );
+
+ if (isDebugEnabled) {
+ log.debug("XMLStreamReader is " + reader.getClass().getName());
+ }
+ return reader;
+ } catch (PrivilegedActionException pae) {
+ throw (XMLStreamException) pae.getException();
+ } finally {
+ releaseXMLInputFactory(inputFactory);
+ }
+ }
+
+ /**
+ * Create an XMLStreamReader that will operate when detached from a
network.
+ * The XMLStreamReader is created from a OMInputFactory that has external
+ * entities disabled. This kind of XMLStreamReader is useful for reading
+ * deployment information.
+ *
+ * @param in
+ * @return
+ * @throws XMLStreamException
+ */
+ public static XMLStreamReader createNetworkDetachedXMLStreamReader(final
Reader in)
+ throws XMLStreamException {
+ final XMLInputFactory inputFactory =
getNetworkDetachedXMLInputFactory();
+ try {
+ XMLStreamReader reader =
+ (XMLStreamReader)
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws XMLStreamException {
+ return inputFactory.createXMLStreamReader(in);
+ }
+ }
+ );
+ if (isDebugEnabled) {
+ log.debug("XMLStreamReader is " + reader.getClass().getName());
+ }
+ return reader;
+ } catch (PrivilegedActionException pae) {
+ throw (XMLStreamException) pae.getException();
+ } finally {
+ releaseXMLInputFactory(inputFactory);
+ }
+ }
+
}
Modified:
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/OMDTDTest.java
URL:
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/OMDTDTest.java?rev=700737&r1=700736&r2=700737&view=diff
==============================================================================
---
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/OMDTDTest.java
(original)
+++
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/OMDTDTest.java
Wed Oct 1 03:56:44 2008
@@ -1,56 +1,125 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.axiom.om;
-
-import junit.framework.TestCase;
-import org.apache.axiom.om.impl.builder.StAXOMBuilder;
-
-import javax.xml.stream.XMLStreamException;
-import java.io.ByteArrayOutputStream;
-
-public class OMDTDTest extends TestCase {
-
- private OMDocument document;
-
- protected void setUp() throws Exception {
- try {
- StAXOMBuilder stAXOMBuilder = new
StAXOMBuilder("test-resources/xml/dtd.xml");
- document = this.document = stAXOMBuilder.getDocument();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void testDTDSerialization() {
- try {
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- document.serialize(baos);
- String serializedString = new String(baos.toByteArray());
-
- assertTrue(serializedString.indexOf("<!ENTITY foo \"bar\">") > -1);
- assertTrue(serializedString.indexOf("<!ENTITY bar \"foo\">") > -1);
- assertTrue(
- serializedString.indexOf("<feed
xmlns=\"http://www.w3.org/2005/Atom\">") > -1);
- } catch (XMLStreamException e) {
- fail("Bug in serializing OMDocuments which have DTDs, text and a
document element");
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.om;
+
+import junit.framework.TestCase;
+import org.apache.axiom.om.impl.builder.StAXOMBuilder;
+import org.apache.axiom.om.util.StAXUtils;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Iterator;
+
+public class OMDTDTest extends TestCase {
+
+ private OMDocument document;
+
+ protected void setUp() throws Exception {
+ try {
+ StAXOMBuilder stAXOMBuilder = new
StAXOMBuilder("test-resources/xml/dtd.xml");
+ document = this.document = stAXOMBuilder.getDocument();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void testDTDSerialization() {
+ try {
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ document.serialize(baos);
+ String serializedString = new String(baos.toByteArray());
+
+ assertTrue(serializedString.indexOf("<!ENTITY foo \"bar\">") > -1);
+ assertTrue(serializedString.indexOf("<!ENTITY bar \"foo\">") > -1);
+ assertTrue(
+ serializedString.indexOf("<feed
xmlns=\"http://www.w3.org/2005/Atom\">") > -1);
+ } catch (XMLStreamException e) {
+ fail("Bug in serializing OMDocuments which have DTDs, text and a
document element");
+ }
+ }
+
+ public void testDTDInWebXML() throws Exception{
+
+ // The JSR 173 (StAX) Specification did not do a very good job
+ // of defining how DOCTYPE entities are processed. According
+ // to the reference implementation, the external entities of the
DOCTYPE
+ // are always followed. This is wrong for a number of reasons.
+ // a) You cannot read the file unless you are network attached
...which
+ // might not be the case.
+ // b) You incur an expensive network access even though in many cases
+ // the DOCTYPE contents are unimportant.
+ //
+ // StAX should have allowed the caller to process the DOCTYPE as
information
+ // only and allow the caller to request external information. Perhaps
this
+ // will be addressed in future versions of the specification.
+ //
+ // For now, we have a work-around. A "network detached"
XMLStreamReader
+ // can be obtained from StAXUtils and used to process configuration
files
+ // (like a web.xml) that may contain DTD information.
+ //
+ // The following test first reads a normal web.xml that has a proper
+ // DTD.
+ // The second test has a web.xml where the external link is
intentionally
+ // changed to use the "urn" protocol. This second test is designed to
simulate
+ // reading the XML in a "network disconnected environment". Both
+ // of these examples should pass without error.
+ // Read a web.xml file that contains a DTD.
+
+ InputStream is = new
FileInputStream("test-resources/xml/web_w_dtd.xml");
+ XMLStreamReader reader =
StAXUtils.createNetworkDetachedXMLStreamReader(is);
+ StAXOMBuilder builder = new StAXOMBuilder(reader);
+ OMElement root = builder.getDocumentElement();
+ assertTrue(root.getLocalName().equals("web-app"));
+ OMDocument document = builder.getDocument();
+ Iterator i = document.getChildren();
+ OMDocType docType = null;
+ while (docType == null && i.hasNext()) {
+ Object obj = i.next();
+ if (obj instanceof OMDocType) {
+ docType = (OMDocType) obj;
+ }
+ }
+ assertTrue(docType != null);
+
+ // Make sure that a web.xml with a dtd can be loaded even if
disconnected
+ // from the network. In this case, the dtd has an invalid protocol
(urn)
+ // to simulate a disconnect from the network.
+ is = new FileInputStream("test-resources/xml/web_w_dtd2.xml");
+ reader = StAXUtils.createNetworkDetachedXMLStreamReader(is);
+ builder = new StAXOMBuilder(reader);
+ root = builder.getDocumentElement();
+ assertTrue(root.getLocalName().equals("web-app"));
+ document = builder.getDocument();
+ i = document.getChildren();
+ docType = null;
+ while (docType == null && i.hasNext()) {
+ Object obj = i.next();
+ if (obj instanceof OMDocType) {
+ docType = (OMDocType) obj;
+ }
+ }
+ assertTrue(docType != null);
+ }
+}
Added:
webservices/commons/trunk/modules/axiom/modules/axiom-tests/test-resources/xml/web_w_dtd.xml
URL:
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/test-resources/xml/web_w_dtd.xml?rev=700737&view=auto
==============================================================================
---
webservices/commons/trunk/modules/axiom/modules/axiom-tests/test-resources/xml/web_w_dtd.xml
(added)
+++
webservices/commons/trunk/modules/axiom/modules/axiom-tests/test-resources/xml/web_w_dtd.xml
Wed Oct 1 03:56:44 2008
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application
2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+ <servlet>
+ <servlet-name>snoop</servlet-name>
+ <servlet-class>SnoopServlet</servlet-class>
+ </servlet>
+ <servlet>
+ <servlet-name>file</servlet-name>
+ <servlet-class>ViewFile</servlet-class>
+ <init-param>
+ <param-name>initial</param-name>
+ <param-value>
+ 1000
+ </param-value>
+ <description>
+ The initial value for the counter <!-- optional -->
+ </description>
+ </init-param>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>
+ mv
+ </servlet-name>
+ <url-pattern>
+ *.wm
+ </url-pattern>
+ </servlet-mapping>
+
+ <distributed/>
+
+ <security-role>
+ <role-name>
+ manager
+ </role-name>
+ <role-name>
+ director
+ </role-name>
+ <role-name>
+ president
+ </role-name>
+ </security-role>
+</web-app>
\ No newline at end of file
Added:
webservices/commons/trunk/modules/axiom/modules/axiom-tests/test-resources/xml/web_w_dtd2.xml
URL:
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/test-resources/xml/web_w_dtd2.xml?rev=700737&view=auto
==============================================================================
---
webservices/commons/trunk/modules/axiom/modules/axiom-tests/test-resources/xml/web_w_dtd2.xml
(added)
+++
webservices/commons/trunk/modules/axiom/modules/axiom-tests/test-resources/xml/web_w_dtd2.xml
Wed Oct 1 03:56:44 2008
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application
2.3//EN" "urn://java.sun.com/dtd/web-app_2_3.dtd">
+<!-- The location of the DOCTYPE is intentionally invalid to ensure that the
document is built even
+ if disconnected from the network -->
+ <web-app>
+ <servlet>
+ <servlet-name>snoop</servlet-name>
+ <servlet-class>SnoopServlet</servlet-class>
+ </servlet>
+ <servlet>
+ <servlet-name>file</servlet-name>
+ <servlet-class>ViewFile</servlet-class>
+ <init-param>
+ <param-name>initial</param-name>
+ <param-value>
+ 1000
+ </param-value>
+ <description>
+ The initial value for the counter <!-- optional -->
+ </description>
+ </init-param>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>
+ mv
+ </servlet-name>
+ <url-pattern>
+ *.wm
+ </url-pattern>
+ </servlet-mapping>
+
+ <distributed/>
+
+ <security-role>
+ <role-name>
+ manager
+ </role-name>
+ <role-name>
+ director
+ </role-name>
+ <role-name>
+ president
+ </role-name>
+ </security-role>
+</web-app>
\ No newline at end of file