Updated Branches: refs/heads/master 4e33427a1 -> db3605e8e
DELTASPIKE-488 @GroupedConversationScoped (first draft) Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/fca5cbd5 Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/fca5cbd5 Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/fca5cbd5 Branch: refs/heads/master Commit: fca5cbd5c43d769210a9decd94d5e7087a990679 Parents: 4e33427 Author: gpetracek <gpetra...@apache.org> Authored: Thu Jan 2 23:16:26 2014 +0100 Committer: gpetracek <gpetra...@apache.org> Committed: Fri Jan 3 00:10:54 2014 +0100 ---------------------------------------------------------------------- .../core/api/scope/ConversationGroup.java | 46 ++++++ .../core/api/scope/GroupedConversation.java | 26 +++ .../api/scope/GroupedConversationScoped.java | 39 +++++ .../GroupedConversationManager.java | 48 ++++++ .../core/util/context/AbstractContext.java | 3 +- .../util/context/ContextualInstanceInfo.java | 2 + .../core/impl/scope/AbstractBeanHolder.java | 93 +++++++++++ .../impl/scope/DeltaSpikeContextExtension.java | 81 ++++++++++ .../conversation/ConversationBeanHolder.java | 28 ++++ .../scope/conversation/ConversationKey.java | 161 +++++++++++++++++++ .../GroupedConversationArtifactProducer.java | 52 ++++++ .../GroupedConversationContext.java | 152 +++++++++++++++++ .../InjectableGroupedConversation.java | 50 ++++++ .../InjectableGroupedConversationManager.java | 67 ++++++++ .../window/DeltaSpikeContextExtension.java | 63 -------- .../scope/window/InjectableWindowContext.java | 1 + .../impl/scope/window/WindowBeanHolder.java | 91 +---------- .../impl/scope/window/WindowContextImpl.java | 2 +- .../scope/window/WindowContextProducer.java | 3 +- .../core/impl/util/ConversationUtils.java | 77 +++++++++ .../javax.enterprise.inject.spi.Extension | 2 +- 21 files changed, 932 insertions(+), 155 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/ConversationGroup.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/ConversationGroup.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/ConversationGroup.java new file mode 100644 index 0000000..1274392 --- /dev/null +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/ConversationGroup.java @@ -0,0 +1,46 @@ +/* + * 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.api.scope; + +import javax.inject.Qualifier; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target( { PARAMETER, FIELD, METHOD, CONSTRUCTOR, TYPE } ) +@Retention(RUNTIME) +@Documented + +@Qualifier +public @interface ConversationGroup +{ + /** + * Class or interface which should be used as type-safe key for identifying the conversation-group. + * + * @return class or interface which should be used as key + */ + Class<?> value(); +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/GroupedConversation.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/GroupedConversation.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/GroupedConversation.java new file mode 100644 index 0000000..6d8231b --- /dev/null +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/GroupedConversation.java @@ -0,0 +1,26 @@ +/* + * 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.api.scope; + +import java.io.Serializable; + +public interface GroupedConversation extends Serializable +{ + void close(); +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/GroupedConversationScoped.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/GroupedConversationScoped.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/GroupedConversationScoped.java new file mode 100644 index 0000000..5db9768 --- /dev/null +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/scope/GroupedConversationScoped.java @@ -0,0 +1,39 @@ +/* + * 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.api.scope; + +import javax.enterprise.context.NormalScope; +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target( { METHOD,TYPE,FIELD } ) +@Retention(RUNTIME) +@Inherited +@Documented +@NormalScope(passivating = true) +public @interface GroupedConversationScoped +{ +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/scope/conversation/GroupedConversationManager.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/scope/conversation/GroupedConversationManager.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/scope/conversation/GroupedConversationManager.java new file mode 100644 index 0000000..dfa0a49 --- /dev/null +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/spi/scope/conversation/GroupedConversationManager.java @@ -0,0 +1,48 @@ +/* + * 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.conversation; + +import org.apache.deltaspike.core.util.context.ContextualStorage; + +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.util.Set; + +public interface GroupedConversationManager extends Serializable +{ + /** + * @param conversationGroup group of the conversation in question + * @param qualifiers optional qualifiers for the conversation + * @return the removed conversation - null otherwise + */ + ContextualStorage closeConversation(Class<?> conversationGroup, Annotation... qualifiers); + + /** + * destroys all conversation of a group independent of the qualifiers + * + * @param conversationGroup group of the conversation in question + * @return the removed storages - null otherwise + */ + Set<ContextualStorage> closeConversationGroup(Class<?> conversationGroup); + + /** + * invalidate all conversations immediately (within the current window) + */ + void closeConversations(); +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/AbstractContext.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/AbstractContext.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/AbstractContext.java index 7be712c..11546ec 100644 --- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/AbstractContext.java +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/AbstractContext.java @@ -160,7 +160,7 @@ public abstract class AbstractContext implements Context * This is a static method to allow various holder objects to cleanup * properly in @PreDestroy. */ - public static void destroyAllActive(ContextualStorage storage) + public static Map<Object, ContextualInstanceInfo<?>> destroyAllActive(ContextualStorage storage) { //drop all entries in the storage before starting with destroying the original entries Map<Object, ContextualInstanceInfo<?>> contextMap = @@ -174,6 +174,7 @@ public abstract class AbstractContext implements Context ContextualInstanceInfo<?> contextualInstanceInfo = entry.getValue(); bean.destroy(contextualInstanceInfo.getContextualInstance(), contextualInstanceInfo.getCreationalContext()); } + return contextMap; } /** http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualInstanceInfo.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualInstanceInfo.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualInstanceInfo.java index b970cc0..3e26522 100644 --- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualInstanceInfo.java +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualInstanceInfo.java @@ -28,6 +28,8 @@ import java.io.Serializable; */ public class ContextualInstanceInfo<T> implements Serializable { + private static final long serialVersionUID = 6384932199958645324L; + /** * The actual Contextual Instance in the context */ http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/AbstractBeanHolder.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/AbstractBeanHolder.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/AbstractBeanHolder.java new file mode 100644 index 0000000..3648dd6 --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/AbstractBeanHolder.java @@ -0,0 +1,93 @@ +/* + * 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; + +import org.apache.deltaspike.core.util.context.AbstractContext; +import org.apache.deltaspike.core.util.context.ContextualStorage; + +import javax.annotation.PreDestroy; +import javax.enterprise.inject.spi.BeanManager; +import java.io.Serializable; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class AbstractBeanHolder<K> implements Serializable +{ + private Map<K, ContextualStorage> storageMap = new ConcurrentHashMap<K, ContextualStorage>(); + + private final boolean useConcurrentStorage; + private final boolean usePassivationCapableStorage; + + protected AbstractBeanHolder() + { + this(true, true); + } + + protected AbstractBeanHolder(boolean useConcurrentStorage, boolean usePassivationCapableStorage) + { + this.useConcurrentStorage = useConcurrentStorage; + this.usePassivationCapableStorage = usePassivationCapableStorage; + } + + public ContextualStorage getContextualStorage(BeanManager beanManager, K key, boolean createIfNotExist) + { + ContextualStorage contextualStorage = storageMap.get(key); + + if (contextualStorage == null && createIfNotExist) + { + contextualStorage = createContextualStorage(beanManager, key); + } + + return contextualStorage; + } + + protected synchronized ContextualStorage createContextualStorage(BeanManager beanManager, K key) + { + ContextualStorage contextualStorage = storageMap.get(key); + if (contextualStorage == null) + { + contextualStorage = new ContextualStorage(beanManager, useConcurrentStorage, usePassivationCapableStorage); + storageMap.put(key, contextualStorage); + } + return contextualStorage; + } + + public Map<K, ContextualStorage> getStorageMap() + { + return storageMap; + } + + public Map<K, ContextualStorage> forceNewStorage() + { + Map<K, ContextualStorage> oldStorageMap = storageMap; + storageMap = new ConcurrentHashMap<K, ContextualStorage>(); + return oldStorageMap; + } + + @PreDestroy + public void destroyBeans() + { + Map<K, ContextualStorage> oldWindowContextStorages = forceNewStorage(); + + for (ContextualStorage contextualStorage : oldWindowContextStorages.values()) + { + AbstractContext.destroyAllActive(contextualStorage); + } + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/DeltaSpikeContextExtension.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/DeltaSpikeContextExtension.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/DeltaSpikeContextExtension.java new file mode 100644 index 0000000..2e74c0f --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/DeltaSpikeContextExtension.java @@ -0,0 +1,81 @@ +/* + * 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; + +import javax.enterprise.event.Observes; +import javax.enterprise.inject.spi.AfterBeanDiscovery; +import javax.enterprise.inject.spi.AfterDeploymentValidation; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.Extension; + +import org.apache.deltaspike.core.api.provider.BeanProvider; +import org.apache.deltaspike.core.impl.scope.conversation.ConversationBeanHolder; +import org.apache.deltaspike.core.impl.scope.conversation.GroupedConversationContext; +import org.apache.deltaspike.core.impl.scope.window.WindowBeanHolder; +import org.apache.deltaspike.core.impl.scope.window.WindowContextImpl; +import org.apache.deltaspike.core.impl.scope.window.WindowIdHolder; + +/** + * Handle all DeltaSpike WindowContext and ConversationContext + * related features. + */ +public class DeltaSpikeContextExtension implements Extension +{ + private WindowContextImpl windowContext; + + private GroupedConversationContext conversationContext; + + public void registerDeltaSpikeContexts(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) + { + windowContext = new WindowContextImpl(beanManager); + conversationContext = new GroupedConversationContext(beanManager, windowContext); + afterBeanDiscovery.addContext(windowContext); + afterBeanDiscovery.addContext(conversationContext); + } + + /** + * We can only initialize our contexts in AfterDeploymentValidation because + * getBeans must not be invoked earlier than this phase to reduce randomness + * caused by Beans no being fully registered yet. + */ + public void initializeDeltaSpikeContexts(@Observes AfterDeploymentValidation adv, BeanManager beanManager) + { + WindowBeanHolder windowBeanHolder = + BeanProvider.getContextualReference(beanManager, WindowBeanHolder.class, false); + + WindowIdHolder windowIdHolder = + BeanProvider.getContextualReference(beanManager, WindowIdHolder.class, false); + + windowContext.init(windowBeanHolder, windowIdHolder); + + ConversationBeanHolder conversationBeanHolder = + BeanProvider.getContextualReference(beanManager, ConversationBeanHolder.class, false); + conversationContext.init(conversationBeanHolder); + } + + public WindowContextImpl getWindowContext() + { + return windowContext; + } + + public GroupedConversationContext getConversationContext() + { + return conversationContext; + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/ConversationBeanHolder.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/ConversationBeanHolder.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/ConversationBeanHolder.java new file mode 100644 index 0000000..5caf2fa --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/ConversationBeanHolder.java @@ -0,0 +1,28 @@ +/* + * 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.conversation; + +import org.apache.deltaspike.core.api.scope.WindowScoped; +import org.apache.deltaspike.core.impl.scope.AbstractBeanHolder; + +@WindowScoped +public class ConversationBeanHolder extends AbstractBeanHolder<ConversationKey> +{ + private static final long serialVersionUID = 6313493410718133308L; +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/ConversationKey.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/ConversationKey.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/ConversationKey.java new file mode 100644 index 0000000..378322b --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/ConversationKey.java @@ -0,0 +1,161 @@ +/* + * 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.conversation; + +import org.apache.deltaspike.core.api.scope.ConversationGroup; + +import javax.enterprise.inject.Any; +import javax.enterprise.inject.Default; +import javax.inject.Named; +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public class ConversationKey implements Serializable +{ + private static final long serialVersionUID = 6565204223928766263L; + + private final Class<?> groupKey; + + //HashSet due to Serializable warning in checkstyle rules + private HashSet<Annotation> qualifiers; + + public ConversationKey(Class<?> groupKey, Annotation... qualifiers) + { + this.groupKey = groupKey; + + //TODO maybe we have to add a real qualifier instead + Class<? extends Annotation> annotationType; + for (Annotation qualifier : qualifiers) + { + annotationType = qualifier.annotationType(); + + if (Any.class.isAssignableFrom(annotationType) || + Default.class.isAssignableFrom(annotationType) || + Named.class.isAssignableFrom(annotationType) || + ConversationGroup.class.isAssignableFrom(annotationType)) + { + //won't be used for this key! + continue; + } + + if (this.qualifiers == null) + { + this.qualifiers = new HashSet<Annotation>(); + } + this.qualifiers.add(qualifier); + } + } + + public Class<?> getConversationGroup() + { + return groupKey; + } + + public Set<Annotation> getQualifiers() + { + if (qualifiers == null) + { + return Collections.emptySet(); + } + return Collections.unmodifiableSet(this.qualifiers); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof ConversationKey)) + { + return false; + } + + ConversationKey that = (ConversationKey) o; + + if (!groupKey.equals(that.groupKey)) + { + return false; + } + if (qualifiers == null && that.qualifiers == null) + { + return true; + } + if (qualifiers != null && that.qualifiers == null) + { + return false; + } + + if (!that.qualifiers.equals(qualifiers)) + { + return false; + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() + { + int result = groupKey.hashCode(); + result = 31 * result + (qualifiers != null ? qualifiers.hashCode() : 0); + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() + { + StringBuilder result = new StringBuilder("conversation-key\n"); + + result.append("\n"); + result.append("\tgroup:\t\t"); + result.append(this.groupKey.getName()); + + result.append("\n"); + result.append("\tqualifiers:\t"); + + if (qualifiers != null) + { + for (Annotation qualifier : this.qualifiers) + { + result.append(qualifier.annotationType().getName()); + result.append(" "); + } + } + else + { + result.append("---"); + } + + return result.toString(); + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/GroupedConversationArtifactProducer.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/GroupedConversationArtifactProducer.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/GroupedConversationArtifactProducer.java new file mode 100644 index 0000000..fe387c7 --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/GroupedConversationArtifactProducer.java @@ -0,0 +1,52 @@ +/* + * 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.conversation; + +import org.apache.deltaspike.core.api.scope.GroupedConversation; +import org.apache.deltaspike.core.impl.scope.DeltaSpikeContextExtension; +import org.apache.deltaspike.core.impl.util.ConversationUtils; +import org.apache.deltaspike.core.spi.scope.conversation.GroupedConversationManager; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Dependent; +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.inject.Inject; + +@ApplicationScoped +public class GroupedConversationArtifactProducer +{ + @Inject + private DeltaSpikeContextExtension deltaSpikeContextExtension; + + @Produces + @Dependent + public GroupedConversationManager getGroupedConversationManager() + { + return new InjectableGroupedConversationManager(deltaSpikeContextExtension.getConversationContext()); + } + + @Produces + @Dependent + public GroupedConversation getGroupedConversation(InjectionPoint injectionPoint) + { + ConversationKey conversationKey = ConversationUtils.convertToConversationKey(injectionPoint.getBean()); + return new InjectableGroupedConversation(conversationKey, getGroupedConversationManager()); + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/GroupedConversationContext.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/GroupedConversationContext.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/GroupedConversationContext.java new file mode 100644 index 0000000..0724ae4 --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/GroupedConversationContext.java @@ -0,0 +1,152 @@ +/* + * 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.conversation; + +import org.apache.deltaspike.core.api.scope.GroupedConversationScoped; +import org.apache.deltaspike.core.impl.scope.window.WindowContextImpl; +import org.apache.deltaspike.core.impl.util.ConversationUtils; +import org.apache.deltaspike.core.spi.scope.conversation.GroupedConversationManager; +import org.apache.deltaspike.core.util.context.AbstractContext; +import org.apache.deltaspike.core.util.context.ContextualStorage; + +import javax.enterprise.context.spi.Contextual; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.Typed; +import javax.enterprise.inject.spi.BeanManager; +import java.lang.annotation.Annotation; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +@Typed() +//TODO add RequestCache +//TODO ConversationSubGroup +public class GroupedConversationContext extends AbstractContext implements GroupedConversationManager +{ + private static final long serialVersionUID = -5463564406828391468L; + + @Deprecated //TODO remove it once DELTASPIKE-489 is fixed + private static ThreadLocal<Contextual<?>> currentContextual = new ThreadLocal<Contextual<?>>(); + + private final BeanManager beanManager; + + private final WindowContextImpl windowContext; + + private ConversationBeanHolder conversationBeanHolder; + + public GroupedConversationContext(BeanManager beanManager, WindowContextImpl windowContext) + { + super(beanManager); + + this.beanManager = beanManager; + this.windowContext = windowContext; + } + + public void init(ConversationBeanHolder conversationBeanHolder) + { + this.conversationBeanHolder = conversationBeanHolder; + } + + @Override + public <T> T get(Contextual<T> bean) + { + try + { + currentContextual.set(bean); + return super.get(bean); + } + finally + { + currentContextual.set(null); + currentContextual.remove(); + } + } + + @Override + public <T> T get(Contextual<T> bean, CreationalContext<T> creationalContext) + { + try + { + currentContextual.set(bean); + return super.get(bean, creationalContext); + } + finally + { + currentContextual.set(null); + currentContextual.remove(); + } + } + + @Override + protected ContextualStorage getContextualStorage(boolean createIfNotExist) + { + ConversationKey conversationKey = ConversationUtils.convertToConversationKey(currentContextual.get()); + return this.conversationBeanHolder.getContextualStorage(beanManager, conversationKey, createIfNotExist); + } + + @Override + public Class<? extends Annotation> getScope() + { + return GroupedConversationScoped.class; + } + + @Override + public boolean isActive() + { + return this.windowContext.isActive(); //autom. active once a window is active + } + + @Override + public ContextualStorage closeConversation(Class<?> conversationGroup, Annotation... qualifiers) + { + ConversationKey conversationKey = new ConversationKey(conversationGroup, qualifiers); + ContextualStorage contextualStorage = this.conversationBeanHolder.getStorageMap().remove(conversationKey); + + if (contextualStorage != null) + { + AbstractContext.destroyAllActive(contextualStorage); + } + + return contextualStorage; + } + + @Override + public Set<ContextualStorage> closeConversationGroup(Class<?> conversationGroup) + { + Set<ContextualStorage> result = new HashSet<ContextualStorage>(); + + Map<ConversationKey, ContextualStorage> storageMap = this.conversationBeanHolder.getStorageMap(); + for (Map.Entry<ConversationKey, ContextualStorage> entry : storageMap.entrySet()) + { + if (entry.getKey().getConversationGroup().equals(conversationGroup)) + { + AbstractContext.destroyAllActive(entry.getValue()); + result.add(entry.getValue()); + storageMap.remove(entry.getKey()); //ok due to ConcurrentHashMap + } + } + return result; + } + + @Override + public void closeConversations() + { + this.conversationBeanHolder.destroyBeans(); + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/InjectableGroupedConversation.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/InjectableGroupedConversation.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/InjectableGroupedConversation.java new file mode 100644 index 0000000..4805aa6 --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/InjectableGroupedConversation.java @@ -0,0 +1,50 @@ +/* + * 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.conversation; + +import org.apache.deltaspike.core.api.scope.GroupedConversation; +import org.apache.deltaspike.core.spi.scope.conversation.GroupedConversationManager; + +import javax.enterprise.inject.Typed; +import java.lang.annotation.Annotation; +import java.util.Set; + +@Typed() +class InjectableGroupedConversation implements GroupedConversation +{ + private static final long serialVersionUID = -3909049219127821425L; + + private final ConversationKey conversationKey; + private final GroupedConversationManager conversationManager; + + InjectableGroupedConversation(ConversationKey conversationKey, GroupedConversationManager conversationManager) + { + this.conversationManager = conversationManager; + this.conversationKey = conversationKey; + } + + @Override + public void close() + { + Set<Annotation> qualifiers = this.conversationKey.getQualifiers(); + + this.conversationManager.closeConversation( + this.conversationKey.getConversationGroup(), qualifiers.toArray(new Annotation[qualifiers.size()])); + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/InjectableGroupedConversationManager.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/InjectableGroupedConversationManager.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/InjectableGroupedConversationManager.java new file mode 100644 index 0000000..f88d491 --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/conversation/InjectableGroupedConversationManager.java @@ -0,0 +1,67 @@ +/* + * 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.conversation; + +import org.apache.deltaspike.core.api.provider.BeanProvider; +import org.apache.deltaspike.core.impl.scope.DeltaSpikeContextExtension; +import org.apache.deltaspike.core.spi.scope.conversation.GroupedConversationManager; +import org.apache.deltaspike.core.util.context.ContextualStorage; + +import javax.enterprise.inject.Typed; +import java.lang.annotation.Annotation; +import java.util.Set; + +@Typed() +class InjectableGroupedConversationManager implements GroupedConversationManager +{ + private transient volatile GroupedConversationManager conversationManager; + + public InjectableGroupedConversationManager(GroupedConversationManager conversationManager) + { + this.conversationManager = conversationManager; + } + + private GroupedConversationManager getConversationManager() + { + if (this.conversationManager == null) + { + this.conversationManager = + BeanProvider.getContextualReference(DeltaSpikeContextExtension.class).getConversationContext(); + } + return conversationManager; + } + + @Override + public ContextualStorage closeConversation(Class<?> conversationGroup, Annotation... qualifiers) + { + return getConversationManager().closeConversation(conversationGroup, qualifiers); + } + + @Override + public Set<ContextualStorage> closeConversationGroup(Class<?> conversationGroup) + { + return getConversationManager().closeConversationGroup(conversationGroup); + } + + @Override + public void closeConversations() + { + getConversationManager().closeConversations(); + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/DeltaSpikeContextExtension.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/DeltaSpikeContextExtension.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/DeltaSpikeContextExtension.java deleted file mode 100644 index ad8186e..0000000 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/DeltaSpikeContextExtension.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 javax.enterprise.event.Observes; -import javax.enterprise.inject.spi.AfterBeanDiscovery; -import javax.enterprise.inject.spi.AfterDeploymentValidation; -import javax.enterprise.inject.spi.BeanManager; -import javax.enterprise.inject.spi.Extension; - -import org.apache.deltaspike.core.api.provider.BeanProvider; - -/** - * Handle all DeltaSpike WindowContext and ConversationContext - * related features. - */ -public class DeltaSpikeContextExtension implements Extension -{ - private WindowContextImpl windowContext; - - public void registerDeltaSpikeContexts(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) - { - windowContext = new WindowContextImpl(beanManager); - afterBeanDiscovery.addContext(windowContext); - } - - /** - * We can only initialize our contexts in AfterDeploymentValidation because - * getBeans must not be invoked earlier than this phase to reduce randomness - * caused by Beans no being fully registered yet. - */ - public void initializeDeltaSpikeContexts(@Observes AfterDeploymentValidation adv, BeanManager beanManager) - { - WindowBeanHolder windowBeanHolder - = BeanProvider.getContextualReference(beanManager, WindowBeanHolder.class, false); - - WindowIdHolder windowIdHolder - = BeanProvider.getContextualReference(beanManager, WindowIdHolder.class, false); - - windowContext.initWindowContext(windowBeanHolder, windowIdHolder); - } - - public WindowContextImpl getWindowContext() - { - return windowContext; - } -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/InjectableWindowContext.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/InjectableWindowContext.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/InjectableWindowContext.java index 4263c8e..f5f3945 100644 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/InjectableWindowContext.java +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/InjectableWindowContext.java @@ -19,6 +19,7 @@ package org.apache.deltaspike.core.impl.scope.window; import org.apache.deltaspike.core.api.provider.BeanProvider; +import org.apache.deltaspike.core.impl.scope.DeltaSpikeContextExtension; import org.apache.deltaspike.core.spi.scope.window.WindowContext; import javax.enterprise.inject.Typed; http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/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 a94966f..a83e0bd 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 @@ -18,15 +18,9 @@ */ package org.apache.deltaspike.core.impl.scope.window; -import javax.annotation.PreDestroy; -import javax.enterprise.context.SessionScoped; -import javax.enterprise.inject.spi.BeanManager; -import java.io.Serializable; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import org.apache.deltaspike.core.impl.scope.AbstractBeanHolder; -import org.apache.deltaspike.core.util.context.AbstractContext; -import org.apache.deltaspike.core.util.context.ContextualStorage; +import javax.enterprise.context.SessionScoped; /** * This holder will store the window Ids and it's beans for the current @@ -34,86 +28,7 @@ import org.apache.deltaspike.core.util.context.ContextualStorage; * to treat async-supported and similar headache. */ @SessionScoped -public class WindowBeanHolder implements Serializable +public class WindowBeanHolder extends AbstractBeanHolder<String> { private static final long serialVersionUID = 6313493410718133308L; - - /** - * key: the windowId for the browser tab or window - * value: the {@link ContextualStorage} which holds all the - * {@link javax.enterprise.inject.spi.Bean}s. - */ - private Map<String, ContextualStorage> storageMap = new ConcurrentHashMap<String, ContextualStorage>(); - - /** - * This method will return the ContextualStorage or create a new one - * if no one is yet assigned to the current windowId. - * @param beanManager we need the CDI {@link javax.enterprise.inject.spi.BeanManager} for serialisation. - * @param windowId the windowId for the current browser tab or window. - * @param createIfNotExist true if a new storage should get created (if it doesn't exist already), false otherwise - */ - public ContextualStorage getContextualStorage(BeanManager beanManager, String windowId, boolean createIfNotExist) - { - ContextualStorage contextualStorage = storageMap.get(windowId); - if (contextualStorage == null && createIfNotExist) - { - contextualStorage = createContextualStorage(beanManager, windowId); - } - - return contextualStorage; - } - - private synchronized ContextualStorage createContextualStorage(BeanManager beanManager, String windowId) - { - ContextualStorage contextualStorage = storageMap.get(windowId); - if (contextualStorage == null) - { - contextualStorage = new ContextualStorage(beanManager, true, true); - storageMap.put(windowId, contextualStorage); - } - return contextualStorage; - } - - public Map<String, ContextualStorage> getStorageMap() - { - return storageMap; - } - - /** - * - * This method will replace the storageMap and with - * a new empty one. - * This method can be used to properly destroy the WindowBeanHolder beans - * without having to sync heavily. Any - * {@link javax.enterprise.inject.spi.Bean#destroy(Object, javax.enterprise.context.spi.CreationalContext)} - * should be performed on the returned old storage map. - * @return the old storageMap. - */ - public Map<String, ContextualStorage> forceNewStorage() - { - Map<String, ContextualStorage> oldStorageMap = storageMap; - storageMap = new ConcurrentHashMap<String, ContextualStorage>(); - return oldStorageMap; - } - - /** - * This method properly destroys all current @WindowScoped beans - * of the active session and also prepares the storage for new beans. - * It will automatically get called when the session context closes - * but can also get invoked manually, e.g. if a user likes to get rid - * of all it's @WindowScoped beans. - */ - @PreDestroy - public void destroyBeans() - { - // we replace the old windowBeanHolder beans with a new storage Map - // an afterwards destroy the old Beans without having to care about any syncs. - Map<String, ContextualStorage> oldWindowContextStorages = forceNewStorage(); - - for (ContextualStorage contextualStorage : oldWindowContextStorages.values()) - { - AbstractContext.destroyAllActive(contextualStorage); - } - - } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextImpl.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextImpl.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextImpl.java index ce63708..10faa7b 100644 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextImpl.java +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextImpl.java @@ -65,7 +65,7 @@ public class WindowContextImpl extends AbstractContext implements WindowContext * requestscoped windowIdHolder in a later phase because * getBeans is only allowed from AfterDeploymentValidation onwards. */ - void initWindowContext(WindowBeanHolder windowBeanHolder, WindowIdHolder windowIdHolder) + public void init(WindowBeanHolder windowBeanHolder, WindowIdHolder windowIdHolder) { this.windowBeanHolder = windowBeanHolder; this.windowIdHolder = windowIdHolder; http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextProducer.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextProducer.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextProducer.java index 2f1e686..46d8d31 100644 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextProducer.java +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/scope/window/WindowContextProducer.java @@ -23,13 +23,14 @@ import javax.enterprise.context.Dependent; import javax.enterprise.inject.Produces; import javax.inject.Inject; +import org.apache.deltaspike.core.impl.scope.DeltaSpikeContextExtension; import org.apache.deltaspike.core.spi.scope.window.WindowContext; /** * This producer provides access to the internally created * {@link WindowContext} implementation. * It simply wraps through to the instance used in the - * {@link DeltaSpikeContextExtension}. + * {@link org.apache.deltaspike.core.impl.scope.DeltaSpikeContextExtension}. */ @ApplicationScoped public class WindowContextProducer http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/util/ConversationUtils.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/util/ConversationUtils.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/util/ConversationUtils.java new file mode 100644 index 0000000..08e4028 --- /dev/null +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/util/ConversationUtils.java @@ -0,0 +1,77 @@ +/* + * 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.util; + +import org.apache.deltaspike.core.api.scope.ConversationGroup; +import org.apache.deltaspike.core.impl.scope.conversation.ConversationKey; + +import javax.enterprise.context.spi.Contextual; +import javax.enterprise.inject.Typed; +import javax.enterprise.inject.spi.Bean; +import java.lang.annotation.Annotation; +import java.util.Set; + +@Typed() +public abstract class ConversationUtils +{ + private ConversationUtils() + { + } + + public static ConversationKey convertToConversationKey(Contextual<?> contextual) + { + if (!(contextual instanceof Bean)) + { + throw new IllegalArgumentException( + contextual.getClass().getName() + " is not of type " + Bean.class.getName()); + } + + Bean<?> bean = (Bean<?>) contextual; + + //don't cache it (due to the support of different producers) + ConversationGroup conversationGroupAnnotation = findConversationGroupAnnotation(bean); + + Class<?> conversationGroup; + if (conversationGroupAnnotation != null) + { + conversationGroup = conversationGroupAnnotation.value(); + } + else + { + conversationGroup = bean.getBeanClass(); + } + + Set<Annotation> qualifiers = bean.getQualifiers(); + return new ConversationKey(conversationGroup, qualifiers.toArray(new Annotation[qualifiers.size()])); + } + + private static ConversationGroup findConversationGroupAnnotation(Bean<?> bean) + { + Set<Annotation> qualifiers = bean.getQualifiers(); + + for (Annotation qualifier : qualifiers) + { + if (ConversationGroup.class.isAssignableFrom(qualifier.annotationType())) + { + return (ConversationGroup) qualifier; + } + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/fca5cbd5/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension index 666a6b6..a943098 100644 --- a/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension +++ b/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension @@ -22,4 +22,4 @@ org.apache.deltaspike.core.impl.message.MessageBundleExtension org.apache.deltaspike.core.impl.exception.control.extension.ExceptionControlExtension org.apache.deltaspike.core.impl.config.ConfigurationExtension org.apache.deltaspike.core.impl.jmx.MBeanExtension -org.apache.deltaspike.core.impl.scope.window.DeltaSpikeContextExtension +org.apache.deltaspike.core.impl.scope.DeltaSpikeContextExtension