Update the http.jetty bundle to the new plugin, make it compile/run against javax.servlet version 2.1, and hook it up to the parent pom.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@537994 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http.jetty/pom.xml b/http.jetty/pom.xml
index ec12b23..e720c3f 100644
--- a/http.jetty/pom.xml
+++ b/http.jetty/pom.xml
@@ -5,7 +5,7 @@
     <version>0.9.0-incubator-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
-  <packaging>osgi-bundle</packaging>
+  <packaging>bundle</packaging>
   <name>Apache Felix HTTP Service</name>
   <artifactId>org.apache.felix.http.jetty</artifactId>
   <dependencies>
@@ -22,9 +22,10 @@
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>tomcat</groupId>
-      <artifactId>servlet</artifactId>
-      <version>4.0.6</version>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>javax.servlet</artifactId>
+      <version>${pom.version}</version>
+      <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>jetty</groupId>
@@ -35,31 +36,24 @@
   <build>
     <plugins>
       <plugin>
-        <groupId>org.apache.felix.plugins</groupId>
-        <artifactId>maven-osgi-plugin</artifactId>
-        <version>${pom.version}</version>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
         <extensions>true</extensions>
         <configuration>
-          <ignorePackage>
-            com.sun.net.ssl.internal.ssl,
-            com.sun.net.ssl,
-            org.xml.sax,
-            org.xml.sax.helpers,
-            javax.xml.parsers,
-            javax.security.cert
-          </ignorePackage>
-          <osgiManifest>
-            <bundleName>HTTP Service</bundleName>
-            <bundleDescription>An implementation of the OSGi HTTP Service using Jetty.</bundleDescription>
-            <bundleActivator>auto-detect</bundleActivator>
-            <bundleDocUrl>http://oscar-osgi.sf.net/obr2/${pom.artifactId}/</bundleDocUrl>
-            <bundleUrl>http://oscar-osgi.sf.net/obr2/${pom.artifactId}/${pom.artifactId}-${pom.version}.jar</bundleUrl>
-            <bundleSource>http://oscar-osgi.sf.net/obr2/${pom.artifactId}/${pom.artifactId}-${pom.version}-src.jar</bundleSource>
-            <bundleSymbolicName>${pom.artifactId}</bundleSymbolicName>
-            <dynamicImportPackage>javax.net.ssl</dynamicImportPackage>
-            <exportPackage>org.osgi.service.http; version=1.1,javax.servlet;javax.servlet.http;version=2.3.0</exportPackage>
-            <exportService>org.osgi.service.http.HttpService</exportService>
-          </osgiManifest>
+          <instructions>
+            <Bundle-Name>HTTP Service</Bundle-Name>
+            <Bundle-Description>An implementation of the OSGi HTTP Service using Jetty.</Bundle-Description>
+            <Bundle-Activator>${pom.artifactId}.Activator</Bundle-Activator>
+            <Bundle-DocURL>http://oscar-osgi.sf.net/obr2/${pom.artifactId}/</Bundle-DocURL>
+            <Bundle-URL>http://oscar-osgi.sf.net/obr2/${pom.artifactId}/${pom.artifactId}-${pom.version}.jar</Bundle-URL>
+            <Bundle-Source>http://oscar-osgi.sf.net/obr2/${pom.artifactId}/${pom.artifactId}-${pom.version}-src.jar</Bundle-Source>
+            <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
+            <DynamicImport-Package>javax.net.ssl</DynamicImport-Package>
+            <Export-Package>org.osgi.service.http; version=1.1</Export-Package>
+            <Import-Package>!com.sun.net.ssl.internal.ssl,!com.sun.net.ssl,!org.xml.sax,!org.xml.sax.helpers,!javax.xml.parsers,!javax.security.cert,javax.servlet;version=1.1, javax.servlet.http;version=1.1,*</Import-Package>
+	    <Private-Package>org.apache.felix.http.jetty, org.mortbay.*</Private-Package>
+            <Export-Service>org.osgi.service.http.HttpService</Export-Service>
+          </instructions>
         </configuration>
       </plugin>
     </plugins>
diff --git a/http.jetty/src/main/java/org/mortbay/jetty/servlet/OsgiServletHandler.java b/http.jetty/src/main/java/org/mortbay/jetty/servlet/OsgiServletHandler.java
index 7f8f154..3e806ee 100644
--- a/http.jetty/src/main/java/org/mortbay/jetty/servlet/OsgiServletHandler.java
+++ b/http.jetty/src/main/java/org/mortbay/jetty/servlet/OsgiServletHandler.java
@@ -92,7 +92,17 @@
         else
         {
             //TODO: any other error/auth handling we should do in here?
-            response.flushBuffer();
+            
+            // response.flushBuffer() if available
+            try
+            {
+                response.getClass().getDeclaredMethod("flushBuffer", null).invoke(response, null);
+            } 
+            catch (Exception ex)
+            {
+                // else ignore
+                ex.printStackTrace();
+            }
         }
     }
 }
