geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rwo...@apache.org
Subject svn commit: r1081278 - in /geronimo/server/trunk/plugins/console/console-base-portlets/src/main: java/org/apache/geronimo/console/bundlemanager/ webapp/WEB-INF/view/bundlemanager/
Date Mon, 14 Mar 2011 08:08:19 GMT
Author: rwonly
Date: Mon Mar 14 08:08:19 2011
New Revision: 1081278

URL: http://svn.apache.org/viewvc?rev=1081278&view=rev
Log:
GERONIMO-5847 add Show dynamic import packages and Show import packages from require bundle
functionalities, and make the bundle perspective as default

Modified:
    geronimo/server/trunk/plugins/console/console-base-portlets/src/main/java/org/apache/geronimo/console/bundlemanager/BundleManagerPortlet.java
    geronimo/server/trunk/plugins/console/console-base-portlets/src/main/webapp/WEB-INF/view/bundlemanager/BundleManager.jsp
    geronimo/server/trunk/plugins/console/console-base-portlets/src/main/webapp/WEB-INF/view/bundlemanager/ShowWiredBundles.jsp

Modified: geronimo/server/trunk/plugins/console/console-base-portlets/src/main/java/org/apache/geronimo/console/bundlemanager/BundleManagerPortlet.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/console/console-base-portlets/src/main/java/org/apache/geronimo/console/bundlemanager/BundleManagerPortlet.java?rev=1081278&r1=1081277&r2=1081278&view=diff
==============================================================================
--- geronimo/server/trunk/plugins/console/console-base-portlets/src/main/java/org/apache/geronimo/console/bundlemanager/BundleManagerPortlet.java
(original)
+++ geronimo/server/trunk/plugins/console/console-base-portlets/src/main/java/org/apache/geronimo/console/bundlemanager/BundleManagerPortlet.java
Mon Mar 14 08:08:19 2011
@@ -51,6 +51,8 @@ import org.apache.geronimo.console.util.
 import org.apache.geronimo.kernel.config.ConfigurationInfo;
 import org.apache.geronimo.kernel.config.ConfigurationManager;
 import org.apache.xbean.osgi.bundle.util.BundleDescription;
+import org.apache.xbean.osgi.bundle.util.VersionRange;
+import org.apache.xbean.osgi.bundle.util.BundleDescription.RequireBundle;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
@@ -257,32 +259,48 @@ public class BundleManagerPortlet extend
                 Bundle bundle = bundleContext.getBundle(id);
                 
                 String perspectiveType = renderRequest.getParameter("perspectiveTypeValue");
-                if (perspectiveType == null || perspectiveType == "") perspectiveType = "package";
//when we access this page with a renderURL, we need the default value
+                if (perspectiveType == null || perspectiveType == "") perspectiveType = "bundle";
//when we access this page with a renderURL, we need the default value
                 
                 ServiceReference reference = bundleContext.getServiceReference(PackageAdmin.class.getName());
                 PackageAdmin packageAdmin = (PackageAdmin) bundle.getBundleContext().getService(reference);
                 
 
                 Set<PackageBundlePair> importingPairs = getImportingPairs(packageAdmin,
bundle);
+                Set<PackageBundlePair> dynamicImportingPairs = getDynamicImportingPairs(packageAdmin,
bundle, importingPairs);
+                Set<PackageBundlePair> requireBundlesImportingPairs = getRequireBundlesImportingPairs(packageAdmin,
bundle);
                 Set<PackageBundlePair> exportingPairs = getExportingPairs(packageAdmin,
bundle);
                 
