/*
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
*
* Licensed 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.drools.core.impl;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.kie.api.runtime.Environment;
import org.kie.api.runtime.KieSession;
public class EnvironmentImpl implements Environment {
// The default concurrencyLevel is 16: if users have enough threads
// that (16^(1.5))=64 *concurrent* updates are possible/likely
// then the concurrencyLevel will need to be upgraded,
// but that situation is fairly unlikely
private Map<String, Object> environment = new NullValueConcurrentHashMap<String, Object>();
private Environment delegate;
public void setDelegate(Environment delegate) {
this.delegate = delegate;
}
public Object get(String identifier) {
Object object = environment.get(identifier);
if ( object == null && delegate != null ) {
object = this.delegate.get( identifier );
}
return object;
}
public void set(String name, Object object) {
environment.put(name, object);
}
/**
* This class adds the possibility of storing null values in the {@link ConcurrentHashMap},
* since storing null values in an {@link Environment} is something that happens in the kie code.
*
* This class is needed for the {@link Environment} implementation since happens-before is
* not guaranteed with a normal {@link HashMap}. Not having guaranteed happens-before can lead to
* race-conditions, especially when using a {@link KieSession} as a Singleton in a multi-threaded
* environment.
*
* @param <K> The key type
* @param <V> The value type
*/
private static class NullValueConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
private static Object NULL = new Object();
public V put(K key, V value) {
if (value != null) {
value = super.put(key, value);
} else {
value = super.put(key, (V) NULL);
if (value == NULL) {
return null;
}
}
return value;
}
public V get(Object key) {
Object value = super.get(key);
if (value == NULL) {
return null;
}
return (V) value;
}
public boolean containsValue(Object value) {
if( value == null ) {
return super.containsValue(NULL);
}
return super.containsValue(value);
}
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException("The putAll(Map<K, V> m) method is not supported on this implementation.");
}
public Collection<V> values() {
throw new UnsupportedOperationException("The values() method is not supported on this implementation.");
}
public Set<Map.Entry<K, V>> entrySet() {
throw new UnsupportedOperationException("The entrySet() method is not supported on this implementation.");
}
}
}