From 65f19055371fd37f2c8c7a03443b5bf87307f0c1 Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Sat, 18 Jan 2020 17:43:41 +0100 Subject: [PATCH 01/11] use one function to get the map --- .../listeners/AddResourcesListener.java | 160 ++++++++---------- 1 file changed, 73 insertions(+), 87 deletions(-) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index ed231380b..bef674b36 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -58,8 +58,8 @@ import net.bootsfaces.utils.BsfUtils; /** - * This class adds the resource needed by BootsFaces and ensures that they are - * loaded in the correct order. It replaces the former HeadListener. + * This class adds the resource needed by BootsFaces and ensures that they are loaded in the correct order. It replaces + * the former HeadListener. * * @author Stephan Rauh */ @@ -73,45 +73,39 @@ public class AddResourcesListener implements SystemEventListener { private static final String BASIC_JS_RESOURCE_KEY = "net.bootsfaces.listeners.AddResourcesListener.BasicJSResourceFiles"; /** - * Version of FontAwesome. By default, version 4.7.0 is used. If you specify the - * subfont ("solid", "regular", "light" or "brand"), the version number is - * automatically set to 5.2.0. + * Version of FontAwesome. By default, version 4.7.0 is used. If you specify the subfont ("solid", "regular", + * "light" or "brand"), the version number is automatically set to 5.2.0. */ private static final String FONTAWESOME_VERSION = "net.bootsfaces.listeners.AddResourcesListener.FontAwesomeVersion"; /** - * List of components using a non-default version of FontAwesome. Needed to - * detect whether FontAwesome 4 (the default version) needs to be imported or - * not. + * List of components using a non-default version of FontAwesome. Needed to detect whether FontAwesome 4 (the + * default version) needs to be imported or not. */ private static final String FONTAWESOME_NEW_VERSION = "net.bootsfaces.listeners.AddResourcesListener.FontAwesomeNewVersion"; /** - * This entry of the view map is set to true if there's at least one Fontawesome - * icon + * This entry of the view map is set to true if there's at least one Fontawesome icon */ private static final String FONTAWESOME_USED = "net.bootsfaces.listeners.AddResourcesListener.FontAwesomeIsUsed"; /** - * Components can request JS resources by registering them in the ViewMap, using - * the RESOURCE_KEY. + * Components can request JS resources by registering them in the ViewMap, using the RESOURCE_KEY. */ private static final String RESOURCE_KEY = "net.bootsfaces.listeners.AddResourcesListener.ResourceFiles"; /** - * Components can request themed CSS resources by registering them in the - * ViewMap, using the THEME_RESOURCE_KEY. + * Components can request themed CSS resources by registering them in the ViewMap, using the THEME_RESOURCE_KEY. */ private static final String THEME_RESOURCE_KEY = "net.bootsfaces.listeners.AddResourcesListener.ThemedResourceFiles"; /** - * Components can request extended CSS resources by registering them in the - * ViewMap, using the EXT_RESOURCE_KEY. + * Components can request extended CSS resources by registering them in the ViewMap, using the EXT_RESOURCE_KEY. */ private static final String EXT_RESOURCE_KEY = "net.bootsfaces.listeners.AddResourcesListener.ExtResourceFiles"; private static final String SCRIPT_RENDERER = "javax.faces.resource.Script", - CSS_RENDERER = "javax.faces.resource.Stylesheet"; + CSS_RENDERER = "javax.faces.resource.Stylesheet"; static { LOGGER.info("This application is running on BootsFaces " + C.BSFVERSION + "-" + C.BSFRELEASE_STATUS); @@ -126,8 +120,7 @@ public boolean isListenerForSource(Object source) { } /** - * Trigger adding the resources if and only if the event has been fired by - * UIViewRoot. + * Trigger adding the resources if and only if the event has been fired by UIViewRoot. */ public void processEvent(SystemEvent event) throws AbortProcessingException { FacesContext context = FacesContext.getCurrentInstance(); @@ -142,19 +135,27 @@ public void processEvent(SystemEvent event) throws AbortProcessingException { } /** - * Check if there is almost one bootsfaces component in page. If yes, load the - * correct items. * - * To ensure that, it checks first the viewMap to find specific bootsfaces key. - * If it found nothing, it check for components that has as a resource lib, the - * "bsf" lib. + * @param root the UIViewRoot + * @return + */ + private static Map getViewMap(UIViewRoot root) { + Map viewMap = root.getViewMap(true); + return viewMap; + } + + /** + * Check if there is almost one bootsfaces component in page. If yes, load the correct items. + * + * To ensure that, it checks first the viewMap to find specific bootsfaces key. If it found nothing, it check + * for components that has as a resource lib, the "bsf" lib. * - * @param root the UIViewRoot + * @param root the UIViewRoot * @param context the faces context * @return */ private boolean ensureExistBootsfacesComponent(UIViewRoot root, FacesContext context) { - Map viewMap = root.getViewMap(); + Map viewMap = getViewMap(root); // check explicit js request if (viewMap.get(RESOURCE_KEY) != null) { @@ -177,11 +178,10 @@ private boolean ensureExistBootsfacesComponent(UIViewRoot root, FacesContext con } /** - * Check all components in page to find one that has as resource library the - * target library. I use this method to check existence of a BsF component - * because, at this level, the getComponentResource returns always null + * Check all components in page to find one that has as resource library the target library. I use this method + * to check existence of a BsF component because, at this level, the getComponentResource returns always null * - * @param parent the parent component + * @param parent the parent component * @param targetLib the lib to search * @return */ @@ -235,7 +235,7 @@ private void addMetaTags(UIViewRoot root, FacesContext context) { /** * Add the required CSS files and the FontAwesome CDN link. * - * @param root The UIViewRoot of the JSF tree. + * @param root The UIViewRoot of the JSF tree. * @param context The current FacesContext */ private void addCSS(UIViewRoot root, FacesContext context) { @@ -284,7 +284,7 @@ private void addCSS(UIViewRoot root, FacesContext context) { // 2) Font Awesome if (useCDNImportForFontAwesome) { InternalFALink output = new InternalFALink(); - Map viewMap = root.getViewMap(); + Map viewMap = getViewMap(root); if (viewMap.containsKey(FONTAWESOME_USED)) { String version = (String) viewMap.get(FONTAWESOME_VERSION); if (version != null) { @@ -360,7 +360,7 @@ private String loadTheme(UIViewRoot root, FacesContext context) { if (themeResource == null) { throw new FacesException("Error loading theme, cannot find \"" + "css/" + theme + "/" + filename - + "\" resource of \"" + C.BSF_LIBRARY + "\" library"); + + "\" resource of \"" + C.BSF_LIBRARY + "\" library"); } else { String name = "css/" + theme + "/" + filename; createAndAddComponent(root, context, CSS_RENDERER, name, C.BSF_LIBRARY); @@ -392,7 +392,7 @@ private String getTheme(FacesContext context) { /** * Add the required Javascript files and the FontAwesome CDN link. * - * @param root The UIViewRoot of the JSF tree. + * @param root The UIViewRoot of the JSF tree. * @param context The current FacesContext */ private void addJavascript(UIViewRoot root, FacesContext context) { @@ -442,7 +442,7 @@ private void addJavascript(UIViewRoot root, FacesContext context) { } private Map addMandatoryLibraries(UIViewRoot root, FacesContext context, boolean loadJQuery, - boolean loadJQueryUI) { + boolean loadJQueryUI) { /* * We used to check if a single component needs the bsf.js, jsf or jquery @@ -456,7 +456,7 @@ private Map addMandatoryLibraries(UIViewRoot root, FacesContext createAndAddComponent(root, context, SCRIPT_RENDERER, "jq/jquery.js", C.BSF_LIBRARY); } - Map viewMap = root.getViewMap(); + Map viewMap = getViewMap(root); @SuppressWarnings("unchecked") Map basicResourceMap = (Map) viewMap.get(BASIC_JS_RESOURCE_KEY); @@ -465,7 +465,7 @@ private Map addMandatoryLibraries(UIViewRoot root, FacesContext String file = entry.getValue(); String library = entry.getKey().substring(0, entry.getKey().length() - file.length() - 1); if (!"jq/jquery.js".equals(file) || !C.BSF_LIBRARY.equals(library) || !file.startsWith("jq/ui") - || loadJQueryUI) { + || loadJQueryUI) { createAndAddComponent(root, context, SCRIPT_RENDERER, file, library); } } @@ -479,7 +479,7 @@ private Map addMandatoryLibraries(UIViewRoot root, FacesContext String file = entry.getValue(); String library = entry.getKey().substring(0, entry.getKey().length() - file.length() - 1); if (!"jq/jquery.js".equals(file) || !C.BSF_LIBRARY.equals(library) || !file.startsWith("jq/ui") - || loadJQueryUI) { + || loadJQueryUI) { createAndAddComponent(root, context, SCRIPT_RENDERER, file, library); } } @@ -563,9 +563,7 @@ public static void addResourceIfNecessary(String url) { } public static void setFontAwesomeVersion(int version, Object uiComponent) { - FacesContext context = FacesContext.getCurrentInstance(); - UIViewRoot root = context.getViewRoot(); - Map viewMap = root.getViewMap(); + Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); if (version != 4) { @SuppressWarnings("unchecked") @@ -591,14 +589,12 @@ public static void setFontAwesomeVersion(int version, Object uiComponent) { } LOGGER.log(Level.FINER, "by setFontAwesomeVersion - viewMap(FONTAWESOME_VERSION) is {0}", - viewMap.get(FONTAWESOME_VERSION)); + viewMap.get(FONTAWESOME_VERSION)); } @SuppressWarnings("unchecked") public static void setNeedsFontsAwesome(Object uiComponent) { - FacesContext context = FacesContext.getCurrentInstance(); - UIViewRoot root = context.getViewRoot(); - Map viewMap = root.getViewMap(); + Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); ArrayList list = (ArrayList) viewMap.get(FONTAWESOME_USED); if (list == null) { list = new ArrayList(); @@ -608,9 +604,7 @@ public static void setNeedsFontsAwesome(Object uiComponent) { } private boolean needsFontAwesome4() { - FacesContext context = FacesContext.getCurrentInstance(); - UIViewRoot root = context.getViewRoot(); - Map viewMap = root.getViewMap(); + Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); @SuppressWarnings("unchecked") Map v5 = (Map) viewMap.get(FONTAWESOME_NEW_VERSION); @SuppressWarnings("unchecked") @@ -637,14 +631,12 @@ private boolean needsFontAwesome4() { } /** - * Remove duplicate resource files. For some reason, many resource files are - * added more than once, especially when AJAX is used. The method removes the - * duplicate files. + * Remove duplicate resource files. For some reason, many resource files are added more than once, especially + * when AJAX is used. The method removes the duplicate files. * - * TODO: Verify if the duplicate resource files are a bug of BootsFaces or of - * the Mojarra library itself. + * TODO: Verify if the duplicate resource files are a bug of BootsFaces or of the Mojarra library itself. * - * @param root The current UIViewRoot + * @param root The current UIViewRoot * @param context The current FacesContext */ private void removeDuplicateResources(UIViewRoot root, FacesContext context) { @@ -681,17 +673,16 @@ public int compare(UIComponent o1, UIComponent o2) { String library = (String) c.getAttributes().get("library"); String url = (String) c.getAttributes().get("url"); LOGGER.log(Level.FINER, "-1 " + c.getClientId() + " " + name + " " + library + " " + url + " " - + c.getClass().getSimpleName()); + + c.getClass().getSimpleName()); } } /** - * Remove Bootstrap CSS files (called if the context param - * "net.bootsfaces.get_bootstrap_from_cdn" is set). Only needed for Default - * Theme (Bootstrap) and custom themes, other themes would get default theme - * look and feel otherwise. + * Remove Bootstrap CSS files (called if the context param "net.bootsfaces.get_bootstrap_from_cdn" is set). Only + * needed for Default Theme (Bootstrap) and custom themes, other themes would get default theme look and feel + * otherwise. * - * @param root The current UIViewRoot + * @param root The current UIViewRoot * @param context The current FacesContext */ private void removeBootstrapResources(UIViewRoot root, FacesContext context) { @@ -703,7 +694,7 @@ private void removeBootstrapResources(UIViewRoot root, FacesContext context) { String library = (String) resource.getAttributes().get("library"); if (C.BSF_LIBRARY.equals(library) && name != null) { if (name.endsWith("bootstrap.min.css") || name.endsWith("bootstrap.css") - || name.endsWith("core.css") || name.endsWith("theme.css")) { + || name.endsWith("core.css") || name.endsWith("theme.css")) { resource.setInView(false); root.removeComponentResource(context, resource); } @@ -723,12 +714,11 @@ private void removeBootstrapResources(UIViewRoot root, FacesContext context) { } /** - * Make sure jQuery is loaded before jQueryUI, and that every other Javascript - * is loaded later. Also make sure that the BootsFaces resource files are loaded - * prior to other resource files, giving the developer the opportunity to - * overwrite a CSS or JS file. + * Make sure jQuery is loaded before jQueryUI, and that every other Javascript is loaded later. Also make sure + * that the BootsFaces resource files are loaded prior to other resource files, giving the developer the + * opportunity to overwrite a CSS or JS file. * - * @param root The current UIViewRoot + * @param root The current UIViewRoot * @param context The current FacesContext */ private void enforceCorrectLoadOrder(UIViewRoot root, FacesContext context) { @@ -809,11 +799,10 @@ private void enforceCorrectLoadOrder(UIViewRoot root, FacesContext context) { } /** - * Look whether a b:iconAwesome component is used. If so, the font-awesome.css - * is removed from the resource list because it's loaded from the CDN. + * Look whether a b:iconAwesome component is used. If so, the font-awesome.css is removed from the resource list + * because it's loaded from the CDN. * - * @return true, if the font-awesome.css is found in the resource list. Note the - * side effect of this method! + * @return true, if the font-awesome.css is found in the resource list. Note the side effect of this method! */ private boolean isFontAwesomeComponentUsedAndRemoveIt() { FacesContext fc = FacesContext.getCurrentInstance(); @@ -865,10 +854,9 @@ private UIComponent findHeader(UIViewRoot root) { } /** - * Registers a JS file that needs to be included in the header of the HTML file, - * but after jQuery and AngularJS. + * Registers a JS file that needs to be included in the header of the HTML file, but after jQuery and AngularJS. * - * @param library The name of the sub-folder of the resources folder. + * @param library The name of the sub-folder of the resources folder. * @param resource The name of the resource file within the library folder. */ public static void addResourceToHeadButAfterJQuery(String library, String resource) { @@ -876,10 +864,10 @@ public static void addResourceToHeadButAfterJQuery(String library, String resour } /** - * Registers a core JS file that needs to be included in the header of the HTML - * file, but after jQuery and AngularJS. + * Registers a core JS file that needs to be included in the header of the HTML file, but after jQuery and + * AngularJS. * - * @param library The name of the sub-folder of the resources folder. + * @param library The name of the sub-folder of the resources folder. * @param resource The name of the resource file within the library folder. */ public static void addBasicJSResource(String library, String resource) { @@ -887,8 +875,7 @@ public static void addBasicJSResource(String library, String resource) { } /** - * Registers a themed CSS file that needs to be included in the header of the - * HTML file. + * Registers a themed CSS file that needs to be included in the header of the HTML file. * * @param resource The name of the resource file within the library folder. */ @@ -907,8 +894,7 @@ public static void addThemedCSSResource(String resource) { } /** - * Registers a Extension CSS file that needs to be included in the header of the - * HTML file. + * Registers a Extension CSS file that needs to be included in the header of the HTML file. * * @param resource The name of the resource file within the library folder. */ @@ -950,12 +936,12 @@ private String evalELIfPossible(String expression) { } private void createAndAddComponent(UIViewRoot root, FacesContext context, String rendererType, String name, - String library) { + String library) { createAndAddComponent(root, context, rendererType, name, library, null); } private void createAndAddComponent(UIViewRoot root, FacesContext context, String rendererType, String name, - String library, String position) { + String library, String position) { // if (library != null && BSF_LIBRARY.equals(library)) { // boolean loadBsfResource = @@ -985,12 +971,12 @@ private boolean isFalseOrNo(String param) { } /** - * Add the default datatables.net resource if and only if the user doesn't bring - * their own copy, and if they didn't disallow it in the web.xml by setting the - * context paramter net.bootsfaces.get_datatable_from_cdn to true. + * Add the default datatables.net resource if and only if the user doesn't bring their own copy, and if they + * didn't disallow it in the web.xml by setting the context paramter net.bootsfaces.get_datatable_from_cdn to + * true. * * @param defaultFilename The URL of the file to be loaded - * @param type either "js" or "css" + * @param type either "js" or "css" */ public static void addDatatablesResourceIfNecessary(String defaultFilename, String type) { boolean loadDatatables = shouldLibraryBeLoaded(P_GET_DATATABLE_FROM_CDN, true); @@ -999,7 +985,7 @@ public static void addDatatablesResourceIfNecessary(String defaultFilename, Stri FacesContext context = FacesContext.getCurrentInstance(); UIViewRoot root = context.getViewRoot(); - String[] positions = { "head", "body", "form" }; + String[] positions = {"head", "body", "form"}; for (String position : positions) { if (loadDatatables) { List availableResources = root.getComponentResources(context, position); From 18b22e5e61ca0ab53beb69b38a19aac9a6e16c10 Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Sat, 18 Jan 2020 17:47:02 +0100 Subject: [PATCH 02/11] use the PassThroughAttributes --- .../java/net/bootsfaces/listeners/AddResourcesListener.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index bef674b36..f0f8292bc 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -139,8 +139,9 @@ public void processEvent(SystemEvent event) throws AbortProcessingException { * @param root the UIViewRoot * @return */ - private static Map getViewMap(UIViewRoot root) { - Map viewMap = root.getViewMap(true); + private static Map getViewMap(UIViewRoot root) { + //Map viewMap = root.getViewMap(true); + Map viewMap = root.getPassThroughAttributes(true); return viewMap; } From 1bc9d7fd35857c60b669319fd5691a15ddd62c2e Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Sat, 18 Jan 2020 18:31:10 +0100 Subject: [PATCH 03/11] add a switch between viewMap and attributes --- .../listeners/AddResourcesListener.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index f0f8292bc..c3a5761d2 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -140,8 +140,15 @@ public void processEvent(SystemEvent event) throws AbortProcessingException { * @return */ private static Map getViewMap(UIViewRoot root) { - //Map viewMap = root.getViewMap(true); - Map viewMap = root.getPassThroughAttributes(true); + + // TODO the question is how can you determine whether you can start a session or not + + Map viewMap = root.getViewMap(false); + if (viewMap == null) { + LOGGER.fine("'root.viewMap' currently do not exist, we use as fallback 'root.attributes'"); + Map attributes = root.getAttributes(); + return attributes; + } return viewMap; } @@ -301,7 +308,7 @@ private void addCSS(UIViewRoot root, FacesContext context) { } @SuppressWarnings("unchecked") - List extCSSMap = (List) root.getViewMap().get(EXT_RESOURCE_KEY); + List extCSSMap = (List) getViewMap(root).get(EXT_RESOURCE_KEY); if (extCSSMap != null) { for (String file : extCSSMap) { String name = "css/" + file; @@ -311,7 +318,7 @@ private void addCSS(UIViewRoot root, FacesContext context) { } @SuppressWarnings("unchecked") - List themedCSSMap = (List) root.getViewMap().get(THEME_RESOURCE_KEY); + List themedCSSMap = (List) getViewMap(root).get(THEME_RESOURCE_KEY); if (themedCSSMap != null) { for (String file : themedCSSMap) { String name = "css/" + theme + "/" + file; @@ -881,7 +888,7 @@ public static void addBasicJSResource(String library, String resource) { * @param resource The name of the resource file within the library folder. */ public static void addThemedCSSResource(String resource) { - Map viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap(); + Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); @SuppressWarnings("unchecked") List resourceList = (List) viewMap.get(THEME_RESOURCE_KEY); if (null == resourceList) { @@ -900,7 +907,7 @@ public static void addThemedCSSResource(String resource) { * @param resource The name of the resource file within the library folder. */ public static void addExtCSSResource(String resource) { - Map viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap(); + Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); @SuppressWarnings("unchecked") List resourceList = (List) viewMap.get(EXT_RESOURCE_KEY); if (null == resourceList) { @@ -914,7 +921,7 @@ public static void addExtCSSResource(String resource) { } private static void addResource(String resource, String library, String resourceKey, String resourceTypeKey) { - Map viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap(); + Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); @SuppressWarnings("unchecked") Map resourceMap = (Map) viewMap.get(resourceTypeKey); if (null == resourceMap) { From ccf15c851fa3ed1f6e887a9966375c69981c2a3b Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Sat, 18 Jan 2020 19:11:25 +0100 Subject: [PATCH 04/11] i have found a cros bug with a other problem --- src/main/java/net/bootsfaces/listeners/AddResourcesListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index c3a5761d2..9243641ac 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -143,6 +143,7 @@ private static Map getViewMap(UIViewRoot root) { // TODO the question is how can you determine whether you can start a session or not + // with this impl we get the old bug https://github.com/TheCoder4eu/BootsFaces-OSP/issues/1066 back :-( Map viewMap = root.getViewMap(false); if (viewMap == null) { LOGGER.fine("'root.viewMap' currently do not exist, we use as fallback 'root.attributes'"); From b50a6f321abc09e5b14bb2c6d3f262d88c85b9bb Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Mon, 20 Jan 2020 23:44:41 +0100 Subject: [PATCH 05/11] use the map if a session exists --- .../java/net/bootsfaces/listeners/AddResourcesListener.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index 9243641ac..d4b603050 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -140,11 +140,12 @@ public void processEvent(SystemEvent event) throws AbortProcessingException { * @return */ private static Map getViewMap(UIViewRoot root) { + boolean externalContextSession = FacesContext.getCurrentInstance().getExternalContext().getSession(false) != null; // TODO the question is how can you determine whether you can start a session or not // with this impl we get the old bug https://github.com/TheCoder4eu/BootsFaces-OSP/issues/1066 back :-( - Map viewMap = root.getViewMap(false); + Map viewMap = root.getViewMap(externalContextSession); if (viewMap == null) { LOGGER.fine("'root.viewMap' currently do not exist, we use as fallback 'root.attributes'"); Map attributes = root.getAttributes(); From 20689898dc04eb9d70f659f7291886a787233ecc Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Tue, 28 Jan 2020 23:06:29 +0100 Subject: [PATCH 06/11] use the map if a session exists --- .../bootsfaces/listeners/AddResourcesListener.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index d4b603050..f4002572f 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -113,6 +113,9 @@ public class AddResourcesListener implements SystemEventListener { /** * Returns true if the source is an instance of {@link UIViewRoot}. + * + * @param source + * @return */ @Override public boolean isListenerForSource(Object source) { @@ -121,7 +124,10 @@ public boolean isListenerForSource(Object source) { /** * Trigger adding the resources if and only if the event has been fired by UIViewRoot. + * + * @param event */ + @Override public void processEvent(SystemEvent event) throws AbortProcessingException { FacesContext context = FacesContext.getCurrentInstance(); UIViewRoot root = context.getViewRoot(); @@ -141,13 +147,10 @@ public void processEvent(SystemEvent event) throws AbortProcessingException { */ private static Map getViewMap(UIViewRoot root) { boolean externalContextSession = FacesContext.getCurrentInstance().getExternalContext().getSession(false) != null; - - // TODO the question is how can you determine whether you can start a session or not - - // with this impl we get the old bug https://github.com/TheCoder4eu/BootsFaces-OSP/issues/1066 back :-( + // with this impl we get the old bug on the first request https://github.com/TheCoder4eu/BootsFaces-OSP/issues/1066 back :-( Map viewMap = root.getViewMap(externalContextSession); if (viewMap == null) { - LOGGER.fine("'root.viewMap' currently do not exist, we use as fallback 'root.attributes'"); + LOGGER.info("'root.viewMap' currently do not exist, we use as fallback 'root.attributes'"); Map attributes = root.getAttributes(); return attributes; } @@ -183,7 +186,6 @@ private boolean ensureExistBootsfacesComponent(UIViewRoot root, FacesContext con if (findBsfComponent(root, C.BSF_LIBRARY) != null) { return true; } - return false; } From 0a4a15e17946dff19935a776490b7f69c219881e Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Fri, 31 Jan 2020 21:08:56 +0100 Subject: [PATCH 07/11] use only viewRoot.attributes --- .../listeners/AddResourcesListener.java | 149 ++++++++---------- 1 file changed, 68 insertions(+), 81 deletions(-) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index f4002572f..02374a6cf 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -28,7 +28,6 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -133,7 +132,7 @@ public void processEvent(SystemEvent event) throws AbortProcessingException { UIViewRoot root = context.getViewRoot(); // render the resources only if there is at least one bsf component - if (ensureExistBootsfacesComponent(root, context)) { + if (ensureExistBootsfacesComponent(root)) { addCSS(root, context); addJavascript(root, context); addMetaTags(root, context); @@ -145,16 +144,9 @@ public void processEvent(SystemEvent event) throws AbortProcessingException { * @param root the UIViewRoot * @return */ - private static Map getViewMap(UIViewRoot root) { - boolean externalContextSession = FacesContext.getCurrentInstance().getExternalContext().getSession(false) != null; - // with this impl we get the old bug on the first request https://github.com/TheCoder4eu/BootsFaces-OSP/issues/1066 back :-( - Map viewMap = root.getViewMap(externalContextSession); - if (viewMap == null) { - LOGGER.info("'root.viewMap' currently do not exist, we use as fallback 'root.attributes'"); - Map attributes = root.getAttributes(); - return attributes; - } - return viewMap; + private static Map getMapForView(UIViewRoot root) { + Map attributes = root.getAttributes(); + return attributes; } /** @@ -167,8 +159,8 @@ private static Map getViewMap(UIViewRoot root) { * @param context the faces context * @return */ - private boolean ensureExistBootsfacesComponent(UIViewRoot root, FacesContext context) { - Map viewMap = getViewMap(root); + private boolean ensureExistBootsfacesComponent(UIViewRoot root) { + Map viewMap = getMapForView(root); // check explicit js request if (viewMap.get(RESOURCE_KEY) != null) { @@ -183,10 +175,7 @@ private boolean ensureExistBootsfacesComponent(UIViewRoot root, FacesContext con return true; } // check referenced bsf request - if (findBsfComponent(root, C.BSF_LIBRARY) != null) { - return true; - } - return false; + return findBsfComponent(root, C.BSF_LIBRARY) != null; } /** @@ -291,12 +280,12 @@ private void addCSS(UIViewRoot root, FacesContext context) { } } - LOGGER.log(Level.FINER, "by addCSS - useCDNImportForFontAwesome is {0}", useCDNImportForFontAwesome); + LOGGER.log(Level.INFO, "by addCSS - useCDNImportForFontAwesome is {0}", useCDNImportForFontAwesome); // 2) Font Awesome if (useCDNImportForFontAwesome) { InternalFALink output = new InternalFALink(); - Map viewMap = getViewMap(root); + Map viewMap = getMapForView(root); if (viewMap.containsKey(FONTAWESOME_USED)) { String version = (String) viewMap.get(FONTAWESOME_VERSION); if (version != null) { @@ -312,25 +301,23 @@ private void addCSS(UIViewRoot root, FacesContext context) { } @SuppressWarnings("unchecked") - List extCSSMap = (List) getViewMap(root).get(EXT_RESOURCE_KEY); + List extCSSMap = (List) getMapForView(root).get(EXT_RESOURCE_KEY); if (extCSSMap != null) { for (String file : extCSSMap) { String name = "css/" + file; - createAndAddComponent(root, context, CSS_RENDERER, name, C.BSF_LIBRARY); } } @SuppressWarnings("unchecked") - List themedCSSMap = (List) getViewMap(root).get(THEME_RESOURCE_KEY); + List themedCSSMap = (List) getMapForView(root).get(THEME_RESOURCE_KEY); if (themedCSSMap != null) { for (String file : themedCSSMap) { - String name = "css/" + theme + "/" + file; // Glyphicons icons now are in core.css if(file.equals("icons.css")) //the // icons.css file isn't found in a theme folder // Glyphicons icons now are in core.css name = "css/icons.css"; //look for it // under the css root instead - + String name = "css/" + theme + "/" + file; createAndAddComponent(root, context, CSS_RENDERER, name, C.BSF_LIBRARY); } } @@ -364,8 +351,11 @@ private String loadTheme(UIViewRoot root, FacesContext context) { String theme = getTheme(context); + // why this line of code??? + boolean hastRemoveFontAwesome = isFontAwesomeComponentUsedAndRemoveIt(); + // Theme loading - if (isFontAwesomeComponentUsedAndRemoveIt() || (!theme.equalsIgnoreCase(THEME_NAME_OTHER))) { + if (hastRemoveFontAwesome || (!theme.equalsIgnoreCase(THEME_NAME_OTHER))) { // String filename = "bsf.css"; String filename = "core.css"; Resource themeResource = rh.createResource("css/" + theme + "/" + filename, C.BSF_LIBRARY); @@ -468,7 +458,7 @@ private Map addMandatoryLibraries(UIViewRoot root, FacesContext createAndAddComponent(root, context, SCRIPT_RENDERER, "jq/jquery.js", C.BSF_LIBRARY); } - Map viewMap = getViewMap(root); + Map viewMap = getMapForView(root); @SuppressWarnings("unchecked") Map basicResourceMap = (Map) viewMap.get(BASIC_JS_RESOURCE_KEY); @@ -539,8 +529,11 @@ private void addResourceIfNecessary(UIViewRoot root, FacesContext context, UIOut for (UIComponent c : root.getComponentResources(context, "head")) { String library = (String) c.getAttributes().get("library"); String name = (String) c.getAttributes().get("name"); - if (library != null && library.equals(libToAdd) && name != null && name.equals(nameToAdd)) { - return; + if (library != null && library.equals(libToAdd)) { + if (name != null && name.equals(nameToAdd)) { + LOGGER.log(Level.FINEST, "by addResourceIfNecessary - find existing {0} - {1}", new Object[]{name, library}); + return; + } } } root.addComponentResource(context, output, "head"); @@ -575,13 +568,13 @@ public static void addResourceIfNecessary(String url) { } public static void setFontAwesomeVersion(int version, Object uiComponent) { - Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); + Map viewMap = getMapForView(FacesContext.getCurrentInstance().getViewRoot()); if (version != 4) { @SuppressWarnings("unchecked") Map v5 = (Map) viewMap.get(FONTAWESOME_NEW_VERSION); if (null == v5) { - v5 = new HashMap(); + v5 = new HashMap<>(); viewMap.put(FONTAWESOME_NEW_VERSION, v5); } v5.put(uiComponent, true); @@ -606,17 +599,17 @@ public static void setFontAwesomeVersion(int version, Object uiComponent) { @SuppressWarnings("unchecked") public static void setNeedsFontsAwesome(Object uiComponent) { - Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); + Map viewMap = getMapForView(FacesContext.getCurrentInstance().getViewRoot()); ArrayList list = (ArrayList) viewMap.get(FONTAWESOME_USED); if (list == null) { - list = new ArrayList(); + list = new ArrayList<>(); viewMap.put(FONTAWESOME_USED, list); } list.add(uiComponent); } private boolean needsFontAwesome4() { - Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); + Map viewMap = getMapForView(FacesContext.getCurrentInstance().getViewRoot()); @SuppressWarnings("unchecked") Map v5 = (Map) viewMap.get(FONTAWESOME_NEW_VERSION); @SuppressWarnings("unchecked") @@ -652,15 +645,10 @@ private boolean needsFontAwesome4() { * @param context The current FacesContext */ private void removeDuplicateResources(UIViewRoot root, FacesContext context) { - List resourcesToRemove = new ArrayList(); - Map alreadyThere = new HashMap(); - List components = new ArrayList(root.getComponentResources(context, "head")); - Collections.sort(components, new Comparator() { - @Override - public int compare(UIComponent o1, UIComponent o2) { - return o1.getClientId().compareTo(o2.getClientId()); - } - }); + List resourcesToRemove = new ArrayList<>(); + Map alreadyThere = new HashMap<>(); + List components = new ArrayList<>(root.getComponentResources(context, "head")); + Collections.sort(components, (UIComponent o1, UIComponent o2) -> o1.getClientId().compareTo(o2.getClientId())); for (UIComponent resource : components) { String name = (String) resource.getAttributes().get("name"); String library = (String) resource.getAttributes().get("library"); @@ -701,7 +689,7 @@ private void removeBootstrapResources(UIViewRoot root, FacesContext context) { String theme = getTheme(context); if (theme.equals(THEME_NAME_DEFAULT) || theme.equals(THEME_NAME_OTHER)) { - for (UIComponent resource : root.getComponentResources(context, "head")) { + root.getComponentResources(context, "head").forEach((resource) -> { String name = (String) resource.getAttributes().get("name"); String library = (String) resource.getAttributes().get("library"); if (C.BSF_LIBRARY.equals(library) && name != null) { @@ -711,7 +699,7 @@ private void removeBootstrapResources(UIViewRoot root, FacesContext context) { root.removeComponentResource(context, resource); } } - } + }); } /* * List resourcesToRemove = new ArrayList(); for @@ -738,13 +726,13 @@ private void enforceCorrectLoadOrder(UIViewRoot root, FacesContext context) { // // Put BootsFaces.css or BootsFaces.min.css first, // // theme.css second // // and everything else behind them. - List resources = new ArrayList(); - List first = new ArrayList(); - List middle = new ArrayList(); - List last = new ArrayList(); - List datatable = new ArrayList(); + List resources = new ArrayList<>(); + List first = new ArrayList<>(); + List middle = new ArrayList<>(); + List last = new ArrayList<>(); + List datatable = new ArrayList<>(); - for (UIComponent resource : root.getComponentResources(context, "head")) { + root.getComponentResources(context, "head").forEach((UIComponent resource) -> { String name = (String) resource.getAttributes().get("name"); String position = (String) resource.getAttributes().get("position"); @@ -765,49 +753,49 @@ private void enforceCorrectLoadOrder(UIViewRoot root, FacesContext context) { } } } - } + }); // add the JavaScript files in correct order. Collections.sort(resources, new ResourceFileComparator()); - for (UIComponent c : first) { + first.forEach((c) -> { root.removeComponentResource(context, c); - } - for (UIComponent c : resources) { + }); + resources.forEach((c) -> { root.removeComponentResource(context, c); - } - for (UIComponent c : last) { + }); + last.forEach((c) -> { root.removeComponentResource(context, c); - } - for (UIComponent c : datatable) { + }); + datatable.forEach((c) -> { root.removeComponentResource(context, c); - } + }); // for (UIComponent resource : root.getComponentResources(context, "head")) { // System.out.println(resource.getClass().getName()); // } - for (UIComponent c : root.getComponentResources(context, "head")) { + root.getComponentResources(context, "head").forEach((c) -> { middle.add(c); - } - for (UIComponent c : middle) { + }); + middle.forEach((c) -> { root.removeComponentResource(context, c); - } + }); - for (UIComponent c : first) { + first.forEach((c) -> { root.addComponentResource(context, c, "head"); - } - for (UIComponent c : middle) { + }); + middle.forEach((c) -> { root.addComponentResource(context, c, "head"); - } - for (UIComponent c : resources) { + }); + resources.forEach((c) -> { root.addComponentResource(context, c, "head"); - } - for (UIComponent c : last) { + }); + last.forEach((c) -> { root.addComponentResource(context, c, "head"); - } - for (UIComponent c : datatable) { + }); + datatable.forEach((c) -> { root.addComponentResource(context, c, "head"); - } + }); } /** @@ -834,7 +822,6 @@ private boolean isFontAwesomeComponentUsedAndRemoveIt() { if (null != fontAwesomeResource) { fontAwesomeResource.setInView(false); viewRoot.removeComponentResource(fc, fontAwesomeResource); - // System.out.println("-3" + fontAwesomeResource.getClientId()); return true; } return false; @@ -892,11 +879,11 @@ public static void addBasicJSResource(String library, String resource) { * @param resource The name of the resource file within the library folder. */ public static void addThemedCSSResource(String resource) { - Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); + Map viewMap = getMapForView(FacesContext.getCurrentInstance().getViewRoot()); @SuppressWarnings("unchecked") List resourceList = (List) viewMap.get(THEME_RESOURCE_KEY); if (null == resourceList) { - resourceList = new ArrayList(); + resourceList = new ArrayList<>(); viewMap.put(THEME_RESOURCE_KEY, resourceList); } @@ -911,11 +898,11 @@ public static void addThemedCSSResource(String resource) { * @param resource The name of the resource file within the library folder. */ public static void addExtCSSResource(String resource) { - Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); + Map viewMap = getMapForView(FacesContext.getCurrentInstance().getViewRoot()); @SuppressWarnings("unchecked") List resourceList = (List) viewMap.get(EXT_RESOURCE_KEY); if (null == resourceList) { - resourceList = new ArrayList(); + resourceList = new ArrayList<>(); viewMap.put(EXT_RESOURCE_KEY, resourceList); } @@ -925,11 +912,11 @@ public static void addExtCSSResource(String resource) { } private static void addResource(String resource, String library, String resourceKey, String resourceTypeKey) { - Map viewMap = getViewMap(FacesContext.getCurrentInstance().getViewRoot()); + Map viewMap = getMapForView(FacesContext.getCurrentInstance().getViewRoot()); @SuppressWarnings("unchecked") Map resourceMap = (Map) viewMap.get(resourceTypeKey); if (null == resourceMap) { - resourceMap = new HashMap(); + resourceMap = new HashMap<>(); viewMap.put(resourceTypeKey, resourceMap); } From 2b1ce77bb6a1ff0e182026fa7753751fff68ba48 Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Fri, 31 Jan 2020 21:17:49 +0100 Subject: [PATCH 08/11] use only viewRoot.attributes --- .../java/net/bootsfaces/listeners/AddResourcesListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index 02374a6cf..94d55ecfd 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -352,10 +352,10 @@ private String loadTheme(UIViewRoot root, FacesContext context) { String theme = getTheme(context); // why this line of code??? - boolean hastRemoveFontAwesome = isFontAwesomeComponentUsedAndRemoveIt(); + boolean hasRemoveFontAwesome = isFontAwesomeComponentUsedAndRemoveIt(); // Theme loading - if (hastRemoveFontAwesome || (!theme.equalsIgnoreCase(THEME_NAME_OTHER))) { + if (hasRemoveFontAwesome || (!theme.equalsIgnoreCase(THEME_NAME_OTHER))) { // String filename = "bsf.css"; String filename = "core.css"; Resource themeResource = rh.createResource("css/" + theme + "/" + filename, C.BSF_LIBRARY); From 648cfc319eee27d21382fe90640b270da7975a49 Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Fri, 31 Jan 2020 21:20:20 +0100 Subject: [PATCH 09/11] use only viewRoot.attributes --- .../java/net/bootsfaces/listeners/AddResourcesListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index 94d55ecfd..46af8b131 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -280,7 +280,7 @@ private void addCSS(UIViewRoot root, FacesContext context) { } } - LOGGER.log(Level.INFO, "by addCSS - useCDNImportForFontAwesome is {0}", useCDNImportForFontAwesome); + LOGGER.log(Level.FINER, "by addCSS - useCDNImportForFontAwesome is {0}", useCDNImportForFontAwesome); // 2) Font Awesome if (useCDNImportForFontAwesome) { From f9390a8b1442ef19b9bc7feeed69c798f380c0e1 Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Fri, 31 Jan 2020 21:55:12 +0100 Subject: [PATCH 10/11] it always uses a session so you can continue to use this map --- .../java/net/bootsfaces/listeners/AddResourcesListener.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index 46af8b131..6430e0286 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -145,8 +145,7 @@ public void processEvent(SystemEvent event) throws AbortProcessingException { * @return */ private static Map getMapForView(UIViewRoot root) { - Map attributes = root.getAttributes(); - return attributes; + return root.getViewMap(); } /** From a7345f4875ee3dfaaf31d5bc2d6c3558cdcb3474 Mon Sep 17 00:00:00 2001 From: geopossachs <10324450+geopossachs@users.noreply.github.com> Date: Sat, 1 Feb 2020 10:49:28 +0100 Subject: [PATCH 11/11] add switch for viewMap and attributes via session and form check --- .../listeners/AddResourcesListener.java | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java index 6430e0286..67f5ce77b 100644 --- a/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java +++ b/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java @@ -41,6 +41,7 @@ import javax.faces.application.Resource; import javax.faces.application.ResourceHandler; import javax.faces.component.UIComponent; +import javax.faces.component.UIForm; import javax.faces.component.UIOutput; import javax.faces.component.UIViewRoot; import javax.faces.component.html.HtmlBody; @@ -144,8 +145,52 @@ public void processEvent(SystemEvent event) throws AbortProcessingException { * @param root the UIViewRoot * @return */ - private static Map getMapForView(UIViewRoot root) { - return root.getViewMap(); + private static Map getMapForView(UIViewRoot rootView) { + // if the view is transient, we use only the attribute-store + if (rootView.isTransient()) { + LOGGER.log(Level.FINEST, "use attribute-store"); + return rootView.getAttributes(); + } else { + // if a session exists, we can use the viewMap-store + // check if a session exists + boolean sessionExists = FacesContext.getCurrentInstance().getExternalContext().getSession(false) != null; + if (sessionExists) { + LOGGER.log(Level.FINEST, "use viewMap-store"); + return rootView.getViewMap(); + } else { + // as far as I know, a session is started if there is a UIForm + // if a form exists, we can use or create the viewMap-store + // check if a form exists + boolean formExists = getClosestForm(rootView) != null; + Map viewMap = rootView.getViewMap(formExists); + if (viewMap != null) { + LOGGER.log(Level.FINEST, "use viewMap-store"); + return viewMap; + } else { + LOGGER.log(Level.FINEST, "use attribute-store"); + return rootView.getAttributes(); + } + } + } + } + + /** + * searches recursively for the next form + * @param component + * @return + */ + private static UIForm getClosestForm(UIComponent component) { + for (UIComponent c : component.getChildren()) { + if (c instanceof UIForm) { + return (UIForm) c; + } else { + UIForm found = getClosestForm(c); + if (found != null) { + return found; + } + } + } + return null; } /**