+                
                 if ("package".equals(perspectiveType)){
                     List<PackagePerspective> importingPackagePerspectives = getPackagePerspectives(importingPairs);
+                    List<PackagePerspective> dynamicImportingPackagePerspectives =
getPackagePerspectives(dynamicImportingPairs);
+                    List<PackagePerspective> requireBundlesImportingPackagePerspectives
= getPackagePerspectives(requireBundlesImportingPairs);
                     List<PackagePerspective> exportingPackagePerspectives = getPackagePerspectives(exportingPairs);
                     
                     Collections.sort(importingPackagePerspectives);
+                    Collections.sort(dynamicImportingPackagePerspectives);
+                    Collections.sort(requireBundlesImportingPackagePerspectives);
                     Collections.sort(exportingPackagePerspectives);
                     
                     renderRequest.setAttribute("importingPackagePerspectives", importingPackagePerspectives);
+                    renderRequest.setAttribute("dynamicImportingPackagePerspectives", dynamicImportingPackagePerspectives);
+                    renderRequest.setAttribute("requireBundlesImportingPackagePerspectives",
requireBundlesImportingPackagePerspectives);
                     renderRequest.setAttribute("exportingPackagePerspectives", exportingPackagePerspectives);
+                    
                 }else{  //"bundle".equals(perspectiveType)){
                     List<BundlePerspective> importingBundlePerspectives = getBundlePerspectives(importingPairs);
+                    List<BundlePerspective> dynamicImportingBundlePerspectives = getBundlePerspectives(dynamicImportingPairs);
+                    List<BundlePerspective> requireBundlesImportingBundlePerspectives
= getBundlePerspectives(requireBundlesImportingPairs);
                     List<BundlePerspective> exportingBundlePerspectives = getBundlePerspectives(exportingPairs);
                     
                     Collections.sort(importingBundlePerspectives);
+                    Collections.sort(dynamicImportingBundlePerspectives);
+                    Collections.sort(requireBundlesImportingBundlePerspectives);
                     Collections.sort(exportingBundlePerspectives);
                     
                     renderRequest.setAttribute("importingBundlePerspectives", importingBundlePerspectives);
+                    renderRequest.setAttribute("dynamicImportingBundlePerspectives", dynamicImportingBundlePerspectives);
+                    renderRequest.setAttribute("requireBundlesImportingBundlePerspectives",
requireBundlesImportingBundlePerspectives);
                     renderRequest.setAttribute("exportingBundlePerspectives", exportingBundlePerspectives);
                 }
                                 
@@ -593,6 +611,7 @@ public class BundleManagerPortlet extend
         // handle static wire via Import-Package
         List<BundleDescription.ImportPackage> imports = description.getExternalImports();
         for (BundleDescription.ImportPackage packageImport : imports) {
+            //find the packages that we are importing
             ExportedPackage[] exportedPackages = packageAdmin.getExportedPackages(packageImport.getName());
             if (exportedPackages!=null){
                 for (ExportedPackage exportedPackage : exportedPackages) {
@@ -606,33 +625,89 @@ public class BundleManagerPortlet extend
                     }
                 }
             }
+            
         }
