Return-Path: X-Original-To: apmail-deltaspike-commits-archive@www.apache.org Delivered-To: apmail-deltaspike-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 210D617826 for ; Fri, 24 Oct 2014 21:40:41 +0000 (UTC) Received: (qmail 91461 invoked by uid 500); 24 Oct 2014 21:40:41 -0000 Delivered-To: apmail-deltaspike-commits-archive@deltaspike.apache.org Received: (qmail 91431 invoked by uid 500); 24 Oct 2014 21:40:40 -0000 Mailing-List: contact commits-help@deltaspike.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@deltaspike.apache.org Delivered-To: mailing list commits@deltaspike.apache.org Received: (qmail 91418 invoked by uid 99); 24 Oct 2014 21:40:40 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 24 Oct 2014 21:40:40 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id A95AD81262E; Fri, 24 Oct 2014 21:40:40 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: gpetracek@apache.org To: commits@deltaspike.apache.org Message-Id: <076c1937f4874608a01190850d6648cc@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: DELTASPIKE-751 WindowContextQuotaHandler Date: Fri, 24 Oct 2014 21:40:40 +0000 (UTC) Repository: deltaspike Updated Branches: refs/heads/master a490378de -> 785ba0ad9 DELTASPIKE-751 WindowContextQuotaHandler Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/785ba0ad Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/785ba0ad Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/785ba0ad Branch: refs/heads/master Commit: 785ba0ad981d316c1b6db9594f73930e81c0a657 Parents: a490378 Author: gpetracek Authored: Fri Oct 24 22:12:01 2014 +0200 Committer: gpetracek Committed: Fri Oct 24 23:28:01 2014 +0200 ---------------------------------------------------------------------- .../scope/window/WindowContextQuotaHandler.java | 31 ++++++++ .../DefaultWindowContextQuotaHandler.java | 84 ++++++++++++++++++++ .../impl/scope/window/WindowBeanHolder.java | 34 ++++++++ .../window/WindowContextQuotaHandlerCache.java | 61 ++++++++++++++ .../spi/scope/window/ClientWindowConfig.java | 6 ++ .../scope/window/DefaultClientWindowConfig.java | 11 +++ .../window/JsfWindowContextQuotaHandler.java | 40 ++++++++++ 7 files changed, 267 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/785ba0ad/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/scope/window/WindowContextQuotaHandler.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/scope/window/WindowContextQuotaHandler.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/scope/window/WindowContextQuotaHandler.java new file mode 100644 index 0000000..8d27c45 --- /dev/null +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/scope/window/WindowContextQuotaHandler.java @@ -0,0 +1,31 @@ +/* + * 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.deltaspike.core.spi.scope.window; + +import org.apache.deltaspike.core.spi.activation.Deactivatable; + +import java.io.Serializable; + +/** + * Allows to create a custom handler for a custom window-quota + */ +public interface WindowContextQuotaHandler extends Deactivatable, Serializable +{ + void checkWindowContextQuota(String windowId); +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/785ba0ad/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/DefaultWindowContextQuotaHandler.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/DefaultWindowContextQuotaHandler.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/DefaultWindowContextQuotaHandler.java new file mode 100644 index 0000000..3b44094 --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/DefaultWindowContextQuotaHandler.java @@ -0,0 +1,84 @@ +/* + * 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.deltaspike.core.impl.scope.window; + +import org.apache.deltaspike.core.api.config.ConfigResolver; +import org.apache.deltaspike.core.spi.scope.window.WindowContextQuotaHandler; + +import javax.annotation.PostConstruct; +import javax.enterprise.context.SessionScoped; +import javax.inject.Inject; +import java.util.Stack; + +@SessionScoped +//could be also dependent-scoped since we only inject it in one session-scoped bean, however, +//if users would like to customize the behavior they wouldn't be able to use it (if it would be dependent-scoped) +public class DefaultWindowContextQuotaHandler implements WindowContextQuotaHandler +{ + protected int maxWindowContextCount; + + @Inject + private WindowContextQuotaHandlerCache quotaHandlerCache; + + private Stack windowIdStack = new Stack(); + + @PostConstruct + protected void init() + { + String maxCount = ConfigResolver.getPropertyValue("deltaspike.scope.window.max-count", "" + 1024); + this.maxWindowContextCount = Integer.parseInt(maxCount); + } + + public synchronized /*no issue due to session-scoped instance*/ void checkWindowContextQuota(String windowId) + { + if (windowId == null) + { + return; + } + + if (this.quotaHandlerCache.cacheWindowId(windowId)) + { + return; + } + + /* + * the following part gets executed only once per request, if the window-id is the same + */ + + if (this.windowIdStack.contains(windowId)) + { + if (windowIdStack.size() > 1) //don't move it up if there is just one entry + { + this.windowIdStack.remove(windowId); + this.windowIdStack.push(windowId); + } + } + else + { + this.windowIdStack.push(windowId); + if (this.windowIdStack.size() > this.maxWindowContextCount) + { + String windowIdToRemove = this.windowIdStack.remove(0); + //destroy it lazily at the end of the request to avoid an overhead during the request + //which might be caused by pre-destroy logic of window-scoped beans + this.quotaHandlerCache.setWindowIdToDestroy(windowIdToRemove); + } + } + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/785ba0ad/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowBeanHolder.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowBeanHolder.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowBeanHolder.java index a83e0bd..bed91c7 100644 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowBeanHolder.java +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowBeanHolder.java @@ -19,8 +19,16 @@ package org.apache.deltaspike.core.impl.scope.window; import org.apache.deltaspike.core.impl.scope.AbstractBeanHolder; +import org.apache.deltaspike.core.spi.activation.Deactivatable; +import org.apache.deltaspike.core.spi.scope.window.WindowContextQuotaHandler; +import org.apache.deltaspike.core.util.ClassDeactivationUtils; +import org.apache.deltaspike.core.util.ProxyUtils; +import org.apache.deltaspike.core.util.context.ContextualStorage; +import javax.annotation.PostConstruct; import javax.enterprise.context.SessionScoped; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; /** * This holder will store the window Ids and it's beans for the current @@ -31,4 +39,30 @@ import javax.enterprise.context.SessionScoped; public class WindowBeanHolder extends AbstractBeanHolder { private static final long serialVersionUID = 6313493410718133308L; + + @Inject + private WindowContextQuotaHandler windowContextQuotaHandler; + + private boolean windowContextQuotaHandlerEnabled; + + @PostConstruct + protected void init() + { + Class windowContextQuotaHandlerClass = + ProxyUtils.getUnproxiedClass(windowContextQuotaHandler.getClass()); + + this.windowContextQuotaHandlerEnabled = ClassDeactivationUtils.isActivated(windowContextQuotaHandlerClass); + } + + @Override + public ContextualStorage getContextualStorage(BeanManager beanManager, String key, boolean createIfNotExist) + { + ContextualStorage result = super.getContextualStorage(beanManager, key, createIfNotExist); + if (this.windowContextQuotaHandlerEnabled) + { + //only check it once the storage was created successfully + this.windowContextQuotaHandler.checkWindowContextQuota(key); + } + return result; + } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/785ba0ad/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextQuotaHandlerCache.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextQuotaHandlerCache.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextQuotaHandlerCache.java new file mode 100644 index 0000000..47ae860 --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextQuotaHandlerCache.java @@ -0,0 +1,61 @@ +/* + * 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.deltaspike.core.impl.scope.window; + +import org.apache.deltaspike.core.spi.scope.window.WindowContext; + +import javax.annotation.PreDestroy; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import java.io.Serializable; + +@RequestScoped +public class WindowContextQuotaHandlerCache implements Serializable +{ + private String checkedWindowId; + private String windowIdToRemove; + + @Inject + private WindowContext windowContext; + + /** + * @param currentWindowId window-id which gets processed right now + * @return true if the previously checked window-id is the same, false otherwise + */ + public boolean cacheWindowId(String currentWindowId) + { + boolean result = currentWindowId.equals(this.checkedWindowId); + this.checkedWindowId = currentWindowId; + return result; + } + + public void setWindowIdToDestroy(String windowIdToRemove) + { + this.windowIdToRemove = windowIdToRemove; + } + + @PreDestroy + public void cleanup() + { + if (this.windowIdToRemove != null) + { + this.windowContext.closeWindow(this.windowIdToRemove); + } + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/785ba0ad/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindowConfig.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindowConfig.java b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindowConfig.java index 2828bd4..3c38c1f 100644 --- a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindowConfig.java +++ b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindowConfig.java @@ -86,4 +86,10 @@ public interface ClientWindowConfig */ String getClientWindowHtml(); + /** + * Restricts the number of active windows. + * + * @return limit for active windows + */ + int getMaxWindowContextCount(); } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/785ba0ad/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/DefaultClientWindowConfig.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/DefaultClientWindowConfig.java b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/DefaultClientWindowConfig.java index a13011e..8c90d99 100644 --- a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/DefaultClientWindowConfig.java +++ b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/DefaultClientWindowConfig.java @@ -28,6 +28,7 @@ import java.io.InputStream; import java.io.Serializable; import java.util.Map; +import org.apache.deltaspike.core.api.config.ConfigResolver; import org.apache.deltaspike.core.api.projectstage.ProjectStage; import org.apache.deltaspike.core.util.ClassUtils; import org.apache.deltaspike.core.util.ExceptionUtils; @@ -75,11 +76,15 @@ public class DefaultClientWindowConfig implements ClientWindowConfig, Serializab private ProjectStage projectStage; private ClientWindowRenderMode defaultClientWindowRenderMode; + private int maxWindowContextCount; @PostConstruct protected void init() { this.defaultClientWindowRenderMode = this.jsfModuleConfig.getDefaultWindowMode(); + + String maxCount = ConfigResolver.getPropertyValue("deltaspike.scope.window.max-count", "" + 64); + this.maxWindowContextCount = Integer.parseInt(maxCount); } @Override @@ -235,4 +240,10 @@ public class DefaultClientWindowConfig implements ClientWindowConfig, Serializab { return DEFAULT_WINDOW_HANDLER_HTML_FILE; } + + @Override + public int getMaxWindowContextCount() + { + return this.maxWindowContextCount; + } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/785ba0ad/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/JsfWindowContextQuotaHandler.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/JsfWindowContextQuotaHandler.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/JsfWindowContextQuotaHandler.java new file mode 100644 index 0000000..9d78f35 --- /dev/null +++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/JsfWindowContextQuotaHandler.java @@ -0,0 +1,40 @@ +/* + * 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.deltaspike.jsf.impl.scope.window; + +import org.apache.deltaspike.core.impl.scope.window.DefaultWindowContextQuotaHandler; +import org.apache.deltaspike.jsf.spi.scope.window.ClientWindowConfig; + +import javax.annotation.PostConstruct; +import javax.enterprise.inject.Specializes; +import javax.inject.Inject; + +@Specializes +public class JsfWindowContextQuotaHandler extends DefaultWindowContextQuotaHandler +{ + @Inject + private ClientWindowConfig clientWindowConfig; + + @Override + @PostConstruct + protected void init() + { + this.maxWindowContextCount = this.clientWindowConfig.getMaxWindowContextCount(); + } +}