You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2023/09/09 12:46:33 UTC
[felix-dev] branch master updated: FELIX-6652 : Remove deprecated rendering attributes
This is an automated email from the ASF dual-hosted git repository.
cziegeler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/felix-dev.git
The following commit(s) were added to refs/heads/master by this push:
new 39668e8fa9 FELIX-6652 : Remove deprecated rendering attributes
39668e8fa9 is described below
commit 39668e8fa9d475c46e39e0be2be5976aec1bc553
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Sat Sep 9 14:46:24 2023 +0200
FELIX-6652 : Remove deprecated rendering attributes
---
.../felix/webconsole/AbstractWebConsolePlugin.java | 300 ++-------------------
.../webconsole/internal/NavigationRenderer.java | 201 ++++++++++++++
.../org/apache/felix/webconsole/internal/Util.java | 28 ++
.../servlet/AbstractOsgiManagerPlugin.java | 6 +
.../internal/servlet/AbstractPluginAdapter.java | 215 +--------------
.../webconsole/internal/servlet/OsgiManager.java | 34 +--
.../felix/webconsole/servlet/AbstractServlet.java | 30 +--
7 files changed, 264 insertions(+), 550 deletions(-)
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java b/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java
index e66125b517..b16001433e 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java
@@ -21,30 +21,24 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
-import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLConnection;
-import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.util.Iterator;
-import java.util.Locale;
import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.felix.webconsole.internal.NavigationRenderer;
import org.apache.felix.webconsole.internal.Util;
-import org.apache.felix.webconsole.internal.servlet.OsgiManager;
+import org.apache.felix.webconsole.internal.servlet.AbstractOsgiManagerPlugin;
import org.apache.felix.webconsole.servlet.RequestVariableResolver;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -108,16 +102,6 @@ public abstract class AbstractWebConsolePlugin extends HttpServlet {
*/
public static final String GET_RESOURCE_METHOD_NAME = "getResource";
- /**
- * The header fragment read from the templates/main_header.html file
- */
- private static String HEADER;
-
- /**
- * The footer fragment read from the templates/main_footer.html file
- */
- private static String FOOTER;
-
/**
* The reference to the getResource method provided by the
* {@link #getResourceProvider()}. This is <code>null</code> if there is
@@ -617,7 +601,7 @@ public abstract class AbstractWebConsolePlugin extends HttpServlet {
r.put("brand.product.img", toUrl( BRANDING_PLUGIN.getProductImage(), appRoot ));
r.put("brand.favicon", toUrl( BRANDING_PLUGIN.getFavIcon(), appRoot ));
r.put("brand.css", toUrl( BRANDING_PLUGIN.getMainStyleSheet(), appRoot ));
- pw.println( getHeader() );
+ pw.println( NavigationRenderer.HEADER );
return pw;
}
@@ -630,118 +614,17 @@ public abstract class AbstractWebConsolePlugin extends HttpServlet {
* @param pw the writer, where the HTML data is rendered
*/
@SuppressWarnings({ "rawtypes" })
- protected void renderTopNavigation( HttpServletRequest request, PrintWriter pw )
- {
- // assume pathInfo to not be null, else this would not be called
- String current = request.getPathInfo();
- int slash = current.indexOf( "/", 1 );
- if ( slash < 0 )
- {
- slash = current.length();
- }
- current = current.substring( 1, slash );
-
- String appRoot = ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );
-
- Map menuMap = ( Map ) request.getAttribute( OsgiManager.ATTR_LABEL_MAP_CATEGORIZED );
- this.renderMenu( menuMap, appRoot, pw );
-
- // render lang-box
- Map langMap = (Map) request.getAttribute(WebConsoleConstants.ATTR_LANG_MAP);
- if (null != langMap && !langMap.isEmpty())
- {
- // determine the currently selected locale from the request and fail-back
- // to the default locale if not set
- // if locale is missing in locale map, the default 'en' locale is used
- Locale reqLocale = request.getLocale();
- String locale = null != reqLocale ? reqLocale.getLanguage()
- : Locale.getDefault().getLanguage();
- if (!langMap.containsKey(locale))
- {
- locale = Locale.getDefault().getLanguage();
- }
- if (!langMap.containsKey(locale))
- {
- locale = "en";
- }
-
- pw.println("<div id='langSelect'>");
- pw.println(" <span>");
- printLocaleElement(pw, appRoot, locale, langMap.get(locale));
- pw.println(" </span>");
- pw.println(" <span class='flags ui-helper-hidden'>");
- for (Iterator li = langMap.keySet().iterator(); li.hasNext();)
- {
- // <img src="us.gif" alt="en" title="English"/>
- final Object l = li.next();
- if (!l.equals(locale))
- {
- printLocaleElement(pw, appRoot, l, langMap.get(l));
- }
- }
-
- pw.println(" </span>");
- pw.println("</div>");
- }
- }
-
-
- @SuppressWarnings({ "rawtypes" })
- protected void renderMenu( Map menuMap, String appRoot, PrintWriter pw )
- {
- if ( menuMap != null )
- {
- SortedMap categoryMap = sortMenuCategoryMap( menuMap, appRoot );
- pw.println( "<ul id=\"navmenu\">" );
- renderSubmenu( categoryMap, appRoot, pw, 0 );
- pw.println("<li class=\"logoutButton navMenuItem-0\">");
- pw.println("<a href=\"" + appRoot + "/logout\">${logout}</a>");
- pw.println("</li>");
- pw.println( "</ul>" );
- }
- }
-
+ protected void renderTopNavigation(final HttpServletRequest request, final PrintWriter pw ) {
+ final String appRoot = ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );
+ final Map menuMap = ( Map ) request.getAttribute( AbstractOsgiManagerPlugin.ATTR_LABEL_MAP_CATEGORIZED );
+ final Map langMap = (Map) request.getAttribute(WebConsoleConstants.ATTR_LANG_MAP);
- @SuppressWarnings({ "rawtypes" })
- private void renderMenu( Map menuMap, String appRoot, PrintWriter pw, int level )
- {
- pw.println( "<ul class=\"navMenuLevel-" + level + "\">" );
- renderSubmenu( menuMap, appRoot, pw, level );
- pw.println( "</ul>" );
+ NavigationRenderer.renderTopNavigation(pw, appRoot, menuMap, langMap, request.getLocale());
}
-
@SuppressWarnings({ "rawtypes" })
- private void renderSubmenu( Map menuMap, String appRoot, PrintWriter pw, int level )
- {
- String liStyleClass = " class=\"navMenuItem-" + level + "\"";
- Iterator itr = menuMap.keySet().iterator();
- while ( itr.hasNext() )
- {
- String key = ( String ) itr.next();
- MenuItem menuItem = ( MenuItem ) menuMap.get( key );
- pw.println( "<li" + liStyleClass + ">" + menuItem.getLink() );
- Map subMenu = menuItem.getSubMenu();
- if ( subMenu != null )
- {
- renderMenu( subMenu, appRoot, pw, level + 1 );
- }
- pw.println( "</li>" );
- }
- }
-
-
- private static final void printLocaleElement( PrintWriter pw, String appRoot, Object langCode, Object langName )
- {
- pw.print(" <img src='");
- pw.print(appRoot);
- pw.print("/res/flags/");
- pw.print(langCode);
- pw.print(".gif' alt='");
- pw.print(langCode);
- pw.print("' title='");
- pw.print(langName);
- pw.println("'/>");
+ protected void renderMenu(final Map menuMap, final String appRoot, final PrintWriter pw ) {
+ throw new UnsupportedOperationException();
}
/**
@@ -750,12 +633,10 @@ public abstract class AbstractWebConsolePlugin extends HttpServlet {
* @param pw the writer, where the HTML data is rendered
* @see #startResponse(HttpServletRequest, HttpServletResponse)
*/
- protected void endResponse( PrintWriter pw )
- {
- pw.println(getFooter());
+ protected void endResponse( PrintWriter pw ) {
+ pw.println(NavigationRenderer.FOOTER);
}
-
/**
* An utility method, that is used to filter out simple parameter from file
* parameter when multipart transfer encoding is used.
@@ -843,36 +724,6 @@ public abstract class AbstractWebConsolePlugin extends HttpServlet {
// nothing to do
}
- private final String getHeader() {
- // MessageFormat pattern place holder
- // 0 main title (brand name)
- // 1 console plugin title
- // 2 application root path (ATTR_APP_ROOT)
- // 3 console plugin label (from the URI)
- // 4 branding favourite icon (BrandingPlugin.getFavIcon())
- // 5 branding main style sheet (BrandingPlugin.getMainStyleSheet())
- // 6 branding product URL (BrandingPlugin.getProductURL())
- // 7 branding product name (BrandingPlugin.getProductName())
- // 8 branding product image (BrandingPlugin.getProductImage())
- // 9 additional HTML code to be inserted into the <head> section
- // (for example plugin provided CSS links)
- if ( HEADER == null )
- {
- HEADER = readTemplateFile( AbstractWebConsolePlugin.class, "/templates/main_header.html" );
- }
- return HEADER;
- }
-
-
- private final String getFooter()
- {
- if ( FOOTER == null )
- {
- FOOTER = readTemplateFile( AbstractWebConsolePlugin.class, "/templates/main_footer.html" );
- }
- return FOOTER;
- }
-
/**
* Reads the <code>templateFile</code> as a resource through the class
* loader of this class converting the binary data into a string using
@@ -892,43 +743,14 @@ public abstract class AbstractWebConsolePlugin extends HttpServlet {
* exception thrown as its cause.
*/
protected final String readTemplateFile( final String templateFile ) {
- return readTemplateFile( getClass(), templateFile );
- }
-
- private final String readTemplateFile( final Class<?> clazz, final String templateFile) {
-
- try(InputStream templateStream = clazz.getResourceAsStream( templateFile )) {
- if ( templateStream != null ) {
- try ( final StringWriter w = new StringWriter()) {
- final byte[] buf = new byte[2048];
- int l;
- while ( ( l = templateStream.read(buf)) > 0 ) {
- w.write(new String(buf, 0, l, StandardCharsets.UTF_8));
- }
- String str = w.toString();
- switch ( str.charAt(0) )
- { // skip BOM
- case 0xFEFF: // UTF-16/UTF-32, big-endian
- case 0xFFFE: // UTF-16, little-endian
- case 0xEFBB: // UTF-8
- return str.substring(1);
- }
- return str;
- }
- }
- }
- catch ( IOException e )
- {
- // don't use new Exception(message, cause) because cause is 1.4+
- throw new RuntimeException( "readTemplateFile: Error loading " + templateFile + ": " + e );
+ try {
+ return Util.readTemplateFile( getClass(), templateFile );
+ } catch (final IOException e) {
+ Util.LOGGER.error("readTemplateFile: File '{}' not found through class {}", templateFile, getClass() );
+ return "";
}
-
- // template file does not exist, return an empty string
- log( LogService.LOG_ERROR, "readTemplateFile: File '" + templateFile + "' not found through class " + clazz );
- return "";
}
-
private final String getCssLinks( final String appRoot )
{
// get the CSS references and return nothing if there are none
@@ -972,50 +794,7 @@ public abstract class AbstractWebConsolePlugin extends HttpServlet {
return url;
}
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private SortedMap sortMenuCategoryMap( Map map, String appRoot )
- {
- SortedMap sortedMap = new TreeMap<>( String.CASE_INSENSITIVE_ORDER );
- Iterator keys = map.keySet().iterator();
- while ( keys.hasNext() )
- {
- String key = ( String ) keys.next();
- if ( key.startsWith( "category." ) )
- {
- SortedMap categoryMap = sortMenuCategoryMap( ( Map ) map.get( key ), appRoot );
- String title = key.substring( key.indexOf( '.' ) + 1 );
- if ( sortedMap.containsKey( title ) )
- {
- ( ( MenuItem ) sortedMap.get( title ) ).setSubMenu( categoryMap );
- }
- else
- {
- String link = "<a href=\"#\">" + title + "</a>";
- MenuItem menuItem = new MenuItem( link, categoryMap );
- sortedMap.put( title, menuItem );
- }
- }
- else
- {
- String title = ( String ) map.get( key );
- String link = "<a href=\"" + appRoot + "/" + key + "\">" + title + "</a>";
- if ( sortedMap.containsKey( title ) )
- {
- ( ( MenuItem ) sortedMap.get( title ) ).setLink( link );
- }
- else
- {
- MenuItem menuItem = new MenuItem( link );
- sortedMap.put( title, menuItem );
- }
- }
-
- }
- return sortedMap;
- }
-
- /**
+ /**
* Returns the {@link RequestVariableResolver} for the given request.
* <p>
* The resolver is added to the request attributes via the web console main
@@ -1035,47 +814,4 @@ public abstract class AbstractWebConsolePlugin extends HttpServlet {
public RequestVariableResolver getVariableResolver( final ServletRequest request) {
return (RequestVariableResolver) request.getAttribute( RequestVariableResolver.REQUEST_ATTRIBUTE );
}
-
- @SuppressWarnings({ "rawtypes" })
- private static class MenuItem
- {
- private String link;
- private Map subMenu;
-
- public MenuItem( String link )
- {
- this.link = link;
- }
-
- public MenuItem( String link, Map subMenu )
- {
- super();
- this.link = link;
- this.subMenu = subMenu;
- }
-
-
- public String getLink()
- {
- return link;
- }
-
-
- public void setLink( String link )
- {
- this.link = link;
- }
-
-
- public Map getSubMenu()
- {
- return subMenu;
- }
-
-
- public void setSubMenu( Map subMenu )
- {
- this.subMenu = subMenu;
- }
- }
}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/NavigationRenderer.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/NavigationRenderer.java
new file mode 100644
index 0000000000..39d6bf4739
--- /dev/null
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/NavigationRenderer.java
@@ -0,0 +1,201 @@
+/*
+ * 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.felix.webconsole.internal;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+public class NavigationRenderer {
+
+ /**
+ * The header fragment read from the templates/main_header.html file
+ */
+ public static final String HEADER;
+
+ /**
+ * The footer fragment read from the templates/main_footer.html file
+ */
+ public static final String FOOTER;
+
+ static {
+ try {
+ HEADER = Util.readTemplateFile( NavigationRenderer.class, "/templates/main_header.html" );
+ FOOTER = Util.readTemplateFile(NavigationRenderer.class, "/templates/main_footer.html" );
+ } catch ( final IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ }
+
+ /**
+ * This method is called to generate the top level links with the available plug-ins.
+ *
+ * @param request the HTTP request coming from the user
+ * @param pw the writer, where the HTML data is rendered
+ */
+ @SuppressWarnings({ "rawtypes" })
+ public static void renderTopNavigation( final PrintWriter pw, final String appRoot, final Map menuMap, final Map langMap, final Locale reqLocale) {
+ renderMenu( menuMap, appRoot, pw );
+
+ // render lang-box
+ if (null != langMap && !langMap.isEmpty()) {
+ // determine the currently selected locale from the request and fail-back
+ // to the default locale if not set
+ // if locale is missing in locale map, the default 'en' locale is used
+ String locale = null != reqLocale ? reqLocale.getLanguage() : Locale.getDefault().getLanguage();
+ if (!langMap.containsKey(locale)) {
+ locale = Locale.getDefault().getLanguage();
+ }
+ if (!langMap.containsKey(locale)) {
+ locale = "en";
+ }
+
+ pw.println("<div id='langSelect'>");
+ pw.println(" <span>");
+ printLocaleElement(pw, appRoot, locale, langMap.get(locale));
+ pw.println(" </span>");
+ pw.println(" <span class='flags ui-helper-hidden'>");
+ for (Iterator li = langMap.keySet().iterator(); li.hasNext();) {
+ // <img src="us.gif" alt="en" title="English"/>
+ final Object l = li.next();
+ if (!l.equals(locale)) {
+ printLocaleElement(pw, appRoot, l, langMap.get(l));
+ }
+ }
+
+ pw.println(" </span>");
+ pw.println("</div>");
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private static SortedMap sortMenuCategoryMap(final Map map, final String appRoot ) {
+ final SortedMap sortedMap = new TreeMap<>( String.CASE_INSENSITIVE_ORDER );
+ final Iterator keys = map.keySet().iterator();
+ while ( keys.hasNext() ) {
+ final String key = ( String ) keys.next();
+ if ( key.startsWith( "category." ) ) {
+ final SortedMap categoryMap = sortMenuCategoryMap( ( Map ) map.get( key ), appRoot );
+ final String title = key.substring( key.indexOf( '.' ) + 1 );
+ if ( sortedMap.containsKey( title ) ) {
+ ( ( MenuItem ) sortedMap.get( title ) ).setSubMenu( categoryMap );
+ } else {
+ final String link = "<a href=\"#\">" + title + "</a>";
+ final MenuItem menuItem = new MenuItem( link, categoryMap );
+ sortedMap.put( title, menuItem );
+ }
+ } else {
+ final String title = ( String ) map.get( key );
+ final String link = "<a href=\"" + appRoot + "/" + key + "\">" + title + "</a>";
+ if ( sortedMap.containsKey( title ) ) {
+ ( ( MenuItem ) sortedMap.get( title ) ).setLink( link );
+ } else {
+ final MenuItem menuItem = new MenuItem( link );
+ sortedMap.put( title, menuItem );
+ }
+ }
+ }
+ return sortedMap;
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ private static void renderMenu(final Map menuMap, final String appRoot, final PrintWriter pw ) {
+ if ( menuMap != null ) {
+ final SortedMap categoryMap = sortMenuCategoryMap( menuMap, appRoot );
+ pw.println( "<ul id=\"navmenu\">" );
+ renderSubmenu( categoryMap, appRoot, pw, 0 );
+ pw.println("<li class=\"logoutButton navMenuItem-0\">");
+ pw.println("<a href=\"" + appRoot + "/logout\">${logout}</a>");
+ pw.println("</li>");
+ pw.println( "</ul>" );
+ }
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ private static void renderMenu(final Map menuMap, final String appRoot, final PrintWriter pw, final int level ) {
+ pw.println( "<ul class=\"navMenuLevel-" + level + "\">" );
+ renderSubmenu( menuMap, appRoot, pw, level );
+ pw.println( "</ul>" );
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ private static void renderSubmenu(final Map menuMap, final String appRoot, final PrintWriter pw, final int level ) {
+ String liStyleClass = " class=\"navMenuItem-" + level + "\"";
+ Iterator itr = menuMap.keySet().iterator();
+ while ( itr.hasNext() ) {
+ String key = ( String ) itr.next();
+ MenuItem menuItem = ( MenuItem ) menuMap.get( key );
+ pw.println( "<li" + liStyleClass + ">" + menuItem.getLink() );
+ Map subMenu = menuItem.getSubMenu();
+ if ( subMenu != null ) {
+ renderMenu( subMenu, appRoot, pw, level + 1 );
+ }
+ pw.println( "</li>" );
+ }
+ }
+
+ private static final void printLocaleElement(final PrintWriter pw, final String appRoot, final Object langCode, final Object langName ) {
+ pw.print(" <img src='");
+ pw.print(appRoot);
+ pw.print("/res/flags/");
+ pw.print(langCode);
+ pw.print(".gif' alt='");
+ pw.print(langCode);
+ pw.print("' title='");
+ pw.print(langName);
+ pw.println("'/>");
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ private static class MenuItem {
+
+ private String link;
+ private Map subMenu;
+
+ public MenuItem(final String link ) {
+ this.link = link;
+ }
+
+ public MenuItem(final String link, final Map subMenu ) {
+ this.link = link;
+ this.subMenu = subMenu;
+ }
+
+ public String getLink() {
+ return link;
+ }
+
+
+ public void setLink(final String link ) {
+ this.link = link;
+ }
+
+
+ public Map getSubMenu() {
+ return subMenu;
+ }
+
+
+ public void setSubMenu(final Map subMenu ) {
+ this.subMenu = subMenu;
+ }
+ }
+}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
index 4a7d9db1eb..8f990b4205 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
@@ -17,8 +17,12 @@
package org.apache.felix.webconsole.internal;
+import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
import java.lang.reflect.Array;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
@@ -341,6 +345,30 @@ public class Util {
ref.getBundle().getSymbolicName() + ":" + ref.getBundle().getVersion() + "(" + ref.getBundle().getBundleId() + ")";
}
+ public static final String readTemplateFile( final Class<?> clazz, final String templateFile) throws IOException {
+ try(final InputStream templateStream = clazz.getResourceAsStream( templateFile )) {
+ if ( templateStream != null ) {
+ try ( final StringWriter w = new StringWriter()) {
+ final byte[] buf = new byte[2048];
+ int l;
+ while ( ( l = templateStream.read(buf)) > 0 ) {
+ w.write(new String(buf, 0, l, StandardCharsets.UTF_8));
+ }
+ String str = w.toString();
+ switch ( str.charAt(0) ) { // skip BOM
+ case 0xFEFF: // UTF-16/UTF-32, big-endian
+ case 0xFFFE: // UTF-16, little-endian
+ case 0xEFBB: // UTF-8
+ return str.substring(1);
+ }
+ return str;
+ }
+ }
+ }
+
+ throw new FileNotFoundException("Template " + templateFile + " not found");
+ }
+
/** Logger for the webconsole */
public static final Logger LOGGER = LoggerFactory.getLogger("org.apache.felix.webconsole");
}
\ No newline at end of file
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/AbstractOsgiManagerPlugin.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/AbstractOsgiManagerPlugin.java
index 67b0983ba0..a3d46d68c0 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/AbstractOsgiManagerPlugin.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/AbstractOsgiManagerPlugin.java
@@ -44,6 +44,12 @@ public abstract class AbstractOsgiManagerPlugin extends AbstractServlet implemen
*/
public static final String ATTR_LABEL_MAP = "felix.webconsole.labelMap";
+ /**
+ * The name of the (internal) request attribute providing the categorized
+ * label map structure.
+ */
+ public static final String ATTR_LABEL_MAP_CATEGORIZED = AbstractOsgiManagerPlugin.ATTR_LABEL_MAP + ".categorized";
+
// used to obtain services. Structure is: service name -> ServiceTracker
private final Map<String, ServiceTracker<?, ?>> services = new HashMap<>();
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/AbstractPluginAdapter.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/AbstractPluginAdapter.java
index 205921759c..2bf18ca20f 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/AbstractPluginAdapter.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/AbstractPluginAdapter.java
@@ -20,16 +20,10 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
-import java.io.StringWriter;
import java.net.URL;
import java.net.URLConnection;
-import java.nio.charset.StandardCharsets;
-import java.util.Iterator;
-import java.util.Locale;
import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
+import org.apache.felix.webconsole.internal.NavigationRenderer;
import org.apache.felix.webconsole.servlet.RequestVariableResolver;
import org.apache.felix.webconsole.servlet.ServletConstants;
import org.apache.felix.webconsole.spi.BrandingPlugin;
@@ -51,16 +45,6 @@ public abstract class AbstractPluginAdapter extends HttpServlet {
/** Pseudo class version ID to keep the IDE quite. */
private static final long serialVersionUID = 1L;
- /**
- * The header fragment read from the templates/main_header.html file
- */
- private static final String HEADER = readTemplateFile( "/templates/main_header.html" );
-
- /**
- * The footer fragment read from the templates/main_footer.html file
- */
- private static final String FOOTER = readTemplateFile( "/templates/main_footer.html" );
-
private static volatile BrandingPlugin BRANDING_PLUGIN = new BrandingPluginImpl();
private volatile BundleContext bundleContext;
@@ -130,7 +114,7 @@ public abstract class AbstractPluginAdapter extends HttpServlet {
// detect if this is an html request
if ( isHtmlRequest(request) ) {
// start the html response, write the header, open body and main div
- PrintWriter pw = startResponse( request, response );
+ final PrintWriter pw = startResponse( request, response );
// render top navigation
renderTopNavigation( request, pw );
@@ -284,7 +268,7 @@ public abstract class AbstractPluginAdapter extends HttpServlet {
r.put("brand.product.img", toUrl( BRANDING_PLUGIN.getProductImage(), appRoot ));
r.put("brand.favicon", toUrl( BRANDING_PLUGIN.getFavIcon(), appRoot ));
r.put("brand.css", toUrl( BRANDING_PLUGIN.getMainStyleSheet(), appRoot ));
- pw.println( HEADER );
+ pw.println( NavigationRenderer.HEADER );
return pw;
}
@@ -297,102 +281,11 @@ public abstract class AbstractPluginAdapter extends HttpServlet {
*/
@SuppressWarnings({ "rawtypes" })
private void renderTopNavigation(final HttpServletRequest request, final PrintWriter pw ) {
- // assume pathInfo to not be null, else this would not be called
- String current = request.getPathInfo();
- int slash = current.indexOf( "/", 1 );
- if ( slash < 0 ) {
- slash = current.length();
- }
- current = current.substring( 1, slash );
-
final String appRoot = ( String ) request.getAttribute( ServletConstants.ATTR_APP_ROOT );
+ final Map menuMap = ( Map ) request.getAttribute( AbstractOsgiManagerPlugin.ATTR_LABEL_MAP_CATEGORIZED );
+ final Map langMap = (Map) request.getAttribute(ATTR_LANG_MAP);
- @SuppressWarnings("deprecation")
- final Map menuMap = ( Map ) request.getAttribute( OsgiManager.ATTR_LABEL_MAP_CATEGORIZED );
- this.renderMenu( menuMap, appRoot, pw );
-
- // render lang-box
- Map langMap = (Map) request.getAttribute(ATTR_LANG_MAP);
- if (null != langMap && !langMap.isEmpty()) {
- // determine the currently selected locale from the request and fail-back
- // to the default locale if not set
- // if locale is missing in locale map, the default 'en' locale is used
- Locale reqLocale = request.getLocale();
- String locale = null != reqLocale ? reqLocale.getLanguage()
- : Locale.getDefault().getLanguage();
- if (!langMap.containsKey(locale)) {
- locale = Locale.getDefault().getLanguage();
- }
- if (!langMap.containsKey(locale)) {
- locale = "en";
- }
-
- pw.println("<div id='langSelect'>");
- pw.println(" <span>");
- printLocaleElement(pw, appRoot, locale, langMap.get(locale));
- pw.println(" </span>");
- pw.println(" <span class='flags ui-helper-hidden'>");
- for (Iterator li = langMap.keySet().iterator(); li.hasNext();) {
- // <img src="us.gif" alt="en" title="English"/>
- final Object l = li.next();
- if (!l.equals(locale)) {
- printLocaleElement(pw, appRoot, l, langMap.get(l));
- }
- }
-
- pw.println(" </span>");
- pw.println("</div>");
- }
- }
-
- @SuppressWarnings({ "rawtypes" })
- private void renderMenu(final Map menuMap, final String appRoot, final PrintWriter pw ) {
- if ( menuMap != null ) {
- final SortedMap categoryMap = sortMenuCategoryMap( menuMap, appRoot );
- pw.println( "<ul id=\"navmenu\">" );
- renderSubmenu( categoryMap, appRoot, pw, 0 );
- pw.println("<li class=\"logoutButton navMenuItem-0\">");
- pw.println("<a href=\"" + appRoot + "/logout\">${logout}</a>");
- pw.println("</li>");
- pw.println( "</ul>" );
- }
- }
-
- @SuppressWarnings({ "rawtypes" })
- private void renderMenu(final Map menuMap, final String appRoot, final PrintWriter pw, final int level ) {
- pw.println( "<ul class=\"navMenuLevel-" + level + "\">" );
- renderSubmenu( menuMap, appRoot, pw, level );
- pw.println( "</ul>" );
- }
-
- @SuppressWarnings({ "rawtypes" })
- private void renderSubmenu(final Map menuMap, final String appRoot, final PrintWriter pw, final int level ) {
- String liStyleClass = " class=\"navMenuItem-" + level + "\"";
- Iterator itr = menuMap.keySet().iterator();
- while ( itr.hasNext() )
- {
- String key = ( String ) itr.next();
- MenuItem menuItem = ( MenuItem ) menuMap.get( key );
- pw.println( "<li" + liStyleClass + ">" + menuItem.getLink() );
- Map subMenu = menuItem.getSubMenu();
- if ( subMenu != null )
- {
- renderMenu( subMenu, appRoot, pw, level + 1 );
- }
- pw.println( "</li>" );
- }
- }
-
- private static final void printLocaleElement( PrintWriter pw, String appRoot, Object langCode, Object langName ) {
- pw.print(" <img src='");
- pw.print(appRoot);
- pw.print("/res/flags/");
- pw.print(langCode);
- pw.print(".gif' alt='");
- pw.print(langCode);
- pw.print("' title='");
- pw.print(langName);
- pw.println("'/>");
+ NavigationRenderer.renderTopNavigation(pw, appRoot, menuMap, langMap, request.getLocale());
}
/**
@@ -402,7 +295,7 @@ public abstract class AbstractPluginAdapter extends HttpServlet {
* @see #startResponse(HttpServletRequest, HttpServletResponse)
*/
private void endResponse( PrintWriter pw ) {
- pw.println(FOOTER);
+ pw.println(NavigationRenderer.FOOTER);
}
/**
@@ -422,35 +315,6 @@ public abstract class AbstractPluginAdapter extends HttpServlet {
}
}
- private static final String readTemplateFile( final String templateFile) {
- try(final InputStream templateStream = AbstractPluginAdapter.class.getResourceAsStream( templateFile )) {
- if ( templateStream != null ) {
- try ( final StringWriter w = new StringWriter()) {
- final byte[] buf = new byte[2048];
- int l;
- while ( ( l = templateStream.read(buf)) > 0 ) {
- w.write(new String(buf, 0, l, StandardCharsets.UTF_8));
- }
- String str = w.toString();
- switch ( str.charAt(0) )
- { // skip BOM
- case 0xFEFF: // UTF-16/UTF-32, big-endian
- case 0xFFFE: // UTF-16, little-endian
- case 0xEFBB: // UTF-8
- return str.substring(1);
- }
- return str;
- }
- }
- } catch (final IOException e ) {
- // don't use new Exception(message, cause) because cause is 1.4+
- throw new RuntimeException( "readTemplateFile: Error loading " + templateFile + ": " + e );
- }
-
- // template file does not exist, throw
- throw new RuntimeException("readTemplateFile: File '" + templateFile + "' not found in webconsole bundle");
- }
-
private final String getCssLinks( final String appRoot ) {
// get the CSS references and return nothing if there are none
if ( this.cssReferences == null || this.cssReferences.length == 0) {
@@ -487,36 +351,6 @@ public abstract class AbstractPluginAdapter extends HttpServlet {
return url;
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private SortedMap sortMenuCategoryMap(final Map map, final String appRoot ) {
- final SortedMap sortedMap = new TreeMap<>( String.CASE_INSENSITIVE_ORDER );
- final Iterator keys = map.keySet().iterator();
- while ( keys.hasNext() ) {
- final String key = ( String ) keys.next();
- if ( key.startsWith( "category." ) ) {
- final SortedMap categoryMap = sortMenuCategoryMap( ( Map ) map.get( key ), appRoot );
- final String title = key.substring( key.indexOf( '.' ) + 1 );
- if ( sortedMap.containsKey( title ) ) {
- ( ( MenuItem ) sortedMap.get( title ) ).setSubMenu( categoryMap );
- } else {
- final String link = "<a href=\"#\">" + title + "</a>";
- final MenuItem menuItem = new MenuItem( link, categoryMap );
- sortedMap.put( title, menuItem );
- }
- } else {
- final String title = ( String ) map.get( key );
- final String link = "<a href=\"" + appRoot + "/" + key + "\">" + title + "</a>";
- if ( sortedMap.containsKey( title ) ) {
- ( ( MenuItem ) sortedMap.get( title ) ).setLink( link );
- } else {
- final MenuItem menuItem = new MenuItem( link );
- sortedMap.put( title, menuItem );
- }
- }
- }
- return sortedMap;
- }
-
/**
* Get the variable resolver
* @param request The request
@@ -525,39 +359,4 @@ public abstract class AbstractPluginAdapter extends HttpServlet {
protected RequestVariableResolver getVariableResolver( final ServletRequest request) {
return (RequestVariableResolver) request.getAttribute( RequestVariableResolver.REQUEST_ATTRIBUTE );
}
-
- @SuppressWarnings({ "rawtypes" })
- private static class MenuItem {
-
- private String link;
- private Map subMenu;
-
- public MenuItem(final String link ) {
- this.link = link;
- }
-
- public MenuItem(final String link, final Map subMenu ) {
- this.link = link;
- this.subMenu = subMenu;
- }
-
- public String getLink() {
- return link;
- }
-
-
- public void setLink(final String link ) {
- this.link = link;
- }
-
-
- public Map getSubMenu() {
- return subMenu;
- }
-
-
- public void setSubMenu(final Map subMenu ) {
- this.subMenu = subMenu;
- }
- }
}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
index 845d4d0e52..966e588c44 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
@@ -81,34 +81,6 @@ public class OsgiManager extends HttpServlet {
/** Pseudo class version ID to keep the IDE quite. */
private static final long serialVersionUID = 1L;
- /**
- * Old name of the request attribute providing the root to the web console.
- * This attribute is no deprecated and replaced by
- * {@link ServletConstants#ATTR_APP_ROOT}.
- *
- * @deprecated use {@link ServletConstants#ATTR_APP_ROOT} instead
- */
- @Deprecated
- private static final String ATTR_APP_ROOT_OLD = OsgiManager.class.getName() + ".appRoot";
-
- /**
- * Old name of the request attribute providing the mappings from label to
- * page title. This attribute is now deprecated and replaced by
- * {@link AbstractOsgiManagerPlugin#ATTR_LABEL_MAP}.
- *
- * @deprecated use {@link AbstractOsgiManagerPlugin#ATTR_LABEL_MAP} instead
- */
- @Deprecated
- private static final String ATTR_LABEL_MAP_OLD = OsgiManager.class.getName() + ".labelMap";
-
- /**
- * The name of the (internal) request attribute providing the categorized
- * label map structure.
- * @deprecated use {@link AbstractOsgiManagerPlugin#ATTR_LABEL_MAP} instead
- */
- @Deprecated
- public static final String ATTR_LABEL_MAP_CATEGORIZED = AbstractOsgiManagerPlugin.ATTR_LABEL_MAP + ".categorized";
-
/**
* The name and value of a parameter which will prevent redirection to a
* render after the action has been executed (value is "_noredir_"). This
@@ -553,16 +525,12 @@ public class OsgiManager extends HttpServlet {
// the official request attributes
request.setAttribute(org.apache.felix.webconsole.WebConsoleConstants.ATTR_LANG_MAP, getLangMap());
request.setAttribute(AbstractOsgiManagerPlugin.ATTR_LABEL_MAP, flatLabelMap);
- request.setAttribute( ATTR_LABEL_MAP_CATEGORIZED, labelMap );
+ request.setAttribute(AbstractOsgiManagerPlugin.ATTR_LABEL_MAP_CATEGORIZED, labelMap );
final String appRoot = request.getContextPath().concat(request.getServletPath());
request.setAttribute(ServletConstants.ATTR_APP_ROOT, appRoot);
request.setAttribute(ServletConstants.ATTR_PLUGIN_ROOT, appRoot.concat(postfix));
request.setAttribute(ServletConstants.ATTR_CONFIGURATION, configuration);
- // deprecated request attributes
- request.setAttribute(ATTR_LABEL_MAP_OLD, flatLabelMap);
- request.setAttribute(ATTR_APP_ROOT_OLD, appRoot);
-
final RequestVariableResolver resolver = new org.apache.felix.webconsole.DefaultVariableResolver();
request.setAttribute(RequestVariableResolver.REQUEST_ATTRIBUTE, resolver);
resolver.put( RequestVariableResolver.KEY_APP_ROOT, (String) request.getAttribute( ServletConstants.ATTR_APP_ROOT ) );
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/servlet/AbstractServlet.java b/webconsole/src/main/java/org/apache/felix/webconsole/servlet/AbstractServlet.java
index 71a848f359..da36a50841 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/servlet/AbstractServlet.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/servlet/AbstractServlet.java
@@ -23,10 +23,10 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.StringWriter;
import java.net.URL;
import java.net.URLConnection;
-import java.nio.charset.StandardCharsets;
+
+import org.apache.felix.webconsole.internal.Util;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
@@ -192,31 +192,7 @@ public abstract class AbstractServlet extends HttpServlet {
* @throws IOException On any other error reading the template file
*/
protected final String readTemplateFile( final String templateFile ) throws IOException {
- return readTemplateFile( getClass(), templateFile );
- }
-
- private final String readTemplateFile( final Class<?> clazz, final String templateFile) throws IOException {
- try(final InputStream templateStream = clazz.getResourceAsStream( templateFile )) {
- if ( templateStream != null ) {
- try ( final StringWriter w = new StringWriter()) {
- final byte[] buf = new byte[2048];
- int l;
- while ( ( l = templateStream.read(buf)) > 0 ) {
- w.write(new String(buf, 0, l, StandardCharsets.UTF_8));
- }
- String str = w.toString();
- switch ( str.charAt(0) ) { // skip BOM
- case 0xFEFF: // UTF-16/UTF-32, big-endian
- case 0xFFFE: // UTF-16, little-endian
- case 0xEFBB: // UTF-8
- return str.substring(1);
- }
- return str;
- }
- }
- }
-
- throw new FileNotFoundException("Template " + templateFile + " not found");
+ return Util.readTemplateFile( getClass(), templateFile );
}
protected RequestVariableResolver getVariableResolver(final HttpServletRequest request) {