| /* |
| * 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.myfaces.extensions.scripting.jsf.dynamicdecorators.implemetations; |
| |
| import org.apache.myfaces.extensions.scripting.api.Decorated; |
| import org.apache.myfaces.extensions.scripting.api.ScriptingConst; |
| import org.apache.myfaces.extensions.scripting.core.util.WeavingContext; |
| |
| import javax.el.*; |
| import javax.faces.FacesException; |
| import javax.faces.application.Application; |
| import javax.faces.application.NavigationHandler; |
| import javax.faces.application.StateManager; |
| import javax.faces.application.ViewHandler; |
| import javax.faces.component.UIComponent; |
| import javax.faces.context.FacesContext; |
| import javax.faces.convert.Converter; |
| import javax.faces.el.*; |
| import javax.faces.event.ActionListener; |
| import javax.faces.validator.Validator; |
| import java.lang.reflect.Proxy; |
| import java.util.*; |
| |
| /** |
| * our decorating application |
| * which should resolve our bean issues within a central |
| * bean processing interceptor |
| * <p/> |
| * |
| * @author Werner Punz |
| */ |
| @SuppressWarnings({"deprecation", "deprecation"}) |
| public class ApplicationProxy extends Application implements Decorated { |
| |
| volatile Application _delegate; |
| volatile static boolean elResolverAdded = false; |
| volatile static boolean varResolverAdded = false; |
| |
| public ApplicationProxy(Application delegate) { |
| _delegate = delegate; |
| } |
| |
| public void addELResolver(ELResolver elResolver) { |
| weaveDelegate(); |
| if (!elResolverAdded) { |
| //ordering hints are unsufficient here we make |
| //sure our proxy is added as second in the chain |
| //also this method works as well on |
| //jsf 1.2 while hints only work in jsf2 |
| elResolver = new ELResolverProxy(elResolver); |
| elResolverAdded = true; |
| } |
| _delegate.addELResolver(elResolver); |
| } |
| |
| private void weaveDelegate() { |
| if (_delegate != null) { |
| _delegate = (Application) WeavingContext.getWeaver().reloadScriptingInstance(_delegate, ScriptingConst.ARTIFACT_TYPE_APPLICATION); |
| } |
| } |
| |
| public ELResolver getELResolver() { |
| weaveDelegate(); |
| ELResolver retVal = _delegate.getELResolver(); |
| return retVal; |
| } |
| |
| //TOD add a weaving for resource bundles |
| |
| public ResourceBundle getResourceBundle(FacesContext facesContext, String s) throws FacesException, NullPointerException { |
| weaveDelegate(); |
| return _delegate.getResourceBundle(facesContext, s); |
| } |
| |
| public UIComponent createComponent(ValueExpression valueExpression, FacesContext facesContext, String s) throws FacesException, NullPointerException { |
| weaveDelegate(); |
| System.out.println("create1"); |
| UIComponent component = _delegate.createComponent(valueExpression, facesContext, s); |
| |
| /*we are reweaving on the fly because we cannot be sure if |
| * the class is not recycled all the time in the creation |
| * code, in the renderer we do it on method base |
| * due to the fact that our renderers are recycled via |
| * a flyweight pattern |
| * |
| * |
| * Also we cannot proxy here because there is no UIComponent interface |
| * maybe in the long run we can make a decorator here instead |
| * but for now lets try it this way |
| */ |
| if (WeavingContext.isDynamic(component.getClass()) && !alreadyWovenInRequest(component.getClass().getName())) { |
| /*once it was tainted we have to recreate all the time*/ |
| component = (UIComponent) WeavingContext.getWeaver().reloadScriptingInstance(component, ScriptingConst.ARTIFACT_TYPE_COMPONENT); |
| alreadyWovenInRequest(component.getClass().getName()); |
| } |
| return component; |
| |
| } |
| |
| public ExpressionFactory getExpressionFactory() { |
| weaveDelegate(); |
| return _delegate.getExpressionFactory(); |
| } |
| |
| public void addELContextListener(ELContextListener elContextListener) { |
| weaveDelegate(); |
| if (WeavingContext.isDynamic(elContextListener.getClass())) |
| elContextListener = (ELContextListener) WeavingContext.createMethodReloadingProxyFromObject(elContextListener, ELContextListener.class, ScriptingConst.ARTIFACT_TYPE_ELCONTEXTLISTENER); |
| _delegate.addELContextListener(elContextListener); |
| } |
| |
| public void removeELContextListener(ELContextListener elContextListener) { |
| weaveDelegate(); |
| _delegate.removeELContextListener(elContextListener); |
| } |
| |
| public ELContextListener[] getELContextListeners() { |
| weaveDelegate(); |
| return _delegate.getELContextListeners(); |
| } |
| |
| public Object evaluateExpressionGet(FacesContext facesContext, String s, Class aClass) throws ELException { |
| weaveDelegate(); |
| //good place for a dynamic reloading check as well |
| Object retVal = _delegate.evaluateExpressionGet(facesContext, s, aClass); |
| if (WeavingContext.isDynamic(retVal.getClass())) |
| retVal = WeavingContext.getWeaver().reloadScriptingInstance(retVal, ScriptingConst.ARTIFACT_TYPE_MANAGEDBEAN); |
| return retVal; |
| } |
| |
| public ActionListener getActionListener() { |
| weaveDelegate(); |
| ActionListener retVal = _delegate.getActionListener(); |
| if (WeavingContext.isDynamic(retVal.getClass())) |
| retVal = (ActionListener) WeavingContext.createMethodReloadingProxyFromObject(retVal, ActionListener.class, ScriptingConst.ARTIFACT_TYPE_ACTIONLISTENER); |
| return retVal; |
| } |
| |
| public void setActionListener(ActionListener actionListener) { |
| weaveDelegate(); |
| if (WeavingContext.isDynamic(actionListener.getClass())) |
| actionListener = (ActionListener) WeavingContext.createMethodReloadingProxyFromObject(actionListener, ActionListener.class, ScriptingConst.ARTIFACT_TYPE_ACTIONLISTENER); |
| _delegate.setActionListener(actionListener); |
| } |
| |
| public Locale getDefaultLocale() { |
| weaveDelegate(); |
| return _delegate.getDefaultLocale(); |
| } |
| |
| public void setDefaultLocale(Locale locale) { |
| weaveDelegate(); |
| _delegate.setDefaultLocale(locale); |
| } |
| |
| public String getDefaultRenderKitId() { |
| weaveDelegate(); |
| return _delegate.getDefaultRenderKitId(); |
| } |
| |
| public void setDefaultRenderKitId(String s) { |
| weaveDelegate(); |
| _delegate.setDefaultRenderKitId(s); |
| } |
| |
| public String getMessageBundle() { |
| weaveDelegate(); |
| return _delegate.getMessageBundle(); |
| } |
| |
| public void setMessageBundle(String s) { |
| weaveDelegate(); |
| _delegate.setMessageBundle(s); |
| } |
| |
| public NavigationHandler getNavigationHandler() { |
| weaveDelegate(); |
| //defined in the setter to speed things up a little |
| NavigationHandler retVal = _delegate.getNavigationHandler(); |
| if (retVal != null && WeavingContext.isDynamic(retVal.getClass())) |
| retVal = new NavigationHandlerProxy(retVal); |
| return retVal; |
| } |
| |
| public void setNavigationHandler(NavigationHandler navigationHandler) { |
| weaveDelegate(); |
| if (navigationHandler != null && WeavingContext.isDynamic(navigationHandler.getClass())) |
| navigationHandler = new NavigationHandlerProxy(navigationHandler); |
| _delegate.setNavigationHandler(navigationHandler); |
| } |
| |
| @SuppressWarnings("deprecation") |
| public PropertyResolver getPropertyResolver() { |
| weaveDelegate(); |
| return _delegate.getPropertyResolver(); |
| } |
| |
| @SuppressWarnings("deprecation") |
| public void setPropertyResolver(PropertyResolver propertyResolver) { |
| weaveDelegate(); |
| _delegate.setPropertyResolver(propertyResolver); |
| } |
| |
| @SuppressWarnings("deprecation") |
| public VariableResolver getVariableResolver() { |
| weaveDelegate(); |
| VariableResolver variableResolver = _delegate.getVariableResolver(); |
| return variableResolver; |
| } |
| |
| @SuppressWarnings("deprecation") |
| public void setVariableResolver(VariableResolver variableResolver) { |
| weaveDelegate(); |
| if (!varResolverAdded) { |
| variableResolver = new VariableResolverProxy(variableResolver); |
| varResolverAdded = true; |
| } |
| _delegate.setVariableResolver(variableResolver); |
| } |
| |
| public ViewHandler getViewHandler() { |
| weaveDelegate(); |
| ViewHandler handler = _delegate.getViewHandler(); |
| |
| /* |
| We proxy here to emable dynamic reloading for |
| methods in the long run, as soon as we hit |
| java all our groovy reloading code is lost |
| hence we have to work with proxies here |
| */ |
| if (WeavingContext.isDynamic(handler.getClass())) |
| handler = new ViewHandlerProxy(handler); |
| return handler; |
| } |
| |
| public void setViewHandler(ViewHandler viewHandler) { |
| weaveDelegate(); |
| /*make sure you have the delegates as well in properties*/ |
| if (WeavingContext.isDynamic(viewHandler.getClass())) |
| viewHandler = new ViewHandlerProxy(viewHandler); |
| |
| _delegate.setViewHandler(viewHandler); |
| } |
| |
| public StateManager getStateManager() { |
| weaveDelegate(); |
| return _delegate.getStateManager(); |
| } |
| |
| public void setStateManager(StateManager stateManager) { |
| weaveDelegate(); |
| _delegate.setStateManager(stateManager); |
| } |
| |
| public void addComponent(String componentType, String componentClass) { |
| weaveDelegate(); |
| _delegate.addComponent(componentType, componentClass); |
| } |
| |
| public UIComponent createComponent(String s) throws FacesException { |
| weaveDelegate(); |
| //the components are generated anew very often |
| //we cannot do an on object weaving here |
| UIComponent component = _delegate.createComponent(s); |
| |
| /*we are reweaving on the fly because we cannot be sure if |
| * the class is not recycled all the time in the creation |
| * code, in the renderer we do it on method base |
| * due to the fact that our renderers are recycled via |
| * a flyweight pattern*/ |
| return (UIComponent) reloadInstance(component, ScriptingConst.ARTIFACT_TYPE_COMPONENT); |
| } |
| |
| @SuppressWarnings("deprecation") |
| public UIComponent createComponent(ValueBinding valueBinding, FacesContext facesContext, String s) throws FacesException { |
| weaveDelegate(); |
| UIComponent component = _delegate.createComponent(valueBinding, facesContext, s); |
| |
| /*we are reweaving on the fly because we cannot be sure if |
| * the class is not recycled all the time in the creation |
| * code, in the renderer we do it on method base |
| * due to the fact that our renderers are recycled via |
| * a flyweight pattern*/ |
| return (UIComponent) reloadInstance(component, ScriptingConst.ARTIFACT_TYPE_COMPONENT); |
| } |
| |
| public Iterator<String> getComponentTypes() { |
| weaveDelegate(); |
| return _delegate.getComponentTypes(); |
| } |
| |
| public void addConverter(String s, String s1) { |
| weaveDelegate(); |
| _delegate.addConverter(s, s1); |
| } |
| |
| public void addConverter(Class aClass, String s) { |
| weaveDelegate(); |
| _delegate.addConverter(aClass, s); |
| } |
| |
| public Converter createConverter(String s) { |
| weaveDelegate(); |
| Converter retVal = _delegate.createConverter(s); |
| /** |
| * since createConverter is called only once |
| * we have to work with method reloading proxies |
| * we cannot use this technique extensively for speed reasons |
| * most of the time it is fine just to work with |
| * |
| * reloading objects at their interception points |
| */ |
| if (WeavingContext.isDynamic(retVal.getClass())) { |
| retVal = (Converter) WeavingContext.createMethodReloadingProxyFromObject(retVal, Converter.class, ScriptingConst.ARTIFACT_TYPE_CONVERTER); |
| |
| } |
| |
| return retVal; |
| } |
| |
| public Converter createConverter(Class aClass) { |
| weaveDelegate(); |
| Converter retVal = _delegate.createConverter(aClass); |
| if (retVal != null && WeavingContext.isDynamic(retVal.getClass())) { |
| retVal = (Converter) WeavingContext.createMethodReloadingProxyFromObject(retVal, Converter.class, ScriptingConst.ARTIFACT_TYPE_CONVERTER); |
| } |
| |
| return retVal; |
| } |
| |
| public Iterator<String> getConverterIds() { |
| weaveDelegate(); |
| return _delegate.getConverterIds(); |
| } |
| |
| public Iterator<Class> getConverterTypes() { |
| weaveDelegate(); |
| return _delegate.getConverterTypes(); |
| } |
| |
| @SuppressWarnings("deprecation") |
| public MethodBinding createMethodBinding(String s, Class[] classes) throws ReferenceSyntaxException { |
| weaveDelegate(); |
| return _delegate.createMethodBinding(s, classes); |
| } |
| |
| public Iterator<Locale> getSupportedLocales() { |
| weaveDelegate(); |
| return _delegate.getSupportedLocales(); |
| } |
| |
| public void setSupportedLocales(Collection<Locale> locales) { |
| weaveDelegate(); |
| _delegate.setSupportedLocales(locales); |
| } |
| |
| public void addValidator(String s, String s1) { |
| weaveDelegate(); |
| _delegate.addValidator(s, s1); |
| } |
| |
| public Validator createValidator(String s) throws FacesException { |
| weaveDelegate(); |
| |
| Validator retVal = _delegate.createValidator(s); |
| if (WeavingContext.isDynamic(retVal.getClass()) && !Proxy.isProxyClass(retVal.getClass())) { |
| retVal = (Validator) reloadInstance(retVal, ScriptingConst.ARTIFACT_TYPE_VALIDATOR); |
| } |
| return retVal; |
| } |
| |
| public Iterator<String> getValidatorIds() { |
| weaveDelegate(); |
| return _delegate.getValidatorIds(); |
| } |
| |
| @SuppressWarnings("deprecation") |
| public ValueBinding createValueBinding(String s) throws ReferenceSyntaxException { |
| weaveDelegate(); |
| return _delegate.createValueBinding(s); |
| } |
| |
| public Object getDelegate() { |
| return _delegate; //To change body of implemented methods use File | Settings | File Templates. |
| } |
| |
| private Object reloadInstance(Object instance, int artefactType) { |
| if (instance == null) { |
| return null; |
| } |
| if (WeavingContext.isDynamic(instance.getClass()) && !alreadyWovenInRequest(instance.getClass().getName())) { |
| instance = WeavingContext.getWeaver().reloadScriptingInstance(instance, artefactType); |
| alreadyWovenInRequest(instance.getClass().getName()); |
| } |
| return instance; |
| } |
| |
| private boolean alreadyWovenInRequest(String clazz) { |
| //portlets now can be enabled thanks to the jsf2 indirections regarding the external context |
| Map<String, Object> reqMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap(); |
| if (reqMap.get(ScriptingConst.SCRIPTING_REQUSINGLETON + clazz) == null) { |
| reqMap.put(ScriptingConst.SCRIPTING_REQUSINGLETON + clazz, ""); |
| return false; |
| } |
| return true; |
| } |
| |
| } |