+                
+        //TODO  the result set may contains 2 items which have the same package name but
different versions.
+        return importingPairs;
+    }
+
+    private Set<PackageBundlePair> getRequireBundlesImportingPairs(PackageAdmin packageAdmin,
Bundle bundle) {
+        
+        Set<PackageBundlePair> requireBundlesImportingPairs = new HashSet<PackageBundlePair>();
+        
+        BundleDescription description = new BundleDescription(bundle.getHeaders());
         
-        //TODO 1. sometimes, there might be same pairs in the result set.
-        //TODO 2. the result set may contains 2 items which have the same package name but
different versions.
+        List<BundleDescription.RequireBundle> requireBundles = description.getRequireBundle();
+        if (!requireBundles.isEmpty()) {
+
+            Map<String, VersionRange> requireBundlesMap = new HashMap<String, VersionRange>();
+
+            for (BundleDescription.RequireBundle requireBundle : requireBundles) {
+                requireBundlesMap.put(requireBundle.getName(), requireBundle.getVersionRange());
+            }
+
+            Set<String> requireBundleNames = requireBundlesMap.keySet();
+            for (Bundle b : bundle.getBundleContext().getBundles()) {
+                if (requireBundleNames.contains(b.getSymbolicName())
+                        && requireBundlesMap.get(b.getSymbolicName()).isInRange(b.getVersion()))
{
+
+                    // find the packages that importing from the require bundle
+                    ExportedPackage[] exportedPackages = packageAdmin.getExportedPackages(b);
+                    if (exportedPackages != null) {
+                        for (ExportedPackage exportedPackage : exportedPackages) {
+                            Bundle[] importingBundles = exportedPackage.getImportingBundles();
+                            if (importingBundles != null) {
+                                for (Bundle importingBundle : importingBundles) {
+                                    if (importingBundle == bundle) {
+                                        requireBundlesImportingPairs.add(new PackageBundlePair(exportedPackage,
b));
+                                    }
+                                }
+                            }
+                        }
+                    }
+
+                }
+
+            }
+        }
+        
+        return requireBundlesImportingPairs;
+    
+    }
+    
+    
+    private Set<PackageBundlePair> getDynamicImportingPairs(PackageAdmin packageAdmin,
Bundle bundle, Set<PackageBundlePair> explicitImportingPairs) {
+        BundleDescription description = new BundleDescription(bundle.getHeaders());
+        
+        Set<PackageBundlePair> dynamicImportingPairs = new HashSet<PackageBundlePair>();
         
         // handle dynamic wire via DynamicImport-Package
-//        if (!description.getDynamicImportPackage().isEmpty()) {
-//            for (Bundle b : bundle.getBundleContext().getBundles()) {
-//                ExportedPackage[] exports = packageAdmin.getExportedPackages(b);
-//                Bundle wiredBundle = getWiredBundle(bundle, exports);
-//                if (exports != null) {
-//                    for (ExportedPackage exportedPackage : exports) {
-//                        Bundle[] importingBundles = exportedPackage.getImportingBundles();
-//                        if (importingBundles != null) {
-//                            for (Bundle importingBundle : importingBundles) {
-//                                if (importingBundle == bundle) {
-//                                    pbPairs.put(exportedPackage, wiredBundle);
-//                                }
-//                            }
-//                        }
-//                    }
-//                }
-//              
-//            }
-//        }
+        if (!description.getDynamicImportPackage().isEmpty()) {
+            for (Bundle b : bundle.getBundleContext().getBundles()) {
+                
+                // find the packages that importing from the bundle
+                ExportedPackage[] exportedPackages = packageAdmin.getExportedPackages(b);
+                if (exportedPackages != null) {
+                    for (ExportedPackage exportedPackage : exportedPackages) {
+                        Bundle[] importingBundles = exportedPackage.getImportingBundles();
+                        if (importingBundles != null) {
+                            for (Bundle importingBundle : importingBundles) {
+                                if (importingBundle == bundle) {
+                                    PackageBundlePair pair = new PackageBundlePair(exportedPackage,
b);
+                                    if (!explicitImportingPairs.contains(pair)){
+                                        dynamicImportingPairs.add(pair);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                
+            }
+        }
         
-        return importingPairs;
+        return dynamicImportingPairs;
     }
     
     
@@ -678,13 +753,28 @@ public class BundleManagerPortlet extend
             }
 
             final PackageBundlePair other = (PackageBundlePair) obj;
-            if (this.exportedPackage != other.exportedPackage && (this.exportedPackage
== null || !this.exportedPackage.equals(other.exportedPackage))) {
-                return false;
+// when using the following, there still be same pairs in the set. Maybe the equal method
is not re-written.
+//            if (this.exportedPackage != other.exportedPackage && (this.exportedPackage
== null || !this.exportedPackage.equals(other.exportedPackage))) {
+//                return false;
+//            }
+//            if (this.bundle != other.bundle && (this.bundle == null || !this.bundle.equals(other.bundle)))
{
+//                return false;
+//            }
+            
+            if (this.exportedPackage != null && other.exportedPackage == null) return
false;
+            if (this.exportedPackage == null && other.exportedPackage != null) return
false;
+            if (this.exportedPackage != null && other.exportedPackage != null) {
+                if (this.exportedPackage.getName()!= other.exportedPackage.getName() || this.exportedPackage.getVersion()
!= other.exportedPackage.getVersion())
+                    return false;
             }
-            if (this.bundle != other.bundle && (this.bundle == null || !this.bundle.equals(other.bundle)))
{
-                return false;
+            
+            if (this.bundle != null && other.bundle == null) return false;
+            if (this.bundle == null && other.bundle != null) return false;
+            if (this.bundle != null && other.bundle != null) {
+                if (this.bundle.getSymbolicName()!= other.bundle.getSymbolicName() || this.bundle.getVersion()
!= other.bundle.getVersion())
+                    return false;
             }
-
+            
             return true;
             
         }
@@ -692,8 +782,14 @@ public class BundleManagerPortlet extend
         @Override
         public int hashCode() {
             int hash = 11;
-            hash = 17* hash + (exportedPackage != null ? exportedPackage.hashCode():0);
-            hash = 17 * hash + (bundle != null ? bundle.hashCode():0);
+// because we used exportedPackage.getName(); exportedPackage.getVersion();  bundle.getSymbolicName();bundle.getVersion()
+// to calculate equals(), we must use them to calculate hashCode()
+//            hash = 17 * hash + (exportedPackage != null ? exportedPackage.hashCode():0);
+//            hash = 17 * hash + (bundle != null ? bundle.hashCode():0);
+            hash = 17 * hash + (exportedPackage != null ? exportedPackage.getName().hashCode():0);
+            hash = 17 * hash + (exportedPackage != null ? exportedPackage.getVersion().hashCode():0);
+            hash = 17 * hash + (bundle != null ? bundle.getSymbolicName().hashCode():0);
+            hash = 17 * hash + (bundle != null ? bundle.getVersion().hashCode():0);
 
             return hash;
         }

Modified: geronimo/server/trunk/plugins/console/console-base-portlets/src/main/webapp/WEB-INF/view/bundlemanager/BundleManager.jsp
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/console/console-base-portlets/src/main/webapp/WEB-INF/view/bundlemanager/BundleManager.jsp?rev=1081278&r1=1081277&r2=1081278&view=diff
==============================================================================
--- geronimo/server/trunk/plugins/console/console-base-portlets/src/main/webapp/WEB-INF/view/bundlemanager/BundleManager.jsp
(original)
+++ geronimo/server/trunk/plugins/console/console-base-portlets/src/main/webapp/WEB-INF/view/bundlemanager/BundleManager.jsp
Mon Mar 14 08:08:19 2011
@@ -150,7 +150,7 @@ function uninstallPrompt(target, bundleI
         <th scope="col" width="150">Type</th>
         <th scope="col" width="100">State</th>
         <c:if test="${listTypeValue == 'blueprint'}" >
-            <th scope="col">blueprint</th>
+            <th scope="col" width="100">Blueprint State</th>
         </c:if>
         <c:if test="${listTypeValue != 'system' && listTypeValue != 'configuration'}"
>
             <th scope="col" width="80">Actions</th>

Modified: geronimo/server/trunk/plugins/console/console-base-portlets/src/main/webapp/WEB-INF/view/bundlemanager/ShowWiredBundles.jsp
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/console/console-base-portlets/src/main/webapp/WEB-INF/view/bundlemanager/ShowWiredBundles.jsp?rev=1081278&r1=1081277&r2=1081278&view=diff
==============================================================================
--- geronimo/server/trunk/plugins/console/console-base-portlets/src/main/webapp/WEB-INF/view/bundlemanager/ShowWiredBundles.jsp
(original)
+++ geronimo/server/trunk/plugins/console/console-base-portlets/src/main/webapp/WEB-INF/view/bundlemanager/ShowWiredBundles.jsp
Mon Mar 14 08:08:19 2011
@@ -46,7 +46,10 @@
     </tr>
 </table>
 <br/>
+<!-- ################## Package Perspective ################### -->
 <c:if test="${perspectiveTypeValue == 'package'}" > 
+    <!--  Importing  -->
+    Import packages:<br/>
     <table width="100%" class="TableLine" summary="Wired Bundles">
         <tr class="DarkBackground">
             <th scope="col" width="40%">Importing Packages</th>   
@@ -78,6 +81,74 @@
         </c:forEach>
     </table>
     <br/>
+    <!-- Dynamic Importing -->
+    Dynamic import packages:<br/>
+    <table width="100%" class="TableLine" summary="Wired Bundles">
+        <tr class="DarkBackground">
+            <th scope="col" width="40%">Dynamic Importing Packages</th>   
+            <th scope="col" width="60%">From Bundles</th> 
+        </tr>
+        <c:set var="backgroundClass" value='MediumBackground'/>
+        <c:forEach var="dipp" items="${dynamicImportingPackagePerspectives}">
+          <c:choose>
+              <c:when test="${backgroundClass == 'MediumBackground'}" >
+                  <c:set var="backgroundClass" value='LightBackground'/>
+              </c:when>
+              <c:otherwise>
+                  <c:set var="backgroundClass" value='MediumBackground'/>
+              </c:otherwise>
+          </c:choose>
+          <tr>
+            <td class="${backgroundClass}">
+                ${dipp.packageInfo.packageName} (version=${dipp.packageInfo.packageVersion})
+            </td>
+            <td class="${backgroundClass}">
+                <c:forEach var="info" items="${dipp.bundleInfos}">
+                    ${info.symbolicName} (id=${info.bundleId}) (version=${info.bundleVersion})
+                    <a href="<portlet:renderURL><portlet:param name='page' value='view_manifest'/><portlet:param
name='bundleId' value='${info.bundleId}'/></portlet:renderURL>"><img border="0"
src="<%=request.getContextPath()%>/images/icon_mf.png" title="View Manifest" style="vertical-align:middle"/></a>
+                    <a href="<portlet:renderURL><portlet:param name='page' value='view_wired_bundles'/><portlet:param
name='bundleId' value='${info.bundleId}'/></portlet:renderURL>"><img border="0"
src="<%=request.getContextPath()%>/images/icon_wb.png" title="View Wired Bundles" style="vertical-align:middle"/></a>
+                    <br/>
+                </c:forEach>
+            </td>
+          </tr>
+        </c:forEach>
+    </table>
+    <br/>
+    <!-- Require Bundles -->
+    Import packages from the require bundles:<br/>
+    <table width="100%" class="TableLine" summary="Wired Bundles">
+        <tr class="DarkBackground">
+            <th scope="col" width="40%">Importing Packages</th>   
+            <th scope="col" width="60%">From the Require Bundles</th> 
+        </tr>
+        <c:set var="backgroundClass" value='MediumBackground'/>
+        <c:forEach var="rbipp" items="${requireBundlesImportingPackagePerspectives}">
+          <c:choose>
+              <c:when test="${backgroundClass == 'MediumBackground'}" >
+                  <c:set var="backgroundClass" value='LightBackground'/>
+              </c:when>
+              <c:otherwise>
+                  <c:set var="backgroundClass" value='MediumBackground'/>
+              </c:otherwise>
+          </c:choose>
+          <tr>
+            <td class="${backgroundClass}">
+                ${rbipp.packageInfo.packageName} (version=${rbipp.packageInfo.packageVersion})
+            </td>
+            <td class="${backgroundClass}">
+                <c:forEach var="info" items="${rbipp.bundleInfos}">
+                    ${info.symbolicName} (id=${info.bundleId}) (version=${info.bundleVersion})
+                    <a href="<portlet:renderURL><portlet:param name='page' value='view_manifest'/><portlet:param
name='bundleId' value='${info.bundleId}'/></portlet:renderURL>"><img border="0"
src="<%=request.getContextPath()%>/images/icon_mf.png" title="View Manifest" style="vertical-align:middle"/></a>
+                    <a href="<portlet:renderURL><portlet:param name='page' value='view_wired_bundles'/><portlet:param
name='bundleId' value='${info.bundleId}'/></portlet:renderURL>"><img border="0"
src="<%=request.getContextPath()%>/images/icon_wb.png" title="View Wired Bundles" style="vertical-align:middle"/></a>
+                    <br/>
+                </c:forEach>
+            </td>
+          </tr>
+        </c:forEach>
+    </table>
+    <br/>
+    <!-- Exporting -->
+    Export packages:<br/>
     <table width="100%" class="TableLine" summary="Wired Bundles">
         <tr class="DarkBackground">
             <th scope="col" width="40%">Exporting Packages</th>   
@@ -109,8 +180,10 @@
         </c:forEach>
     </table>
 </c:if>
-
+<!-- ################## Bundle Perspective ################### -->
 <c:if test="${perspectiveTypeValue == 'bundle'}" > 
+    <!--  Importing  -->
+    Import packages:<br/>
     <table width="100%" class="TableLine" summary="Wired Bundles">
         <tr class="DarkBackground">
             <th scope="col" width="40%">Importing Packages</th>   
@@ -141,6 +214,72 @@
         </c:forEach>
     </table>
     <br/>
+    <!-- Dynamic Importing -->
+    Dynamic import packages:<br/>
+    <table width="100%" class="TableLine" summary="Wired Bundles">
+        <tr class="DarkBackground">
+            <th scope="col" width="40%">Dynamic Importing Packages</th>   
+            <th scope="col" width="60%">From Bundles</th> 
+        </tr>
+        <c:set var="backgroundClass" value='MediumBackground'/>
+        <c:forEach var="dibp" items="${dynamicImportingBundlePerspectives}">
+          <c:choose>
+              <c:when test="${backgroundClass == 'MediumBackground'}" >
+                  <c:set var="backgroundClass" value='LightBackground'/>
+              </c:when>
+              <c:otherwise>
+                  <c:set var="backgroundClass" value='MediumBackground'/>
+              </c:otherwise>
+          </c:choose>
+          <tr>
+            <td class="${backgroundClass}">
+                <c:forEach var="info" items="${dibp.packageInfos}">
+                    ${info.packageName} (version=${info.packageVersion}) <br/>
+                </c:forEach>
+            </td>
+            <td class="${backgroundClass}">
+                ${dibp.bundleInfo.symbolicName} (id=${dibp.bundleInfo.bundleId}) (version=${dibp.bundleInfo.bundleVersion})
+                <a href="<portlet:renderURL><portlet:param name='page' value='view_manifest'/><portlet:param
name='bundleId' value='${dibp.bundleInfo.bundleId}'/></portlet:renderURL>"><img
border="0" src="<%=request.getContextPath()%>/images/icon_mf.png" title="View Manifest"
style="vertical-align:middle"/></a>
+                <a href="<portlet:renderURL><portlet:param name='page' value='view_wired_bundles'/><portlet:param
name='bundleId' value='${dibp.bundleInfo.bundleId}'/></portlet:renderURL>"><img
border="0" src="<%=request.getContextPath()%>/images/icon_wb.png" title="View Wired
Bundles" style="vertical-align:middle"/></a>
+            </td>
+          </tr>
+        </c:forEach>
+    </table>
+    <br/>
+    <!-- Require Bundles -->
+    Import packages from the require bundles:<br/>
+    <table width="100%" class="TableLine" summary="Wired Bundles">
+        <tr class="DarkBackground">
+            <th scope="col" width="40%">Importing Packages</th>   
+            <th scope="col" width="60%">From the Require Bundles</th> 
+        </tr>
+        <c:set var="backgroundClass" value='MediumBackground'/>
+        <c:forEach var="rbibp" items="${requireBundlesImportingBundlePerspectives}">
+          <c:choose>
+              <c:when test="${backgroundClass == 'MediumBackground'}" >
+                  <c:set var="backgroundClass" value='LightBackground'/>
+              </c:when>
+              <c:otherwise>
+                  <c:set var="backgroundClass" value='MediumBackground'/>
+              </c:otherwise>
+          </c:choose>
+          <tr>
+            <td class="${backgroundClass}">
+                <c:forEach var="info" items="${rbibp.packageInfos}">
+                    ${info.packageName} (version=${info.packageVersion}) <br/>
+                </c:forEach>
+            </td>
+            <td class="${backgroundClass}">
+                ${rbibp.bundleInfo.symbolicName} (id=${rbibp.bundleInfo.bundleId}) (version=${rbibp.bundleInfo.bundleVersion})
+                <a href="<portlet:renderURL><portlet:param name='page' value='view_manifest'/><portlet:param
name='bundleId' value='${rbibp.bundleInfo.bundleId}'/></portlet:renderURL>"><img
border="0" src="<%=request.getContextPath()%>/images/icon_mf.png" title="View Manifest"
style="vertical-align:middle"/></a>
+                <a href="<portlet:renderURL><portlet:param name='page' value='view_wired_bundles'/><portlet:param
name='bundleId' value='${rbibp.bundleInfo.bundleId}'/></portlet:renderURL>"><img
border="0" src="<%=request.getContextPath()%>/images/icon_wb.png" title="View Wired
Bundles" style="vertical-align:middle"/></a>
+            </td>
+          </tr>
+        </c:forEach>
+    </table>
+    <br/>
+    <!-- Exporting -->
+    Export packages:<br/>
     <table width="100%" class="TableLine" summary="Wired Bundles">
         <tr class="DarkBackground">
             <th scope="col" width="40%">Exporting Packages</th>   



Mime
View raw message