diff --git a/api/src/main/java/javax/faces/component/_UIWebsocket.java b/api/src/main/java/javax/faces/component/_UIWebsocket.java index cc99bb91b2..e2dc0b09b4 100644 --- a/api/src/main/java/javax/faces/component/_UIWebsocket.java +++ b/api/src/main/java/javax/faces/component/_UIWebsocket.java @@ -33,7 +33,7 @@ defaultRendererType = "javax.faces.Websocket", implementz = "javax.faces.component.behavior.ClientBehaviorHolder", bodyContent = "empty") -abstract class _UIWebsocket extends UIOutput implements ClientBehaviorHolder +abstract class _UIWebsocket extends UIComponentBase { static public final String COMPONENT_FAMILY = "javax.faces.Script"; @@ -60,89 +60,4 @@ abstract class _UIWebsocket extends UIOutput implements ClientBehaviorHolder @JSFProperty(defaultValue = "true") public abstract boolean isConnected(); - @Override - public java.util.Collection getEventNames() - { - return new java.util.Collection(){ - - @Override - public int size() - { - return 0; - } - - @Override - public boolean isEmpty() - { - return false; - } - - @Override - public boolean contains(Object o) - { - return true; - } - - @Override - public java.util.Iterator iterator() - { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public Object[] toArray() - { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public T[] toArray(T[] a) - { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public boolean add(String e) - { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public boolean remove(Object o) - { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public boolean containsAll(java.util.Collection c) - { - return true; - } - - @Override - public boolean addAll(java.util.Collection c) - { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public boolean removeAll(java.util.Collection c) - { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public boolean retainAll(java.util.Collection c) - { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void clear() - { - throw new UnsupportedOperationException("Not supported yet."); - } - }; - } - } diff --git a/api/src/main/resources/META-INF/componentClass20.vm b/api/src/main/resources/META-INF/componentClass20.vm index 11d8be7d9a..ce205224b0 100644 --- a/api/src/main/resources/META-INF/componentClass20.vm +++ b/api/src/main/resources/META-INF/componentClass20.vm @@ -131,6 +131,99 @@ $innersource } #end #end + +#if ($component.implements) +#if ( ($component.implements == "javax.faces.component.behavior.ClientBehaviorHolder") + && (${utils.getClassFromFullClass($component.className)} == "UIWebsocket")) + // Start UIWebsocket getEventNames template + @Override + public java.util.Collection getEventNames() + { + return new java.util.Collection(){ + + @Override + public int size() + { + return 0; + } + + @Override + public boolean isEmpty() + { + return false; + } + + @Override + public boolean contains(Object o) + { + return true; + } + + @Override + public java.util.Iterator iterator() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Object[] toArray() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public T[] toArray(T[] a) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean add(String e) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean remove(Object o) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean containsAll(java.util.Collection c) + { + return true; + } + + @Override + public boolean addAll(java.util.Collection c) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean removeAll(java.util.Collection c) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean retainAll(java.util.Collection c) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void clear() + { + throw new UnsupportedOperationException("Not supported yet."); + } + }; + } + // End UIWebsocket getEventNames template +#end +#end + #if ($component.defaultEventName) #if ($component.defaultEventName != "") diff --git a/impl/src/main/java/org/apache/myfaces/push/WebsocketComponentRenderer.java b/impl/src/main/java/org/apache/myfaces/push/WebsocketComponentRenderer.java index d71b716a66..36acddb564 100644 --- a/impl/src/main/java/org/apache/myfaces/push/WebsocketComponentRenderer.java +++ b/impl/src/main/java/org/apache/myfaces/push/WebsocketComponentRenderer.java @@ -112,79 +112,72 @@ public void encodeEnd(FacesContext facesContext, UIComponent c) throws IOExcepti ResponseWriter writer = facesContext.getResponseWriter(); - //Only the first time it is required a session id. - if (component.getValue() == null) + String channel = component.getChannel(); + + // TODO: use a single bean and entry point for this algorithm. + BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext()); + + WebsocketChannelTokenBuilderBean channelTokenBean = CDIUtils.lookup( + beanManager, + WebsocketChannelTokenBuilderBean.class); + + // This bean is required because you always need to register the token, so it can be properly destroyed + WebsocketViewBean viewTokenBean = CDIUtils.lookup( + beanManager, + WebsocketViewBean.class); + WebsocketSessionBean sessionTokenBean = CDIUtils.lookup( + beanManager, WebsocketSessionBean.class); + + // Create channel token + // TODO: Use ResponseStateManager to create the token + String scope = component.getScope() == null ? "application" : component.getScope(); + WebsocketChannelMetadata metadata = new WebsocketChannelMetadata( + channel, scope, component.getUser(), component.isConnected()); + + String channelToken = null; + // Force a new channelToken if "connected" property is set to false, because in that case websocket + // creation + if (!component.isConnected()) { - String channel = component.getChannel(); - - // TODO: use a single bean and entry point for this algorithm. - BeanManager beanManager = CDIUtils.getBeanManager(facesContext.getExternalContext()); - - WebsocketChannelTokenBuilderBean channelTokenBean = CDIUtils.lookup( - beanManager, - WebsocketChannelTokenBuilderBean.class); - - // This bean is required because you always need to register the token, so it can be properly destroyed - WebsocketViewBean viewTokenBean = CDIUtils.lookup( - beanManager, - WebsocketViewBean.class); - WebsocketSessionBean sessionTokenBean = CDIUtils.lookup( - beanManager, WebsocketSessionBean.class); - - // Create channel token - // TODO: Use ResponseStateManager to create the token - String scope = component.getScope() == null ? "application" : component.getScope(); - WebsocketChannelMetadata metadata = new WebsocketChannelMetadata( - channel, scope, component.getUser(), component.isConnected()); - - String channelToken = null; - // Force a new channelToken if "connected" property is set to false, because in that case websocket - // creation - if (!component.isConnected()) - { - channelToken = viewTokenBean.getChannelToken(metadata); - } - if (channelToken == null) - { - // No channel token found for that combination, create a new token for this view - channelToken = channelTokenBean.createChannelToken(facesContext, channel); - - // Register the channel into the bean that will manage the Session instance used to do the push - component.setValue(channelToken); - - // Register channel in view scope to chain discard view algorithm using @PreDestroy - viewTokenBean.registerToken(channelToken, metadata); - - // Register channel in session scope to allow validation on handshake ( WebsocketConfigurator ) - sessionTokenBean.registerToken(channelToken, metadata); - } + channelToken = viewTokenBean.getChannelToken(metadata); + } + if (channelToken == null) + { + // No channel token found for that combination, create a new token for this view + channelToken = channelTokenBean.createChannelToken(facesContext, channel); + + // Register channel in view scope to chain discard view algorithm using @PreDestroy + viewTokenBean.registerToken(channelToken, metadata); + + // Register channel in session scope to allow validation on handshake ( WebsocketConfigurator ) + sessionTokenBean.registerToken(channelToken, metadata); + } - // Ask these two scopes - WebsocketApplicationBean appTokenBean = CDIUtils.getInstance( - beanManager, WebsocketApplicationBean.class, false); + // Ask these two scopes + WebsocketApplicationBean appTokenBean = CDIUtils.getInstance( + beanManager, WebsocketApplicationBean.class, false); - // Register token and metadata in the proper bean - if (scope.equals("view")) - { - viewTokenBean.registerWebsocketSession(channelToken, metadata); - } - else if (scope.equals("session")) - { - sessionTokenBean = (sessionTokenBean != null) ? sessionTokenBean : CDIUtils.lookup( - CDIUtils.getBeanManager(facesContext.getExternalContext()), - WebsocketSessionBean.class); + // Register token and metadata in the proper bean + if (scope.equals("view")) + { + viewTokenBean.registerWebsocketSession(channelToken, metadata); + } + else if (scope.equals("session")) + { + sessionTokenBean = (sessionTokenBean != null) ? sessionTokenBean : CDIUtils.lookup( + CDIUtils.getBeanManager(facesContext.getExternalContext()), + WebsocketSessionBean.class); - sessionTokenBean.registerWebsocketSession(channelToken, metadata); - } - else - { - //Default application - appTokenBean = (appTokenBean != null) ? appTokenBean : CDIUtils.lookup( - CDIUtils.getBeanManager(facesContext.getExternalContext()), - WebsocketApplicationBean.class); + sessionTokenBean.registerWebsocketSession(channelToken, metadata); + } + else + { + //Default application + appTokenBean = (appTokenBean != null) ? appTokenBean : CDIUtils.lookup( + CDIUtils.getBeanManager(facesContext.getExternalContext()), + WebsocketApplicationBean.class); - appTokenBean.registerWebsocketSession(channelToken, metadata); - } + appTokenBean.registerWebsocketSession(channelToken, metadata); } writer.startElement(HTML.SCRIPT_ELEM, component); @@ -196,7 +189,7 @@ else if (scope.equals("session")) sb.append(","); sb.append("'"+facesContext.getExternalContext().encodeWebsocketURL( facesContext.getApplication().getViewHandler().getWebsocketURL( - facesContext, component.getChannel()+"?"+(String) component.getValue()))+"'"); + facesContext, component.getChannel()+"?"+channelToken))+"'"); sb.append(","); sb.append("'"+component.getChannel()+"'"); sb.append(",");