diff --git a/http.jetty/src/main/java/org/osgi/service/http/HttpContext.java b/http.jetty/src/main/java/org/osgi/service/http/HttpContext.java
deleted file mode 100644
index d5a0eb5..0000000
--- a/http.jetty/src/main/java/org/osgi/service/http/HttpContext.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * $Header: /cvshome/build/org.osgi.service.http/src/org/osgi/service/http/HttpContext.java,v 1.9 2006/03/14 01:20:39 hargrave Exp $
- *
- * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
- *
- * 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.osgi.service.http;
-
-import java.io.IOException;
-import java.net.URL;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * This interface defines methods that the Http Service may call to get
- * information about a registration.
- * 
- * <p>
- * Servlets and resources may be registered with an <code>HttpContext</code>
- * object; if no <code>HttpContext</code> object is specified, a default
- * <code>HttpContext</code> object is used. Servlets that are registered using the
- * same <code>HttpContext</code> object will share the same
- * <code>ServletContext</code> object.
- * 
- * <p>
- * This interface is implemented by users of the <code>HttpService</code>.
- * 
- * @version $Revision: 1.9 $
- */
-public interface HttpContext {
-	/**
-	 * <code>HttpServletRequest</code> attribute specifying the name of the
-	 * authenticated user. The value of the attribute can be retrieved by
-	 * <code>HttpServletRequest.getRemoteUser</code>. This attribute name is
-	 * <code>org.osgi.service.http.authentication.remote.user</code>.
-	 * 
-	 * @since 1.1
-	 */
-	public static final String	REMOTE_USER			= "org.osgi.service.http.authentication.remote.user";
-	/**
-	 * <code>HttpServletRequest</code> attribute specifying the scheme used in
-	 * authentication. The value of the attribute can be retrieved by
-	 * <code>HttpServletRequest.getAuthType</code>. This attribute name is
-	 * <code>org.osgi.service.http.authentication.type</code>.
-	 * 
-	 * @since 1.1
-	 */
-	public static final String	AUTHENTICATION_TYPE	= "org.osgi.service.http.authentication.type";
-	/**
-	 * <code>HttpServletRequest</code> attribute specifying the
-	 * <code>Authorization</code> object obtained from the
-	 * <code>org.osgi.service.useradmin.UserAdmin</code> service. The value of the
-	 * attribute can be retrieved by
-	 * <code>HttpServletRequest.getAttribute(HttpContext.AUTHORIZATION)</code>.
-	 * This attribute name is <code>org.osgi.service.useradmin.authorization</code>.
-	 * 
-	 * @since 1.1
-	 */
-	public static final String	AUTHORIZATION		= "org.osgi.service.useradmin.authorization";
-
-	/**
-	 * Handles security for the specified request.
-	 * 
-	 * <p>
-	 * The Http Service calls this method prior to servicing the specified
-	 * request. This method controls whether the request is processed in the
-	 * normal manner or an error is returned.
-	 * 
-	 * <p>
-	 * If the request requires authentication and the Authorization header in
-	 * the request is missing or not acceptable, then this method should set the
-	 * WWW-Authenticate header in the response object, set the status in the
-	 * response object to Unauthorized(401) and return <code>false</code>. See
-	 * also RFC 2617: <i>HTTP Authentication: Basic and Digest Access
-	 * Authentication </i> (available at http://www.ietf.org/rfc/rfc2617.txt).
-	 * 
-	 * <p>
-	 * If the request requires a secure connection and the <code>getScheme</code>
-	 * method in the request does not return 'https' or some other acceptable
-	 * secure protocol, then this method should set the status in the response
-	 * object to Forbidden(403) and return <code>false</code>.
-	 * 
-	 * <p>
-	 * When this method returns <code>false</code>, the Http Service will send
-	 * the response back to the client, thereby completing the request. When
-	 * this method returns <code>true</code>, the Http Service will proceed with
-	 * servicing the request.
-	 * 
-	 * <p>
-	 * If the specified request has been authenticated, this method must set the
-	 * {@link #AUTHENTICATION_TYPE}request attribute to the type of
-	 * authentication used, and the {@link #REMOTE_USER}request attribute to
-	 * the remote user (request attributes are set using the
-	 * <code>setAttribute</code> method on the request). If this method does not
-	 * perform any authentication, it must not set these attributes.
-	 * 
-	 * <p>
-	 * If the authenticated user is also authorized to access certain resources,
-	 * this method must set the {@link #AUTHORIZATION}request attribute to the
-	 * <code>Authorization</code> object obtained from the
-	 * <code>org.osgi.service.useradmin.UserAdmin</code> service.
-	 * 
-	 * <p>
-	 * The servlet responsible for servicing the specified request determines
-	 * the authentication type and remote user by calling the
-	 * <code>getAuthType</code> and <code>getRemoteUser</code> methods,
-	 * respectively, on the request.
-	 * 
-	 * @param request the HTTP request
-	 * @param response the HTTP response
-	 * @return <code>true</code> if the request should be serviced, <code>false</code>
-	 *         if the request should not be serviced and Http Service will send
-	 *         the response back to the client.
-	 * @throws java.io.IOException may be thrown by this method. If this
-	 *            occurs, the Http Service will terminate the request and close
-	 *            the socket.
-	 */
-	public boolean handleSecurity(HttpServletRequest request,
-			HttpServletResponse response) throws IOException;
-
-	/**
-	 * Maps a resource name to a URL.
-	 * 
-	 * <p>
-	 * Called by the Http Service to map a resource name to a URL. For servlet
-	 * registrations, Http Service will call this method to support the
-	 * <code>ServletContext</code> methods <code>getResource</code> and
-	 * <code>getResourceAsStream</code>. For resource registrations, Http Service
-	 * will call this method to locate the named resource. The context can
-	 * control from where resources come. For example, the resource can be
-	 * mapped to a file in the bundle's persistent storage area via
-	 * <code>bundleContext.getDataFile(name).toURL()</code> or to a resource in
-	 * the context's bundle via <code>getClass().getResource(name)</code>
-	 * 
-	 * @param name the name of the requested resource
-	 * @return URL that Http Service can use to read the resource or
-	 *         <code>null</code> if the resource does not exist.
-	 */
-	public URL getResource(String name);
-
-	/**
-	 * Maps a name to a MIME type.
-	 * 
-	 * Called by the Http Service to determine the MIME type for the name. For
-	 * servlet registrations, the Http Service will call this method to support
-	 * the <code>ServletContext</code> method <code>getMimeType</code>. For
-	 * resource registrations, the Http Service will call this method to
-	 * determine the MIME type for the Content-Type header in the response.
-	 * 
-	 * @param name determine the MIME type for this name.
-	 * @return MIME type (e.g. text/html) of the name or <code>null</code> to
-	 *         indicate that the Http Service should determine the MIME type
-	 *         itself.
-	 */
-	public String getMimeType(String name);
-}
diff --git a/http.jetty/src/main/java/org/osgi/service/http/HttpService.java b/http.jetty/src/main/java/org/osgi/service/http/HttpService.java
deleted file mode 100644
index 95acce9..0000000
--- a/http.jetty/src/main/java/org/osgi/service/http/HttpService.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * $Header: /cvshome/build/org.osgi.service.http/src/org/osgi/service/http/HttpService.java,v 1.10 2006/03/14 01:20:39 hargrave Exp $
- *
- * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
- *
- * 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.osgi.service.http;
-
-import javax.servlet.Servlet;
-import javax.servlet.ServletException;
-import java.util.Dictionary;
-
-/**
- * The Http Service allows other bundles in the OSGi environment to dynamically
- * register resources and servlets into the URI namespace of Http Service. A
- * bundle may later unregister its resources or servlets.
- * 
- * @version $Revision: 1.10 $
- * @see HttpContext
- */
-public interface HttpService {
-	/**
-	 * Registers a servlet into the URI namespace.
-	 * 
-	 * <p>
-	 * The alias is the name in the URI namespace of the Http Service at which
-	 * the registration will be mapped.
-	 * 
-	 * <p>
-	 * An alias must begin with slash ('/') and must not end with slash ('/'),
-	 * with the exception that an alias of the form &quot;/&quot; is used to
-	 * denote the root alias. See the specification text for details on how HTTP
-	 * requests are mapped to servlet and resource registrations.
-	 * 
-	 * <p>
-	 * The Http Service will call the servlet's <code>init</code> method before
-	 * returning.
-	 * 
-	 * <pre>
-	 * httpService.registerServlet(&quot;/myservlet&quot;, servlet, initparams, context);
-	 * </pre>
-	 * 
-	 * <p>
-	 * Servlets registered with the same <code>HttpContext</code> object will
-	 * share the same <code>ServletContext</code>. The Http Service will call the
-	 * <code>context</code> argument to support the <code>ServletContext</code>
-	 * methods <code>getResource</code>,<code>getResourceAsStream</code> and
-	 * <code>getMimeType</code>, and to handle security for requests. If the
-	 * <code>context</code> argument is <code>null</code>, a default
-	 * <code>HttpContext</code> object is used (see
-	 * {@link #createDefaultHttpContext}).
-	 * 
-	 * @param alias name in the URI namespace at which the servlet is registered
-	 * @param servlet the servlet object to register
-	 * @param initparams initialization arguments for the servlet or
-	 *        <code>null</code> if there are none. This argument is used by the
-	 *        servlet's <code>ServletConfig</code> object.
-	 * @param context the <code>HttpContext</code> object for the registered
-	 *        servlet, or <code>null</code> if a default <code>HttpContext</code> is
-	 *        to be created and used.
-	 * @throws NamespaceException if the registration fails because the alias
-	 *            is already in use.
-	 * @throws javax.servlet.ServletException if the servlet's <code>init</code>
-	 *            method throws an exception, or the given servlet object has
-	 *            already been registered at a different alias.
-	 * @throws java.lang.IllegalArgumentException if any of the arguments are
-	 *            invalid
-	 */
-	public void registerServlet(String alias, Servlet servlet,
-			Dictionary initparams, HttpContext context)
-			throws ServletException, NamespaceException;
-
-	/**
-	 * Registers resources into the URI namespace.
-	 * 
-	 * <p>
-	 * The alias is the name in the URI namespace of the Http Service at which
-	 * the registration will be mapped. An alias must begin with slash ('/') and
-	 * must not end with slash ('/'), with the exception that an alias of the
-	 * form &quot;/&quot; is used to denote the root alias. The name parameter
-	 * must also not end with slash ('/'). See the specification text for
-	 * details on how HTTP requests are mapped to servlet and resource
-	 * registrations.
-	 * <p>
-	 * For example, suppose the resource name /tmp is registered to the alias
-	 * /files. A request for /files/foo.txt will map to the resource name
-	 * /tmp/foo.txt.
-	 * 
-	 * <pre>
-	 * httpservice.registerResources(&quot;/files&quot;, &quot;/tmp&quot;, context);
-	 * </pre>
-	 * 
-	 * The Http Service will call the <code>HttpContext</code> argument to map
-	 * resource names to URLs and MIME types and to handle security for
-	 * requests. If the <code>HttpContext</code> argument is <code>null</code>, a
-	 * default <code>HttpContext</code> is used (see
-	 * {@link #createDefaultHttpContext}).
-	 * 
-	 * @param alias name in the URI namespace at which the resources are
-	 *        registered
-	 * @param name the base name of the resources that will be registered
-	 * @param context the <code>HttpContext</code> object for the registered
-	 *        resources, or <code>null</code> if a default <code>HttpContext</code>
-	 *        is to be created and used.
-	 * @throws NamespaceException if the registration fails because the alias
-	 *            is already in use.
-	 * @throws java.lang.IllegalArgumentException if any of the parameters
-	 *            are invalid
-	 */
-	public void registerResources(String alias, String name,
-			HttpContext context) throws NamespaceException;
-
-	/**
-	 * Unregisters a previous registration done by <code>registerServlet</code> or
-	 * <code>registerResources</code> methods.
-	 * 
-	 * <p>
-	 * After this call, the registered alias in the URI name-space will no
-	 * longer be available. If the registration was for a servlet, the Http
-	 * Service must call the <code>destroy</code> method of the servlet before
-	 * returning.
-	 * <p>
-	 * If the bundle which performed the registration is stopped or otherwise
-	 * "unget"s the Http Service without calling {@link #unregister}then Http
-	 * Service must automatically unregister the registration. However, if the
-	 * registration was for a servlet, the <code>destroy</code> method of the
-	 * servlet will not be called in this case since the bundle may be stopped.
-	 * {@link #unregister}must be explicitly called to cause the
-	 * <code>destroy</code> method of the servlet to be called. This can be done
-	 * in the <code>BundleActivator.stop</code> method of the
-	 * bundle registering the servlet.
-	 * 
-	 * @param alias name in the URI name-space of the registration to unregister
-	 * @throws java.lang.IllegalArgumentException if there is no registration
-	 *            for the alias or the calling bundle was not the bundle which
-	 *            registered the alias.
-	 */
-	public void unregister(String alias);
-
-	/**
-	 * Creates a default <code>HttpContext</code> for registering servlets or
-	 * resources with the HttpService, a new <code>HttpContext</code> object is
-	 * created each time this method is called.
-	 * 
-	 * <p>
-	 * The behavior of the methods on the default <code>HttpContext</code> is
-	 * defined as follows:
-	 * <ul>
-	 * <li><code>getMimeType</code>- Does not define any customized MIME types
-	 * for the Content-Type header in the response, and always returns
-	 * <code>null</code>.
-	 * <li><code>handleSecurity</code>- Performs implementation-defined
-	 * authentication on the request.
-	 * <li><code>getResource</code>- Assumes the named resource is in the
-	 * context bundle; this method calls the context bundle's
-	 * <code>Bundle.getResource</code> method, and returns the appropriate URL to
-	 * access the resource. On a Java runtime environment that supports
-	 * permissions, the Http Service needs to be granted 
-	 * <code>org.osgi.framework.AdminPermission[*,RESOURCE]</code>.
-	 * </ul>
-	 * 
-	 * @return a default <code>HttpContext</code> object.
-	 * @since 1.1
-	 */
-	public HttpContext createDefaultHttpContext();
-}
diff --git a/http.jetty/src/main/java/org/osgi/service/http/NamespaceException.java b/http.jetty/src/main/java/org/osgi/service/http/NamespaceException.java
deleted file mode 100644
index c8e7889..0000000
--- a/http.jetty/src/main/java/org/osgi/service/http/NamespaceException.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * $Header: /cvshome/build/org.osgi.service.http/src/org/osgi/service/http/NamespaceException.java,v 1.9 2006/03/14 01:20:39 hargrave Exp $
- *
- * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
- *
- * 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.osgi.service.http;
-
-/**
- * A NamespaceException is thrown to indicate an error with the caller's request
- * to register a servlet or resources into the URI namespace of the Http
- * Service. This exception indicates that the requested alias already is in use.
- * 
- * @version $Revision: 1.9 $
- */
-public class NamespaceException extends Exception {
-    static final long serialVersionUID = 7235606031147877747L;
-	/**
-	 * Nested exception.
-	 */
-	private Throwable	cause;
-
-	/**
-	 * Construct a <code>NamespaceException</code> object with a detail message.
-	 * 
-	 * @param message the detail message
-	 */
-	public NamespaceException(String message) {
-		super(message);
-		cause = null;
-	}
-
-	/**
-	 * Construct a <code>NamespaceException</code> object with a detail message
-	 * and a nested exception.
-	 * 
-	 * @param message The detail message.
-	 * @param cause The nested exception.
-	 */
-	public NamespaceException(String message, Throwable cause) {
-		super(message);
-		this.cause = cause;
-	}
-
-	/**
-	 * Returns the nested exception.
-	 *
-     * <p>This method predates the general purpose exception chaining mechanism.
-     * The {@link #getCause()} method is now the preferred means of
-     * obtaining this information.
-	 * 
-	 * @return the nested exception or <code>null</code> if there is no nested
-	 *         exception.
-	 */
-	public Throwable getException() {
-		return cause;
-	}
-
-	/**
-	 * Returns the cause of this exception or <code>null</code> if no
-	 * cause was specified when this exception was created.
-	 *
-	 * @return  The cause of this exception or <code>null</code> if no
-	 * cause was specified.
-	 * @since 1.2 
-	 */
-	public Throwable getCause() {
-	    return cause;
-	}
-
-	/**
-	 * The cause of this exception can only be set when constructed.
-	 *
-	 * @param cause Cause of the exception.
-	 * @return This object.
-	 * @throws java.lang.IllegalStateException
-	 * This method will always throw an <code>IllegalStateException</code>
-	 * since the cause of this exception can only be set when constructed.
-	 * @since 1.2 
-	 */
-	public Throwable initCause(Throwable cause) {
-		throw new IllegalStateException();
-	}
-}
diff --git a/pom.xml b/pom.xml
index 2276a2a..e68dee4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -138,7 +138,7 @@
         <module>eventadmin.bridge.configuration</module>
         <module>eventadmin.bridge.useradmin</module>
         <module>eventadmin.bridge.wireadmin</module>
-
+        <module>http.jetty</module>
         <module>scr</module>
         <module>configadmin</module>
         <module>metatype</module>
@@ -172,8 +172,6 @@
         <module>upnp.sample.tv</module>
         <module>upnp.sample.clock</module>
         <module>upnp.sample.binaryLight</module>
-        <!--    <module>http.jetty</module> -->
-        
 
         <!--    <module>tools/mangen</module> -->