Author: mstruk
Date: 2011-10-03 11:17:29 -0400 (Mon, 03 Oct 2011)
New Revision: 7608
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/
sandbox/as7_support/branches/gatein-as7/gatein-naming/pom.xml
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/AtomicMapFieldUpdater.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InMemoryNamingStore.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InitialContextFactory.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InitialContextFactoryBuilder.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingContext.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingEventCoordinator.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingStore.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/context/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/context/ObjectFactoryBuilder.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/context/SecurityActions.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/interfaces/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/interfaces/java/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/interfaces/java/javaURLContextFactory.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/FastCopyHashMap.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/NameParser.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/NamingUtils.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/SecurityActions.java
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/resources/
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/resources/jndi.properties
Log:
Add gatein-naming
Added: sandbox/as7_support/branches/gatein-as7/gatein-naming/pom.xml
===================================================================
--- sandbox/as7_support/branches/gatein-as7/gatein-naming/pom.xml
(rev 0)
+++ sandbox/as7_support/branches/gatein-as7/gatein-naming/pom.xml 2011-10-03 15:17:29 UTC
(rev 7608)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.gatein</groupId>
+ <artifactId>gatein-parent</artifactId>
+ <version>1.1.0-Beta02</version>
+ </parent>
+
+ <name>GateIn Naming</name>
+ <groupId>org.gatein.naming</groupId>
+ <artifactId>gatein-naming</artifactId>
+ <version>1.0.0-Beta01</version>
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <version>3.0.0.GA</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.threads</groupId>
+ <artifactId>jboss-threads</artifactId>
+ <version>2.0.0.GA</version>
+ </dependency>
+ </dependencies>
+</project>
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/AtomicMapFieldUpdater.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/AtomicMapFieldUpdater.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/AtomicMapFieldUpdater.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,211 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming;
+
+import org.gatein.naming.util.FastCopyHashMap;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+/**
+ * @author <a href="mailto:david.lloyd@redhat.com">David M.
Lloyd</a>
+ */
+final class AtomicMapFieldUpdater<C, K, V> {
+ private final AtomicReferenceFieldUpdater<C, Map<K, V>> updater;
+
+ @SuppressWarnings( { "unchecked" })
+ public static <C, K, V> AtomicMapFieldUpdater<C, K, V>
newMapUpdater(AtomicReferenceFieldUpdater<C, Map> updater) {
+ return new AtomicMapFieldUpdater<C, K, V>(updater);
+ }
+
+ @SuppressWarnings( { "unchecked" })
+ AtomicMapFieldUpdater(AtomicReferenceFieldUpdater<C, Map> updater) {
+ this.updater = (AtomicReferenceFieldUpdater) updater;
+ }
+
+ public void clear(C instance) {
+ updater.set(instance, Collections.<K, V>emptyMap());
+ }
+
+ public V get(C instance, Object key) {
+ return updater.get(instance).get(key);
+ }
+
+ public V put(C instance, K key, V value) {
+ if (key == null) {
+ throw new IllegalArgumentException("key is null");
+ }
+ for (;;) {
+ final Map<K, V> oldMap = updater.get(instance);
+ final Map<K, V> newMap;
+ final V oldValue;
+ final int oldSize = oldMap.size();
+ if (oldSize == 0) {
+ oldValue = null;
+ newMap = Collections.singletonMap(key, value);
+ } else if (oldSize == 1) {
+ final Map.Entry<K, V> entry = oldMap.entrySet().iterator().next();
+ final K oldKey = entry.getKey();
+ if (oldKey.equals(key)) {
+ newMap = Collections.singletonMap(key, value);
+ oldValue = entry.getValue();
+ } else {
+ newMap = new FastCopyHashMap<K, V>(oldMap);
+ oldValue = newMap.put(key, value);
+ }
+ } else {
+ newMap = new FastCopyHashMap<K, V>(oldMap);
+ oldValue = newMap.put(key, value);
+ }
+ final boolean result = updater.compareAndSet(instance, oldMap, newMap);
+ if (result) {
+ return oldValue;
+ }
+ }
+ }
+
+ /**
+ * Put a value if and only if the map has not changed since the given snapshot was
taken.
+ *
+ * @param instance the instance with the map field
+ * @param key the key
+ * @param value the value
+ * @param snapshot the map snapshot
+ * @return {@code value} if the snapshot is out of date, {@code null} if it
succeeded, the existing value if the put failed
+ */
+ public V putAtomic(C instance, K key, V value, Map<K, V> snapshot) {
+ if (key == null) {
+ throw new IllegalArgumentException("key is null");
+ }
+ final Map<K, V> newMap;
+ final int oldSize = snapshot.size();
+ if (oldSize == 0) {
+ newMap = Collections.singletonMap(key, value);
+ } else if (oldSize == 1) {
+ final Map.Entry<K, V> entry = snapshot.entrySet().iterator().next();
+ final K oldKey = entry.getKey();
+ if (oldKey.equals(key)) {
+ return entry.getValue();
+ } else {
+ newMap = new FastCopyHashMap<K, V>(snapshot);
+ newMap.put(key, value);
+ }
+ } else {
+ newMap = new FastCopyHashMap<K, V>(snapshot);
+ newMap.put(key, value);
+ }
+ if (updater.compareAndSet(instance, snapshot, newMap)) {
+ return null;
+ } else {
+ return value;
+ }
+ }
+
+ public V putIfAbsent(C instance, K key, V value) {
+ if (key == null) {
+ throw new IllegalArgumentException("key is null");
+ }
+ for (;;) {
+ final Map<K, V> oldMap = updater.get(instance);
+ final Map<K, V> newMap;
+ final int oldSize = oldMap.size();
+ if (oldSize == 0) {
+ newMap = Collections.singletonMap(key, value);
+ } else if (oldSize == 1) {
+ final Map.Entry<K, V> entry = oldMap.entrySet().iterator().next();
+ final K oldKey = entry.getKey();
+ if (oldKey.equals(key)) {
+ return entry.getValue();
+ } else {
+ newMap = new FastCopyHashMap<K, V>(oldMap);
+ newMap.put(key, value);
+ }
+ } else {
+ if (oldMap.containsKey(key)) {
+ return oldMap.get(key);
+ }
+ newMap = new FastCopyHashMap<K, V>(oldMap);
+ newMap.put(key, value);
+ }
+ if (updater.compareAndSet(instance, oldMap, newMap)) {
+ return null;
+ }
+ }
+ }
+
+ public V remove(C instance, K key) {
+ if (key == null) {
+ return null;
+ }
+ for (;;) {
+ final Map<K, V> oldMap = updater.get(instance);
+ final Map<K, V> newMap;
+ final V oldValue;
+ final int oldSize = oldMap.size();
+ if (oldSize == 0) {
+ return null;
+ } else if (oldSize == 1) {
+ final Map.Entry<K, V> entry = oldMap.entrySet().iterator().next();
+ if (entry.getKey().equals(key)) {
+ newMap = Collections.emptyMap();
+ oldValue = entry.getValue();
+ } else {
+ return null;
+ }
+ } else if (oldSize == 2) {
+ final Iterator<Map.Entry<K,V>> i =
oldMap.entrySet().iterator();
+ final Map.Entry<K, V> entry = i.next();
+ final Map.Entry<K, V> next = i.next();
+ if (entry.getKey().equals(key)) {
+ newMap = Collections.singletonMap(next.getKey(), next.getValue());
+ oldValue = entry.getValue();
+ } else if (next.getKey().equals(key)) {
+ newMap = Collections.singletonMap(entry.getKey(), entry.getValue());
+ oldValue = next.getValue();
+ } else {
+ return null;
+ }
+ } else {
+ if (! oldMap.containsKey(key)) {
+ return null;
+ }
+ newMap = new FastCopyHashMap<K, V>(oldMap);
+ oldValue = newMap.remove(key);
+ }
+ if (updater.compareAndSet(instance, oldMap, newMap)) {
+ return oldValue;
+ }
+ }
+ }
+
+ public Map<K, V> get(final C subregistry) {
+ return updater.get(subregistry);
+ }
+
+ public Map<K, V> getReadOnly(final C subregistry) {
+ final Map<K, V> snapshot = updater.get(subregistry);
+ return snapshot instanceof FastCopyHashMap ?
Collections.unmodifiableMap(snapshot) : snapshot;
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InMemoryNamingStore.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InMemoryNamingStore.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InMemoryNamingStore.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,504 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming;
+
+import javax.naming.Binding;
+import javax.naming.CannotProceedException;
+import javax.naming.CompositeName;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.event.EventContext;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingListener;
+import javax.naming.spi.ResolveResult;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.util.concurrent.locks.ReentrantLock;
+
+import static org.gatein.naming.util.NamingUtils.*;
+
+
+/**
+ * In-memory implementation of the NamingStore. The backing for the entries is a basic
tree structure with either context
+ * nodes or binding nodes. The context nodes are allowed to have children and can be
represented by a NamingContext. A
+ * binding node is only allowed to have a normal object binding.
+ *
+ * @author John E. Bailey
+ */
+public class InMemoryNamingStore implements NamingStore {
+
+ /* The root node of the tree. Represents a JNDI name of "" */
+ private final ContextNode root = new ContextNode(null, null, new CompositeName(), new
NamingContext(this, null));
+
+ /* Naming Event Coordinator */
+ private final NamingEventCoordinator eventCoordinator;
+
+ private final ReentrantLock writeLock = new ReentrantLock();
+
+ /**
+ * Construct instance with no event support.
+ */
+ public InMemoryNamingStore() {
+ this(null);
+ }
+
+ /**
+ * Construct instance with an event coordinator.
+ *
+ * @param eventCoordinator The event coordinator
+ */
+ public InMemoryNamingStore(final NamingEventCoordinator eventCoordinator) {
+ this.eventCoordinator = eventCoordinator;
+ }
+
+ /** {@inheritDoc} */
+ public void bind(Name name, Object object) throws NamingException {
+ bind(name, object, object.getClass());
+ }
+
+ /** {@inheritDoc} */
+ public void bind(final Name name, final Object object, final Class<?> bindType)
throws NamingException {
+ if (isLastComponentEmpty(name)) {
+ throw emptyNameException();
+ }
+
+ writeLock.lock();
+ try {
+ root.accept(new BindVisitor(true, name, object, bindType.getName()));
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void rebind(Name name, Object object) throws NamingException {
+ rebind(name, object, object.getClass());
+ }
+
+ /** {@inheritDoc} */
+ public void rebind(final Name name, final Object object, final Class<?>
bindType) throws NamingException {
+ if (isLastComponentEmpty(name)) {
+ throw emptyNameException();
+ }
+
+ writeLock.lock();
+ try {
+ root.accept(new RebindVisitor(name, object, bindType.getName()));
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ /**
+ * Unbind the entry in the provided location. This will remove the node in the tree
and no longer manage it.
+ *
+ * @param name The entry name
+ * @throws javax.naming.NamingException
+ */
+ public void unbind(final Name name) throws NamingException {
+ if (isLastComponentEmpty(name)) {
+ throw emptyNameException();
+ }
+
+ writeLock.lock();
+ try {
+ root.accept(new UnbindVisitor(name));
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ /**
+ * Lookup the object value of a binding node in the tree.
+ *
+ * @param name The entry name
+ * @return The object value of the binding
+ * @throws javax.naming.NamingException
+ */
+ public Object lookup(final Name name) throws NamingException {
+ if (isEmpty(name)) {
+ final Name emptyName = new CompositeName("");
+ return new NamingContext(emptyName, this, new Hashtable<String,
Object>());
+ }
+ return root.accept(new LookupVisitor(name));
+ }
+
+ /**
+ * List all NameClassPair instances at a given location in the tree.
+ *
+ * @param name The entry name
+ * @return The NameClassPair instances
+ * @throws javax.naming.NamingException
+ */
+ public List<NameClassPair> list(final Name name) throws NamingException {
+ final Name nodeName = name.isEmpty() ? new CompositeName("") : name;
+ return root.accept(new ListVisitor(nodeName));
+ }
+
+ /**
+ * List all the Binding instances at a given location in the tree.
+ *
+ * @param name The entry name
+ * @return The Binding instances
+ * @throws javax.naming.NamingException
+ */
+ public List<Binding> listBindings(final Name name) throws NamingException {
+ final Name nodeName = name.isEmpty() ? new CompositeName("") : name;
+ return root.accept(new ListBindingsVisitor(name));
+ }
+
+ /**
+ * Close the store. This will clear all children from the root node.
+ *
+ * @throws javax.naming.NamingException
+ */
+ public void close() throws NamingException {
+ writeLock.lock();
+ try {
+ root.clear();
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ /**
+ * Add a {@code NamingListener} to the naming event coordinator.
+ *
+ * @param target The target name to add the listener to
+ * @param scope The listener scope
+ * @param listener The listener
+ */
+ public void addNamingListener(final Name target, final int scope, final
NamingListener listener) {
+ final NamingEventCoordinator coordinator = eventCoordinator;
+ if (coordinator != null) {
+ coordinator.addListener(target.toString(), scope, listener);
+ }
+ }
+
+ /**
+ * Remove a {@code NamingListener} from the naming event coordinator.
+ *
+ * @param listener The listener
+ */
+ public void removeNamingListener(final NamingListener listener) {
+ final NamingEventCoordinator coordinator = eventCoordinator;
+ if (coordinator != null) {
+ coordinator.removeListener(listener);
+ }
+ }
+
+ private void fireEvent(final ContextNode contextNode, final Name name, final Binding
existingBinding, final Binding newBinding, final int type, final String changeInfo) {
+ final NamingEventCoordinator coordinator = eventCoordinator;
+ if (eventCoordinator != null) {
+ final Context context = Context.class.cast(contextNode.binding.getObject());
+ if(context instanceof EventContext) {
+ coordinator.fireEvent(EventContext.class.cast(context), name,
existingBinding, newBinding, type, changeInfo, NamingEventCoordinator.DEFAULT_SCOPES);
+ }
+ }
+ }
+
+ private void checkReferenceForContinuation(final Name name, final Object object)
throws CannotProceedException {
+ if (object instanceof Reference) {
+ if (((Reference) object).get("nns") != null) {
+ throw cannotProceedException(object, name);
+ }
+ }
+ }
+
+ private abstract class TreeNode {
+ protected final Name fullName;
+ protected final Binding binding;
+
+ private TreeNode(final Name fullName, final Binding binding) {
+ this.fullName = fullName;
+ this.binding = binding;
+ }
+
+ protected abstract <T> T accept(NodeVisitor<T> visitor) throws
NamingException;
+ }
+
+ private static final AtomicMapFieldUpdater<ContextNode, String, TreeNode>
childrenUpdater =
AtomicMapFieldUpdater.newMapUpdater(AtomicReferenceFieldUpdater.newUpdater(ContextNode.class,
Map.class, "children"));
+
+ private class ContextNode extends TreeNode {
+ volatile Map<String, TreeNode> children = Collections.emptyMap();
+ protected final String name;
+ protected final ContextNode parentNode;
+
+ private ContextNode(final ContextNode parentNode, final String name, final Name
fullName, final NamingContext context) {
+ super(fullName, new Binding(getLastComponent(fullName),
Context.class.getName(), context));
+ this.name = name;
+ this.parentNode = parentNode;
+ }
+
+ private void addChild(final String childName, final TreeNode childNode) throws
NamingException {
+ if (childrenUpdater.putIfAbsent(this, childName, childNode) != null) {
+ throw nameAlreadyBoundException(fullName.add(childName));
+ }
+ }
+
+ private TreeNode replaceChild(final String childName, final TreeNode childNode)
throws NamingException {
+ return childrenUpdater.put(this, childName, childNode);
+ }
+
+ private TreeNode removeChild(final String childName) throws NameNotFoundException
{
+ TreeNode old = childrenUpdater.remove(this, childName);
+ if (old == null) {
+ throw nameNotFoundException(childName, fullName);
+ }
+ if(parentNode != null && children.isEmpty()) {
+ childrenUpdater.remove(parentNode, name);
+ }
+ return old;
+ }
+
+ private void clear() {
+ childrenUpdater.clear(this);
+ }
+
+ protected final <T> T accept(NodeVisitor<T> visitor) throws
NamingException {
+ return visitor.visit(this);
+ }
+
+ public TreeNode addOrGetChild(final String childName, final TreeNode childNode)
{
+ TreeNode appearing = childrenUpdater.putIfAbsent(this, childName,
childNode);
+ return appearing == null ? childNode : appearing;
+ }
+ }
+
+ private class BindingNode extends TreeNode {
+ private BindingNode(final Name fullName, final Binding binding) {
+ super(fullName, binding);
+ }
+
+ protected final <T> T accept(NodeVisitor<T> visitor) throws
NamingException {
+ return visitor.visit(this);
+ }
+ }
+
+ private interface NodeVisitor<T> {
+ T visit(BindingNode bindingNode) throws NamingException;
+
+ T visit(ContextNode contextNode) throws NamingException;
+ }
+
+ private abstract class NodeTraversingVisitor<T> implements NodeVisitor<T>
{
+ private final boolean createIfMissing;
+ private Name currentName;
+ private Name traversedName;
+ protected final Name targetName;
+
+ protected NodeTraversingVisitor(final boolean createIfMissing, final Name
targetName) {
+ this.createIfMissing = createIfMissing;
+ this.targetName = currentName = targetName;
+ this.traversedName = new CompositeName();
+ }
+
+ protected NodeTraversingVisitor(final Name targetName) {
+ this(false, targetName);
+ }
+
+ public final T visit(final BindingNode bindingNode) throws NamingException {
+ if (isEmpty(currentName)) {
+ return found(bindingNode);
+ }
+ return foundReferenceInsteadOfContext(bindingNode);
+ }
+
+ public final T visit(final ContextNode contextNode) throws NamingException {
+ if (isEmpty(currentName)) {
+ return found(contextNode);
+ }
+ final String childName = currentName.get(0);
+ traversedName.add(childName);
+ currentName = currentName.getSuffix(1);
+ final TreeNode node = contextNode.children.get(childName);
+ if (node == null) {
+ if (createIfMissing) {
+ final NamingContext subContext = new NamingContext(traversedName,
InMemoryNamingStore.this, new Hashtable<String, Object>());
+ return contextNode.addOrGetChild(childName, new
ContextNode(contextNode, childName, traversedName, subContext)).accept(this);
+ } else {
+ throw nameNotFoundException(childName, contextNode.fullName);
+ }
+ }
+ return node.accept(this);
+ }
+
+ protected abstract T found(ContextNode contextNode) throws NamingException;
+
+ protected abstract T found(BindingNode bindingNode) throws NamingException;
+
+ protected T foundReferenceInsteadOfContext(BindingNode bindingNode) throws
NamingException {
+ final Object object = bindingNode.binding.getObject();
+ checkReferenceForContinuation(currentName, object);
+ throw notAContextException(bindingNode.fullName);
+ }
+ }
+
+ private abstract class BindingContextVisitor<T> extends
NodeTraversingVisitor<T> {
+ protected final Name targetName;
+
+ protected BindingContextVisitor(final boolean createIfMissing, final Name
targetName) {
+ super(createIfMissing, targetName.getPrefix(targetName.size() - 1));
+ this.targetName = targetName;
+ }
+
+ protected BindingContextVisitor(final Name targetName) {
+ this(false, targetName);
+ }
+
+ protected final T found(final ContextNode contextNode) throws NamingException {
+ return foundBindContext(contextNode);
+ }
+
+ protected final T found(final BindingNode bindingNode) throws NamingException {
+
checkReferenceForContinuation(targetName.getSuffix(bindingNode.fullName.size()),
bindingNode.binding.getObject());
+ throw notAContextException(targetName);
+ }
+
+ protected abstract T foundBindContext(final ContextNode contextNode) throws
NamingException;
+ }
+
+ private final class BindVisitor extends BindingContextVisitor<Void> {
+ private final Object object;
+ private final String className;
+
+ private BindVisitor(final boolean createIfMissing, final Name name, final Object
object, final String className) {
+ super(createIfMissing, name);
+ this.object = object;
+ this.className = className;
+ }
+
+ protected Void foundBindContext(final ContextNode contextNode) throws
NamingException {
+ final String childName = getLastComponent(targetName);
+ final Binding binding = new Binding(childName, className, object, true);
+ final BindingNode bindingNode = new BindingNode(targetName, binding);
+ contextNode.addChild(childName, bindingNode);
+ fireEvent(contextNode, targetName, null, binding, NamingEvent.OBJECT_ADDED,
"bind");
+ return null;
+ }
+ }
+
+ private final class RebindVisitor extends BindingContextVisitor<Void> {
+ private final Object object;
+ private final String className;
+
+ private RebindVisitor(final Name name, final Object object, final String
className) {
+ super(name);
+ this.object = object;
+ this.className = className;
+ }
+
+ protected Void foundBindContext(final ContextNode contextNode) throws
NamingException {
+ final String childName = getLastComponent(targetName);
+ final Binding binding = new Binding(childName, className, object, true);
+ final BindingNode bindingNode = new BindingNode(targetName, binding);
+ final TreeNode previous = contextNode.replaceChild(childName, bindingNode);
+
+ final Binding previousBinding = previous != null ? previous.binding : null;
+ fireEvent(contextNode, targetName, previousBinding, binding, previousBinding
!= null ? NamingEvent.OBJECT_CHANGED : NamingEvent.OBJECT_ADDED, "rebind");
+ return null;
+ }
+ }
+
+ private final class UnbindVisitor extends BindingContextVisitor<Void> {
+
+ private UnbindVisitor(final Name targetName) throws NamingException {
+ super(targetName);
+ }
+
+ protected Void foundBindContext(final ContextNode contextNode) throws
NamingException {
+ final TreeNode previous =
contextNode.removeChild(getLastComponent(targetName));
+ fireEvent(contextNode, targetName, previous.binding, null,
NamingEvent.OBJECT_REMOVED, "unbind");
+ return null;
+ }
+ }
+
+ private final class LookupVisitor extends NodeTraversingVisitor<Object> {
+ private LookupVisitor(final Name targetName) {
+ super(targetName);
+ }
+
+ protected Object found(final ContextNode contextNode) throws NamingException {
+ return contextNode.binding.getObject();
+ }
+
+ protected Object found(final BindingNode bindingNode) throws NamingException {
+ return bindingNode.binding.getObject();
+ }
+
+ protected Object foundReferenceInsteadOfContext(final BindingNode bindingNode)
throws NamingException {
+ final Name remainingName =
targetName.getSuffix(bindingNode.fullName.size());
+ final Object boundObject = bindingNode.binding.getObject();
+ checkReferenceForContinuation(remainingName, boundObject);
+ return new ResolveResult(boundObject, remainingName);
+ }
+ }
+
+ private final class ListVisitor extends
NodeTraversingVisitor<List<NameClassPair>> {
+ private ListVisitor(final Name targetName) {
+ super(targetName);
+ }
+
+ protected List<NameClassPair> found(final ContextNode contextNode) throws
NamingException {
+ final List<NameClassPair> nameClassPairs = new
ArrayList<NameClassPair>();
+ for (TreeNode childNode : contextNode.children.values()) {
+ final Binding binding = childNode.binding;
+ nameClassPairs.add(new NameClassPair(binding.getName(),
binding.getClassName(), true));
+ }
+ return nameClassPairs;
+ }
+
+ protected List<NameClassPair> found(final BindingNode bindingNode) throws
NamingException {
+ checkReferenceForContinuation(new CompositeName(),
bindingNode.binding.getObject());
+ throw notAContextException(targetName);
+ }
+ }
+
+ private final class ListBindingsVisitor extends
NodeTraversingVisitor<List<Binding>> {
+ private ListBindingsVisitor(final Name targetName) {
+ super(targetName);
+ }
+
+ protected List<Binding> found(final ContextNode contextNode) throws
NamingException {
+ final List<Binding> bindings = new ArrayList<Binding>();
+ for (TreeNode childNode : contextNode.children.values()) {
+ bindings.add(childNode.binding);
+ }
+ return bindings;
+ }
+
+ protected List<Binding> found(final BindingNode bindingNode) throws
NamingException {
+ checkReferenceForContinuation(new CompositeName(),
bindingNode.binding.getObject());
+ throw notAContextException(targetName);
+ }
+ }
+
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InitialContextFactory.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InitialContextFactory.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InitialContextFactory.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import java.util.Hashtable;
+
+/**
+ * Initial context factory which returns {@code NamingContext} instances.
+ *
+ * @author John E. Bailey
+ */
+public class InitialContextFactory implements javax.naming.spi.InitialContextFactory {
+ /**
+ * Get an initial context instance.
+ *
+ * @param environment The naming environment
+ * @return A naming context instance
+ * @throws javax.naming.NamingException
+ */
+ @SuppressWarnings("unchecked")
+ public Context getInitialContext(Hashtable<?, ?> environment) throws
NamingException {
+ return new NamingContext((Hashtable<String, Object>) environment);
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InitialContextFactoryBuilder.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InitialContextFactoryBuilder.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/InitialContextFactoryBuilder.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Hashtable;
+
+/**
+ * Initial context factory builder which ensures the proper naming context factory is
used if the environment
+ * does not override the initial context impl property.
+ *
+ * @author John E. Bailey
+ */
+public class InitialContextFactoryBuilder implements
javax.naming.spi.InitialContextFactoryBuilder {
+ private static final javax.naming.spi.InitialContextFactory DEFAULT_FACTORY = new
InitialContextFactory();
+
+ /**
+ * Create a InitialContext factory. If the environment does not override the factory
class it will use the
+ * default JBoss naming context factory.
+ *
+ * @param environment The environment
+ * @return An initial context factory
+ * @throws javax.naming.NamingException If an error occurs loading the factroy
class.
+ */
+ public javax.naming.spi.InitialContextFactory
createInitialContextFactory(Hashtable<?, ?> environment) throws NamingException {
+ final String factoryClassName =
(String)environment.get(Context.INITIAL_CONTEXT_FACTORY);
+ if(factoryClassName == null ||
InitialContextFactory.class.getName().equals(factoryClassName)) {
+ return DEFAULT_FACTORY;
+ }
+ final ClassLoader classLoader = getContextClassLoader();
+ try {
+ final Class<?> factoryClass = Class.forName(factoryClassName, true,
classLoader);
+ return (javax.naming.spi.InitialContextFactory)factoryClass.newInstance();
+ } catch (Exception e) {
+ throw new NamingException("Failed instantiate InitialContextFactory
" + factoryClassName + " from classloader " + classLoader);
+ }
+ }
+
+ private ClassLoader getContextClassLoader() {
+ return AccessController.doPrivileged(
+ new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ }
+ );
+ }
+
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingContext.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingContext.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingContext.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,472 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming;
+
+import org.gatein.naming.context.ObjectFactoryBuilder;
+import org.gatein.naming.util.NameParser;
+import org.jboss.logging.Logger;
+
+import javax.naming.Binding;
+import javax.naming.CannotProceedException;
+import javax.naming.CompositeName;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.LinkRef;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.event.EventContext;
+import javax.naming.event.NamingListener;
+import javax.naming.spi.NamingManager;
+import javax.naming.spi.ObjectFactory;
+import javax.naming.spi.ResolveResult;
+import java.util.Hashtable;
+
+import static org.gatein.naming.util.NamingUtils.*;
+
+/**
+ * Naming context implementation which proxies calls to a {@code NamingStore} instance.
This context is
+ * read-only.
+ *
+ * @author John E. Bailey
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class NamingContext implements EventContext {
+ private static final Logger log = Logger.getLogger("org.jboss.as.naming");
+
+ /*
+ * The active naming store to use for any context created without a name store.
+ */
+ private static NamingStore ACTIVE_NAMING_STORE = new InMemoryNamingStore();
+
+ /**
+ * Set the active naming store
+ *
+ * @param namingStore The naming store
+ */
+ public static void setActiveNamingStore(final NamingStore namingStore) {
+ ACTIVE_NAMING_STORE = namingStore;
+ }
+
+ private static final String PACKAGE_PREFIXES =
"org.jboss.as.naming.interfaces";
+
+ //static {
+ // try {
+ // NamingManager.setObjectFactoryBuilder(ObjectFactoryBuilder.INSTANCE);
+ // } catch(Throwable t) {
+ // log.warn("Failed to set ObjectFactoryBuilder", t);
+ // }
+ //}
+
+ /**
+ * Initialize the naming components required by {@link
javax.naming.spi.NamingManager}.
+ */
+ public static void initializeNamingManager() {
+ // Setup naming environment
+ System.setProperty(Context.URL_PKG_PREFIXES, PACKAGE_PREFIXES);
+ try {
+ //If we are reusing the JVM. e.g. in tests we should not set this again
+ if (!NamingManager.hasInitialContextFactoryBuilder())
+ NamingManager.setInitialContextFactoryBuilder(new
InitialContextFactoryBuilder());
+ } catch (NamingException e) {
+ log.warn("Failed to set InitialContextFactoryBuilder", e);
+ }
+ }
+
+ /* The naming store providing the back-end storage */
+ private final NamingStore namingStore;
+
+ /* The name prefix the context represents. */
+ private final Name prefix;
+
+ /* The environment configuration */
+ private final Hashtable<String, Object> environment;
+
+ /**
+ * Create a new naming context with no prefix or naming store. This will default to
a prefix of "" and
+ * the active naming store.
+ *
+ * @param environment The naming environment
+ */
+ public NamingContext(final Hashtable<String, Object> environment) {
+ this(new CompositeName(), ACTIVE_NAMING_STORE, environment);
+ }
+
+ /**
+ * Create a context with a prefix name.
+ *
+ * @param prefix The prefix for this context
+ * @param environment The naming environment
+ * @throws javax.naming.NamingException if an error occurs
+ */
+ public NamingContext(final Name prefix, final Hashtable<String, Object>
environment) throws NamingException {
+ this(prefix, ACTIVE_NAMING_STORE, environment);
+ }
+
+ /**
+ * Create a new naming context with a prefix name and a NamingStore instance to use
as a backing.
+ *
+ * @param prefix The prefix for this context
+ * @param namingStore The NamingStore
+ * @param environment The naming environment
+ */
+ public NamingContext(final Name prefix, final NamingStore namingStore, final
Hashtable<String, Object> environment) {
+ if(prefix == null) {
+ throw new IllegalArgumentException("Naming prefix can not be
null");
+ }
+ this.prefix = prefix;
+ if(namingStore == null) {
+ throw new IllegalArgumentException("NamingStore can not be null");
+ }
+ this.namingStore = namingStore;
+ if(environment != null) {
+ this.environment = new Hashtable<String, Object>(environment);
+ } else {
+ this.environment = new Hashtable<String, Object>();
+ }
+ }
+
+ /**
+ * Create a new naming context with the given namingStore and an empty name.
+ *
+ * @param namingStore the naming store to use
+ * @param environment the environment to use
+ */
+ public NamingContext(final NamingStore namingStore, final Hashtable<String,
Object> environment) {
+ this(new CompositeName(), namingStore, environment);
+ }
+
+ /** {@inheritDoc} */
+ public Object lookup(final Name name) throws NamingException {
+ if (isEmpty(name)) {
+ return new NamingContext(prefix, namingStore, environment);
+ }
+
+ final Name absoluteName = getAbsoluteName(name);
+ Object result;
+ try {
+ result = namingStore.lookup(absoluteName);
+ } catch(CannotProceedException cpe) {
+ final Context continuationContext =
NamingManager.getContinuationContext(cpe);
+ result = continuationContext.lookup(cpe.getRemainingName());
+ }
+
+ if (result instanceof ResolveResult) {
+ final ResolveResult resolveResult = (ResolveResult) result;
+ final Object resolvedObject = resolveResult.getResolvedObj();
+
+ Object context;
+ if (resolvedObject instanceof LinkRef) {
+ context = resolveLink(resolvedObject);
+ } else {
+ context = getObjectInstance(resolvedObject, absoluteName, environment);
+ }
+ if (!(context instanceof Context)) {
+ throw notAContextException(absoluteName.getPrefix(absoluteName.size() -
resolveResult.getRemainingName().size()));
+ }
+ final Context namingContext = (Context) context;
+ return namingContext.lookup(resolveResult.getRemainingName());
+ } else if (result instanceof LinkRef) {
+ result = resolveLink(result);
+ } else if (result instanceof Reference) {
+ result = getObjectInstance(result, absoluteName, environment);
+ if (result instanceof LinkRef) {
+ result = resolveLink(result);
+ }
+ }
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ public Object lookup(final String name) throws NamingException {
+ return lookup(parseName(name));
+ }
+
+ /** {@inheritDoc} */
+ public void bind(final Name name, Object object) throws NamingException {
+ if (isEmpty(name)) {
+ throw new NamingException("Can't bind to existing context!");
+ }
+
+ final Name absoluteName = getAbsoluteName(name);
+
+ try {
+ namingStore.bind(absoluteName, object);
+ } catch(CannotProceedException cpe) {
+ final Context continuationContext =
NamingManager.getContinuationContext(cpe);
+ continuationContext.bind(absoluteName, object);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void bind(final String name, final Object obj) throws NamingException {
+ bind(parseName(name), obj);
+ }
+
+ /** {@inheritDoc} */
+ public void rebind(final Name name, Object object) throws NamingException {
+ final Name absoluteName = getAbsoluteName(name);
+
+ try {
+ namingStore.rebind(absoluteName, object);
+ } catch(CannotProceedException cpe) {
+ final Context continuationContext =
NamingManager.getContinuationContext(cpe);
+ continuationContext.rebind(absoluteName, object);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void rebind(final String name, final Object obj) throws NamingException {
+ rebind(parseName(name), obj);
+ }
+
+ /** {@inheritDoc} */
+ public void unbind(final Name name) throws NamingException {
+ final Name absoluteName = getAbsoluteName(name);
+
+ try {
+ namingStore.unbind(absoluteName);
+ } catch(CannotProceedException cpe) {
+ final Context continuationContext =
NamingManager.getContinuationContext(cpe);
+ continuationContext.unbind(absoluteName);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void unbind(final String name) throws NamingException {
+ unbind(parseName(name));
+ }
+
+ /** {@inheritDoc} */
+ public void rename(final Name oldName, final Name newName) throws NamingException {
+ throw new UnsupportedOperationException("Naming context is read-only");
+
+ }
+
+ /** {@inheritDoc} */
+ public void rename(final String oldName, final String newName) throws NamingException
{
+ throw new UnsupportedOperationException("Naming context is
read-only");
+ }
+
+ /** {@inheritDoc} */
+ public NamingEnumeration<NameClassPair> list(final Name name) throws
NamingException {
+ try {
+ return namingEnumeration(namingStore.list(getAbsoluteName(name)));
+ } catch(CannotProceedException cpe) {
+ final Context continuationContext =
NamingManager.getContinuationContext(cpe);
+ return continuationContext.list(cpe.getRemainingName());
+ }
+ }
+
+ /** {@inheritDoc} */
+ public NamingEnumeration<NameClassPair> list(final String name) throws
NamingException {
+ return list(parseName(name));
+ }
+
+ /** {@inheritDoc} */
+ public NamingEnumeration<Binding> listBindings(final Name name) throws
NamingException {
+ try {
+ return namingEnumeration(namingStore.listBindings(getAbsoluteName(name)));
+ } catch(CannotProceedException cpe) {
+ final Context continuationContext =
NamingManager.getContinuationContext(cpe);
+ return continuationContext.listBindings(cpe.getRemainingName());
+ }
+ }
+
+ /** {@inheritDoc} */
+ public NamingEnumeration<Binding> listBindings(final String name) throws
NamingException {
+ return listBindings(parseName(name));
+ }
+
+ /** {@inheritDoc} */
+ public void destroySubcontext(final Name name) throws NamingException {
+ throw new UnsupportedOperationException("Naming context is
read-only");
+ }
+
+ /** {@inheritDoc} */
+ public void destroySubcontext(String name) throws NamingException {
+ throw new UnsupportedOperationException("Naming context is
read-only");
+ }
+
+ /** {@inheritDoc} */
+ public Context createSubcontext(Name name) throws NamingException {
+ throw new UnsupportedOperationException("Naming context is
read-only");
+ }
+
+ /** {@inheritDoc} */
+ public Context createSubcontext(String name) throws NamingException {
+ throw new UnsupportedOperationException("Naming context is
read-only");
+ }
+
+ /** {@inheritDoc} */
+ public Object lookupLink(Name name) throws NamingException {
+ if (name.isEmpty()) {
+ return lookup(name);
+ }
+ try {
+ final Name absoluteName = getAbsoluteName(name);
+ Object link = namingStore.lookup(absoluteName);
+ if (!(link instanceof LinkRef) && link instanceof Reference) {
+ link = getObjectInstance(link, name, null);
+ }
+ return link;
+ } catch (Exception e) {
+ throw namingException("Could not lookup link", e, name);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Object lookupLink(String name) throws NamingException {
+ return lookup(parseName(name));
+ }
+
+ /** {@inheritDoc} */
+ public NameParser getNameParser(Name name) throws NamingException {
+ return NameParser.INSTANCE;
+ }
+
+ /** {@inheritDoc} */
+ public NameParser getNameParser(String name) throws NamingException {
+ return NameParser.INSTANCE;
+ }
+
+ /** {@inheritDoc} */
+ public Name composeName(Name name, Name prefix) throws NamingException {
+ final Name result = (Name) prefix.clone();
+ result.addAll(name);
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ public String composeName(String name, String prefix) throws NamingException {
+ return composeName(parseName(name), parseName(prefix)).toString();
+ }
+
+ /** {@inheritDoc} */
+ public Object addToEnvironment(String propName, Object propVal) throws
NamingException {
+ final Object existing = environment.get(propName);
+ environment.put(propName, propVal);
+ return existing;
+ }
+
+ /** {@inheritDoc} */
+ public Object removeFromEnvironment(String propName) throws NamingException {
+ return environment.remove(propName);
+ }
+
+ /** {@inheritDoc} */
+ public Hashtable<?, ?> getEnvironment() throws NamingException {
+ return environment;
+ }
+
+ /** {@inheritDoc} */
+ public void close() throws NamingException {
+ // NO-OP
+ }
+
+ /** {@inheritDoc} */
+ public String getNameInNamespace() throws NamingException {
+ return prefix.toString();
+ }
+
+ /** {@inheritDoc} */
+ public void addNamingListener(final Name target, final int scope, final
NamingListener listener) throws NamingException {
+ namingStore.addNamingListener(target, scope, listener);
+ }
+
+ /** {@inheritDoc} */
+ public void addNamingListener(final String target, final int scope, final
NamingListener listener) throws NamingException {
+ addNamingListener(parseName(target), scope, listener);
+ }
+
+ /** {@inheritDoc} */
+ public void removeNamingListener(final NamingListener listener) throws
NamingException {
+ namingStore.removeNamingListener(listener);
+ }
+
+ /** {@inheritDoc} */
+ public boolean targetMustExist() throws NamingException {
+ return false;
+ }
+
+ private Name parseName(final String name) throws NamingException {
+ return getNameParser(name).parse(name);
+ }
+
+ private Name getAbsoluteName(final Name name) throws NamingException {
+ if(name.isEmpty()) {
+ return composeName(name, prefix);
+ }
+ final String firstComponent = name.get(0);
+ if(firstComponent.startsWith("java:")) {
+ final String cleaned = firstComponent.substring(5);
+ final Name suffix = name.getSuffix(1);
+ if(cleaned.isEmpty()) {
+ return suffix;
+ }
+ return suffix.add(0, cleaned);
+ } else if(firstComponent.isEmpty()) {
+ return name.getSuffix(1);
+ } else {
+ return composeName(name, prefix);
+ }
+ }
+
+ private Object getObjectInstance(final Object object, final Name name, final
Hashtable<?, ?> environment) throws NamingException {
+ try {
+ final ObjectFactoryBuilder factoryBuilder = ObjectFactoryBuilder.INSTANCE;
+ final ObjectFactory objectFactory =
factoryBuilder.createObjectFactory(object, environment);
+ return objectFactory.getObjectInstance(object, name, this, environment);
+ } catch(NamingException e) {
+ throw e;
+ } catch(Throwable t) {
+ throw namingException("Could not dereference object", t);
+ }
+ }
+
+ private Object resolveLink(Object result) throws NamingException {
+ final Object linkResult;
+ try {
+ final LinkRef linkRef = (LinkRef) result;
+ final String referenceName = linkRef.getLinkName();
+ if (referenceName.startsWith("./")) {
+ linkResult = lookup(referenceName.substring(2));
+ } else {
+ linkResult = new InitialContext().lookup(referenceName);
+ }
+ } catch (Throwable t) {
+ throw namingException("Could not dereference object", t);
+ }
+ return linkResult;
+ }
+
+ Name getPrefix() {
+ return prefix;
+ }
+
+ NamingStore getNamingStore() {
+ return namingStore;
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingEventCoordinator.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingEventCoordinator.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingEventCoordinator.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,260 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming;
+
+import org.gatein.naming.util.FastCopyHashMap;
+import org.jboss.threads.JBossThreadFactory;
+
+import javax.naming.Binding;
+import javax.naming.Name;
+import javax.naming.event.EventContext;
+import javax.naming.event.NamespaceChangeListener;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingListener;
+import javax.naming.event.ObjectChangeListener;
+import java.security.AccessController;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Coordinator responsible for passing @(code NamingEvent} instances to registered @{code
NamingListener} instances. Two
+ * maps are used to managed a mapping between a listener and its configuration as well as
a mapping from target name to a list
+ * of listener configurations. These maps are updated atomically on listener add and
remove.
+ *
+ * @author John E. Bailey
+ */
+public class NamingEventCoordinator
+{
+ private volatile Map<TargetScope, List<ListenerHolder>> holdersByTarget =
Collections.emptyMap();
+ private volatile Map<NamingListener, ListenerHolder> holdersByListener =
Collections.emptyMap();
+
+ private final ThreadFactory threadFactory = new JBossThreadFactory(new
ThreadGroup("NamingEventCoordinator-threads"), Boolean.FALSE, null, "%G -
%t", null, null, AccessController.getContext());
+
+ private final Executor executor = Executors.newSingleThreadExecutor(threadFactory);
+
+ static final Integer[] DEFAULT_SCOPES = {EventContext.OBJECT_SCOPE,
EventContext.ONELEVEL_SCOPE, EventContext.SUBTREE_SCOPE};
+
+ /**
+ * Add a listener to the coordinator with a given target name and event scope. This
information is used when an
+ * event is fired to determine whether or not to fire this listener.
+ *
+ * @param target The target name to lister
+ * @param scope The event scope
+ * @param namingListener The listener
+ */
+ synchronized void addListener(final String target, final int scope, final
NamingListener namingListener) {
+ final TargetScope targetScope = new TargetScope(target, scope);
+ // Do we have a holder for this listener
+ ListenerHolder holder = holdersByListener.get(namingListener);
+ if (holder == null) {
+ holder = new ListenerHolder(namingListener, targetScope);
+ final Map<NamingListener, ListenerHolder> byListenerCopy = new
FastCopyHashMap<NamingListener, ListenerHolder>(holdersByListener);
+ byListenerCopy.put(namingListener, holder);
+ holdersByListener = byListenerCopy;
+ } else {
+ holder.addTarget(targetScope);
+ }
+
+ List<ListenerHolder> holdersForTarget = holdersByTarget.get(targetScope);
+ if (holdersForTarget == null) {
+ holdersForTarget = new CopyOnWriteArrayList<ListenerHolder>();
+ final Map<TargetScope, List<ListenerHolder>> byTargetCopy = new
FastCopyHashMap<TargetScope, List<ListenerHolder>>(holdersByTarget);
+ byTargetCopy.put(targetScope, holdersForTarget);
+ holdersByTarget = byTargetCopy;
+ }
+ holdersForTarget.add(holder);
+ }
+
+ /**
+ * Remove a listener. Will remove it from all target mappings. Once this method
returns, the listener will no longer
+ * receive any events.
+ *
+ * @param namingListener The listener
+ */
+ synchronized void removeListener(final NamingListener namingListener) {
+ // Do we have a holder for this listener
+ final ListenerHolder holder = holdersByListener.get(namingListener);
+ if (holder == null) {
+ return;
+ }
+
+ final Map<NamingListener, ListenerHolder> byListenerCopy = new
FastCopyHashMap<NamingListener, ListenerHolder>(holdersByListener);
+ byListenerCopy.remove(namingListener);
+ holdersByListener = byListenerCopy;
+
+ final Map<TargetScope, List<ListenerHolder>> byTargetCopy = new
FastCopyHashMap<TargetScope, List<ListenerHolder>>(holdersByTarget);
+ for (TargetScope targetScope : holder.targets) {
+ final List<ListenerHolder> holders = holdersByTarget.get(targetScope);
+ holders.remove(holder);
+ if (holders.isEmpty()) {
+ byTargetCopy.remove(targetScope);
+ }
+ }
+ holdersByTarget = byTargetCopy;
+ }
+
+ /**
+ * Fire a naming event. An event will be created with the provided information and
sent to each listener that matches
+ * the target and scope information.
+ *
+ * @param context The event context generating the event.
+ * @param name The target name the event represents
+ * @param existingBinding The existing binding at the provided name
+ * @param newBinding The new binding at the provided name
+ * @param type The event type
+ * @param changeInfo The change info for the event
+ * @param scopes The scopes this event should be fired against
+ */
+ void fireEvent(final EventContext context, final Name name, final Binding
existingBinding, final Binding newBinding, int type, final String changeInfo, final
Integer... scopes) {
+ final String target = name.toString();
+ final Set<Integer> scopeSet = new
HashSet<Integer>(Arrays.asList(scopes));
+ final NamingEvent event = new NamingEvent(context, type, newBinding,
existingBinding, changeInfo);
+
+ final Set<ListenerHolder> holdersToFire = new
HashSet<ListenerHolder>();
+
+ // Check for OBJECT_SCOPE based listeners
+ if (scopeSet.contains(EventContext.OBJECT_SCOPE)) {
+ final TargetScope targetScope = new TargetScope(target,
EventContext.OBJECT_SCOPE);
+ final List<ListenerHolder> holders = holdersByTarget.get(targetScope);
+ if (holders != null) {
+ for (ListenerHolder holder : holders) {
+ holdersToFire.add(holder);
+ }
+ }
+ }
+
+ // Check for ONELEVEL_SCOPE based listeners
+ if (scopeSet.contains(EventContext.ONELEVEL_SCOPE) && !name.isEmpty()) {
+ final TargetScope targetScope = new TargetScope(name.getPrefix(name.size() -
1).toString(), EventContext.ONELEVEL_SCOPE);
+ final List<ListenerHolder> holders = holdersByTarget.get(targetScope);
+ if (holders != null) {
+ for (ListenerHolder holder : holders) {
+ holdersToFire.add(holder);
+ }
+ }
+ }
+
+ // Check for SUBTREE_SCOPE based listeners
+ if (scopeSet.contains(EventContext.SUBTREE_SCOPE) && !name.isEmpty()) {
+ for (int i = 1; i < name.size(); i++) {
+ final Name parentName = name.getPrefix(i);
+ final TargetScope targetScope = new TargetScope(parentName.toString(),
EventContext.SUBTREE_SCOPE);
+ final List<ListenerHolder> holders =
holdersByTarget.get(targetScope);
+ if (holders != null) {
+ for (ListenerHolder holder : holders) {
+ holdersToFire.add(holder);
+ }
+ }
+ }
+ }
+
+ executor.execute(new FireEventTask(holdersToFire, event));
+ }
+
+ private class FireEventTask implements Runnable {
+ private final Set<ListenerHolder> listenerHolders;
+ private final NamingEvent event;
+
+ private FireEventTask(Set<ListenerHolder> listenerHolders, NamingEvent
event) {
+ this.listenerHolders = listenerHolders;
+ this.event = event;
+ }
+
+ @Override
+ public void run() {
+ for (ListenerHolder holder : listenerHolders) {
+ final NamingListener listener = holder.listener;
+ switch (event.getType()) {
+ case NamingEvent.OBJECT_ADDED:
+ if (listener instanceof NamespaceChangeListener)
+ ((NamespaceChangeListener) listener).objectAdded(event);
+ break;
+ case NamingEvent.OBJECT_REMOVED:
+ if (listener instanceof NamespaceChangeListener)
+ ((NamespaceChangeListener) listener).objectRemoved(event);
+ break;
+ case NamingEvent.OBJECT_RENAMED:
+ if (listener instanceof NamespaceChangeListener)
+ ((NamespaceChangeListener) listener).objectRenamed(event);
+ break;
+ case NamingEvent.OBJECT_CHANGED:
+ if (listener instanceof ObjectChangeListener)
+ ((ObjectChangeListener) listener).objectChanged(event);
+ break;
+ }
+ }
+ }
+ }
+
+ private class ListenerHolder {
+ private volatile Set<TargetScope> targets = new
HashSet<TargetScope>();
+ private final NamingListener listener;
+
+ private ListenerHolder(final NamingListener listener, final TargetScope
initialTarget) {
+ this.listener = listener;
+ addTarget(initialTarget);
+ }
+
+ private synchronized void addTarget(final TargetScope targetScope) {
+ targets.add(targetScope);
+ }
+ }
+
+ private class TargetScope {
+ private final String target;
+ private final int scope;
+
+ private TargetScope(String target, int scope) {
+ this.target = target;
+ this.scope = scope;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ TargetScope that = (TargetScope) o;
+
+ if (scope != that.scope) return false;
+ if (target != null ? !target.equals(that.target) : that.target != null)
return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = target != null ? target.hashCode() : 0;
+ result = 31 * result + scope;
+ return result;
+ }
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingStore.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingStore.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/NamingStore.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,140 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming;
+
+import javax.naming.Binding;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NamingException;
+import javax.naming.event.NamingListener;
+import java.util.List;
+
+/**
+ * Interface to layout a contract for naming entry back-end storage. This will be used
by {@code NamingContext} instances
+ * to manage naming entries.
+ *
+ * @author John E. Bailey
+ */
+public interface NamingStore
+{
+ /**
+ * Bind and object into the naming store, creating parent contexts if needed. All
parent contexts must be
+ * created before this can be executed. The bind object type will be determined by
the class of the object being passed in.
+ *
+ * @param name The entry name
+ * @param object The entry object
+ * @throws javax.naming.NamingException If any problems occur
+ */
+ void bind(Name name, Object object) throws NamingException;
+
+ /**
+ * Bind and object into the naming store, creating parent contexts if needed. All
parent contexts must be
+ * created before this can be executed.
+ *
+ * @param name The entry name
+ * @param object The entry object
+ * @param bindType The entry class
+ * @throws javax.naming.NamingException If any problems occur
+ */
+ void bind(Name name, Object object, Class<?> bindType) throws NamingException;
+
+ /**
+ * Re-bind and object into the naming store. All parent contexts must be created
before this can be executed.
+ * The bind object type will be determined by the class of the object being passed
in.
+ *
+ * @param name The entry name
+ * @param object The entry object
+ * @throws javax.naming.NamingException If any problems occur
+ */
+ void rebind(Name name, Object object) throws NamingException;
+
+ /**
+ * Re-bind and object into the naming store. All parent contexts must be created
before this can be executed.
+ *
+ * @param name The entry name
+ * @param object The entry object
+ * @param bindType The entry class
+ * @throws javax.naming.NamingException If any problems occur
+ */
+ void rebind(Name name, Object object, Class<?> bindType) throws
NamingException;
+
+ /**
+ * Unbind an object from the naming store. An entry for the name must exist.
+ *
+ * @param name The entry name
+ * @throws javax.naming.NamingException If any problems occur
+ */
+ void unbind(Name name) throws NamingException;
+
+ /**
+ * Look up an object from the naming store. An entry for this name must already
exist.
+ *
+ * @param name The entry name
+ * @return The object from the store.
+ * @throws javax.naming.NamingException If any errors occur.
+ */
+ Object lookup(Name name) throws NamingException;
+
+ /**
+ * List the NameClassPair instances for the provided name. An entry for this name
must already exist and be bound
+ * to a valid context.
+ *
+ * @param name The entry name
+ * @return The NameClassPair instances
+ * @throws javax.naming.NamingException If any errors occur
+ */
+ List<NameClassPair> list(Name name) throws NamingException;
+
+ /**
+ * List the binding objects for a specified name. An entry for this name must
already exist and be bound
+ * to a valid context.
+ *
+ * @param name The entry name
+ * @return The bindings
+ * @throws javax.naming.NamingException If any errors occur
+ */
+ List<Binding> listBindings(Name name) throws NamingException;
+
+ /**
+ * Close the naming store and cleanup any resource used by the store.
+ *
+ * @throws javax.naming.NamingException If any errors occur
+ */
+ void close() throws NamingException;
+
+ /**
+ * Add a {@code NamingListener} for a specific target and scope.
+ *
+ * @param target The target name to add the listener to
+ * @param scope The listener scope
+ * @param listener The listener
+ */
+ void addNamingListener(Name target, int scope, NamingListener listener);
+
+ /**
+ * Remove a {@code NamingListener} from all targets and scopes
+ *
+ * @param listener The listener
+ */
+ void removeNamingListener(NamingListener listener);
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/context/ObjectFactoryBuilder.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/context/ObjectFactoryBuilder.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/context/ObjectFactoryBuilder.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,113 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming.context;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+import java.util.Hashtable;
+
+import static org.gatein.naming.util.NamingUtils.namingException;
+
+/**
+ * ObjectFactoryBuilder implementation used to support custom object factories being
loaded from modules. This class
+ * also provides the default object factory implementation.
+ *
+ * @author John Bailey
+ */
+public class ObjectFactoryBuilder implements javax.naming.spi.ObjectFactoryBuilder,
ObjectFactory {
+
+ public static final ObjectFactoryBuilder INSTANCE = new ObjectFactoryBuilder();
+
+ private ObjectFactoryBuilder() {
+ }
+
+ /**
+ * Create an object factory. If the object parameter is a reference it will attempt
to create an {@link javax.naming.spi.ObjectFactory}
+ * from the reference. If the parameter is not a reference, or the reference does
not create an {@link javax.naming.spi.ObjectFactory}
+ * it will return {@code this} as the {@link javax.naming.spi.ObjectFactory} to use.
+ *
+ * @param obj The object bound in the naming context
+ * @param environment The environment information
+ * @return The object factory the object resolves to
+ * @throws javax.naming.NamingException If any problems occur
+ */
+ public ObjectFactory createObjectFactory(final Object obj, Hashtable<?, ?>
environment) throws NamingException {
+ try {
+ if (obj instanceof Reference) {
+ return factoryFromReference((Reference) obj, environment);
+ }
+ } catch(Throwable ignored) {
+ }
+ return this;
+ }
+
+ /**
+ * Create an object instance.
+ *
+ * @param ref Object containing reference information
+ * @param name The name relative to nameCtx
+ * @param nameCtx The naming context
+ * @param environment The environment information
+ * @return The object
+ * @throws Exception If any error occur
+ */
+ public Object getObjectInstance(final Object ref, final Name name, final Context
nameCtx, final Hashtable<?, ?> environment) throws Exception {
+ final ClassLoader classLoader = SecurityActions.getContextClassLoader();
+ if(classLoader == null) {
+ return ref;
+ }
+ final String factoriesProp = (String)environment.get(Context.OBJECT_FACTORIES);
+ if(factoriesProp != null) {
+ final String[] classes = factoriesProp.split(":");
+ for(String className : classes) {
+ try {
+ final Class<?> factoryClass =
classLoader.loadClass(className);
+ final ObjectFactory objectFactory =
ObjectFactory.class.cast(factoryClass.newInstance());
+ final Object result = objectFactory.getObjectInstance(ref, name,
nameCtx, environment);
+ if(result != null) {
+ return result;
+ }
+ } catch(Throwable ignored) {
+ }
+ }
+ }
+ return null;
+ }
+
+ private ObjectFactory factoryFromReference(final Reference reference, final
Hashtable<?, ?> environment) throws Exception {
+ return factoryFromReference(reference, SecurityActions.getContextClassLoader(),
environment);
+ }
+
+ private ObjectFactory factoryFromReference(final Reference reference, final
ClassLoader classLoader, final Hashtable<?, ?> environment) throws Exception {
+ try {
+ final Class<?> factoryClass =
classLoader.loadClass(reference.getFactoryClassName());
+ ObjectFactory factory =
ObjectFactory.class.cast(factoryClass.newInstance());
+ return factory;
+ } catch (Throwable t) {
+ throw namingException("Failed to create object factory from
classloader.", t);
+ }
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/context/SecurityActions.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/context/SecurityActions.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/context/SecurityActions.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming.context;
+
+/**
+ * @author John Bailey
+ * @deprecated public class with generic privileged actions
+ */
+@Deprecated
+public class SecurityActions extends org.gatein.naming.util.SecurityActions {
+ static ClassLoader getContextClassLoader() {
+ return org.gatein.naming.util.SecurityActions.getContextClassLoaderProtected();
+ }
+
+ static void setContextClassLoader(ClassLoader loader) {
+ org.gatein.naming.util.SecurityActions.setContextClassLoaderProtected(loader);
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/interfaces/java/javaURLContextFactory.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/interfaces/java/javaURLContextFactory.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/interfaces/java/javaURLContextFactory.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,44 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming.interfaces.java;
+
+import org.gatein.naming.NamingContext;
+
+import javax.naming.CompositeName;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.spi.ObjectFactory;
+import java.util.Hashtable;
+
+/**
+ * Implementation of {@code ObjectFactory} used to create a {@code NamingContext}
instances to support the java: namespace.
+ *
+ * @author John E. Bailey
+ */
+public class javaURLContextFactory implements ObjectFactory {
+
+ /** {@inheritDoc} */
+ public Object getObjectInstance(Object obj, Name name, Context nameCtx,
Hashtable<?, ?> environment) throws Exception {
+ return new NamingContext(name != null ? name : new CompositeName(""),
(Hashtable<String, Object>) environment);
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/FastCopyHashMap.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/FastCopyHashMap.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/FastCopyHashMap.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,757 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming.util;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.AbstractCollection;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A HashMap that is optimized for fast shallow copies. If the copy-ctor is
+ * passed another FastCopyHashMap, or clone is called on this map, the shallow
+ * copy can be performed using little more than a single array copy. In order to
+ * accomplish this, immutable objects must be used internally, so update
+ * operations result in slightly more object churn than
<code>HashMap</code>.
+ * <p/>
+ * Note: It is very important to use a smaller load factor than you normally
+ * would for HashMap, since the implementation is open-addressed with linear
+ * probing. With a 50% load-factor a get is expected to return in only 2 probes.
+ * However, a 90% load-factor is expected to return in around 50 probes.
+ *
+ * @author Jason T. Greene
+ */
+public class FastCopyHashMap<K, V> extends AbstractMap<K, V> implements
Map<K, V>, Cloneable, Serializable {
+ /**
+ * Marks null keys.
+ */
+ private static final Object NULL = new Object();
+
+ /**
+ * Serialization ID
+ */
+ private static final long serialVersionUID = 10929568968762L;
+
+ /**
+ * Same default as HashMap, must be a power of 2
+ */
+ private static final int DEFAULT_CAPACITY = 8;
+
+ /**
+ * MAX_INT - 1
+ */
+ private static final int MAXIMUM_CAPACITY = 1 << 30;
+
+ /**
+ * 67%, just like IdentityHashMap
+ */
+ private static final float DEFAULT_LOAD_FACTOR = 0.67f;
+
+ /**
+ * The open-addressed table
+ */
+ private transient Entry<K, V>[] table;
+
+ /**
+ * The current number of key-value pairs
+ */
+ private transient int size;
+
+ /**
+ * The next resize
+ */
+ private transient int threshold;
+
+ /**
+ * The user defined load factor which defines when to resize
+ */
+ private final float loadFactor;
+
+ /**
+ * Counter used to detect changes made outside of an iterator
+ */
+ private transient int modCount;
+
+ // Cached views
+ private transient KeySet keySet;
+ private transient Values values;
+ private transient EntrySet entrySet;
+
+ public FastCopyHashMap(int initialCapacity, float loadFactor) {
+ if (initialCapacity < 0)
+ throw new IllegalArgumentException("Can not have a negative size
table!");
+
+ if (initialCapacity > MAXIMUM_CAPACITY)
+ initialCapacity = MAXIMUM_CAPACITY;
+
+ if (!(loadFactor > 0F && loadFactor <= 1F))
+ throw new IllegalArgumentException("Load factor must be greater than 0
and less than or equal to 1");
+
+ this.loadFactor = loadFactor;
+ init(initialCapacity, loadFactor);
+ }
+
+ @SuppressWarnings("unchecked")
+ public FastCopyHashMap(Map<? extends K, ? extends V> map) {
+ if (map instanceof FastCopyHashMap) {
+ FastCopyHashMap<? extends K, ? extends V> fast = (FastCopyHashMap<?
extends K, ? extends V>) map;
+ this.table = (Entry<K, V>[]) fast.table.clone();
+ this.loadFactor = fast.loadFactor;
+ this.size = fast.size;
+ this.threshold = fast.threshold;
+ } else {
+ this.loadFactor = DEFAULT_LOAD_FACTOR;
+ init(map.size(), this.loadFactor);
+ putAll(map);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void init(int initialCapacity, float loadFactor) {
+ int c = 1;
+ while (c < initialCapacity) c <<= 1;
+ threshold = (int) (c * loadFactor);
+
+ // Include the load factor when sizing the table for the first time
+ if (initialCapacity > threshold && c < MAXIMUM_CAPACITY) {
+ c <<= 1;
+ threshold = (int) (c * loadFactor);
+ }
+
+ this.table = (Entry<K, V>[]) new Entry[c];
+ }
+
+ public FastCopyHashMap(int initialCapacity) {
+ this(initialCapacity, DEFAULT_LOAD_FACTOR);
+ }
+
+ public FastCopyHashMap() {
+ this(DEFAULT_CAPACITY);
+ }
+
+ // The normal bit spreader...
+
+ private static int hash(Object key) {
+ int h = key.hashCode();
+ h ^= (h >>> 20) ^ (h >>> 12);
+ return h ^ (h >>> 7) ^ (h >>> 4);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <K> K maskNull(K key) {
+ return key == null ? (K) NULL : key;
+ }
+
+ private static <K> K unmaskNull(K key) {
+ return key == NULL ? null : key;
+ }
+
+ private int nextIndex(int index, int length) {
+ index = (index >= length - 1) ? 0 : index + 1;
+ return index;
+ }
+
+ private static boolean eq(Object o1, Object o2) {
+ return o1 == o2 || (o1 != null && o1.equals(o2));
+ }
+
+ private static int index(int hashCode, int length) {
+ return hashCode & (length - 1);
+ }
+
+ public int size() {
+ return size;
+ }
+
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ public V get(Object key) {
+ key = maskNull(key);
+
+ int hash = hash(key);
+ int length = table.length;
+ int index = index(hash, length);
+
+ for (int start = index; ;) {
+ Entry<K, V> e = table[index];
+ if (e == null)
+ return null;
+
+ if (e.hash == hash && eq(key, e.key))
+ return e.value;
+
+ index = nextIndex(index, length);
+ if (index == start) // Full table
+ return null;
+ }
+ }
+
+ public boolean containsKey(Object key) {
+ key = maskNull(key);
+
+ int hash = hash(key);
+ int length = table.length;
+ int index = index(hash, length);
+
+ for (int start = index; ;) {
+ Entry<K, V> e = table[index];
+ if (e == null)
+ return false;
+
+ if (e.hash == hash && eq(key, e.key))
+ return true;
+
+ index = nextIndex(index, length);
+ if (index == start) // Full table
+ return false;
+ }
+ }
+
+ public boolean containsValue(Object value) {
+ for (Entry<K, V> e : table)
+ if (e != null && eq(value, e.value))
+ return true;
+
+ return false;
+ }
+
+ public V put(K key, V value) {
+ key = maskNull(key);
+
+ Entry<K, V>[] table = this.table;
+ int hash = hash(key);
+ int length = table.length;
+ int index = index(hash, length);
+
+ for (int start = index; ;) {
+ Entry<K, V> e = table[index];
+ if (e == null)
+ break;
+
+ if (e.hash == hash && eq(key, e.key)) {
+ table[index] = new Entry<K, V>(e.key, e.hash, value);
+ return e.value;
+ }
+
+ index = nextIndex(index, length);
+ if (index == start)
+ throw new IllegalStateException("Table is full!");
+ }
+
+ modCount++;
+ table[index] = new Entry<K, V>(key, hash, value);
+ if (++size >= threshold)
+ resize(length);
+
+ return null;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ private void resize(int from) {
+ int newLength = from << 1;
+
+ // Can't get any bigger
+ if (newLength > MAXIMUM_CAPACITY || newLength <= from)
+ return;
+
+ Entry<K, V>[] newTable = new Entry[newLength];
+ Entry<K, V>[] old = table;
+
+ for (Entry<K, V> e : old) {
+ if (e == null)
+ continue;
+
+ int index = index(e.hash, newLength);
+ while (newTable[index] != null)
+ index = nextIndex(index, newLength);
+
+ newTable[index] = e;
+ }
+
+ threshold = (int) (loadFactor * newLength);
+ table = newTable;
+ }
+
+ public void putAll(Map<? extends K, ? extends V> map) {
+ int size = map.size();
+ if (size == 0)
+ return;
+
+ if (size > threshold) {
+ if (size > MAXIMUM_CAPACITY)
+ size = MAXIMUM_CAPACITY;
+
+ int length = table.length;
+ while (length < size) length <<= 1;
+
+ resize(length);
+ }
+
+ for (Map.Entry<? extends K, ? extends V> e : map.entrySet())
+ put(e.getKey(), e.getValue());
+ }
+
+ public V remove(Object key) {
+ key = maskNull(key);
+
+ Entry<K, V>[] table = this.table;
+ int length = table.length;
+ int hash = hash(key);
+ int start = index(hash, length);
+
+ for (int index = start; ;) {
+ Entry<K, V> e = table[index];
+ if (e == null)
+ return null;
+
+ if (e.hash == hash && eq(key, e.key)) {
+ table[index] = null;
+ relocate(index);
+ modCount++;
+ size--;
+ return e.value;
+ }
+
+ index = nextIndex(index, length);
+ if (index == start)
+ return null;
+ }
+
+
+ }
+
+ private void relocate(int start) {
+ Entry<K, V>[] table = this.table;
+ int length = table.length;
+ int current = nextIndex(start, length);
+
+ for (; ;) {
+ Entry<K, V> e = table[current];
+ if (e == null)
+ return;
+
+ // A Doug Lea variant of Knuth's Section 6.4 Algorithm R.
+ // This provides a non-recursive method of relocating
+ // entries to their optimal positions once a gap is created.
+ int prefer = index(e.hash, length);
+ if ((current < prefer && (prefer <= start || start <=
current))
+ || (prefer <= start && start <= current)) {
+ table[start] = e;
+ table[current] = null;
+ start = current;
+ }
+
+ current = nextIndex(current, length);
+ }
+ }
+
+ public void clear() {
+ modCount++;
+ Entry<K, V>[] table = this.table;
+ for (int i = 0; i < table.length; i++)
+ table[i] = null;
+
+ size = 0;
+ }
+
+ @SuppressWarnings("unchecked")
+ public FastCopyHashMap<K, V> clone() {
+ try {
+ FastCopyHashMap<K, V> clone = (FastCopyHashMap<K, V>)
super.clone();
+ clone.table = table.clone();
+ clone.entrySet = null;
+ clone.values = null;
+ clone.keySet = null;
+ return clone;
+ }
+ catch (CloneNotSupportedException e) {
+ // should never happen
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void printDebugStats() {
+ int optimal = 0;
+ int total = 0;
+ int totalSkew = 0;
+ int maxSkew = 0;
+ for (int i = 0; i < table.length; i++) {
+ Entry<K, V> e = table[i];
+ if (e != null) {
+
+ total++;
+ int target = index(e.hash, table.length);
+ if (i == target)
+ optimal++;
+ else {
+ int skew = Math.abs(i - target);
+ if (skew > maxSkew) maxSkew = skew;
+ totalSkew += skew;
+ }
+
+ }
+ }
+
+ System.out.println(" Size: " + size);
+ System.out.println(" Real Size: " + total);
+ System.out.println(" Optimal: " + optimal + " (" +
(float) optimal * 100 / total + "%)");
+ System.out.println(" Average Distnce: " + ((float) totalSkew / (total -
optimal)));
+ System.out.println(" Max Distance: " + maxSkew);
+ }
+
+ public Set<Map.Entry<K, V>> entrySet() {
+ if (entrySet == null)
+ entrySet = new EntrySet();
+
+ return entrySet;
+ }
+
+ public Set<K> keySet() {
+ if (keySet == null)
+ keySet = new KeySet();
+
+ return keySet;
+ }
+
+ public Collection<V> values() {
+ if (values == null)
+ values = new Values();
+
+ return values;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void readObject(java.io.ObjectInputStream s) throws IOException,
ClassNotFoundException {
+ s.defaultReadObject();
+
+ int size = s.readInt();
+
+ init(size, loadFactor);
+
+ for (int i = 0; i < size; i++) {
+ K key = (K) s.readObject();
+ V value = (V) s.readObject();
+ putForCreate(key, value);
+ }
+
+ this.size = size;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void putForCreate(K key, V value) {
+ key = maskNull(key);
+
+ Entry<K, V>[] table = this.table;
+ int hash = hash(key);
+ int length = table.length;
+ int index = index(hash, length);
+
+ Entry<K, V> e = table[index];
+ while (e != null) {
+ index = nextIndex(index, length);
+ e = table[index];
+ }
+
+ table[index] = new Entry<K, V>(key, hash, value);
+ }
+
+ private void writeObject(java.io.ObjectOutputStream s) throws IOException {
+ s.defaultWriteObject();
+ s.writeInt(size);
+
+ for (Entry<K, V> e : table) {
+ if (e != null) {
+ s.writeObject(unmaskNull(e.key));
+ s.writeObject(e.value);
+ }
+ }
+ }
+
+ private static final class Entry<K, V> {
+ final K key;
+ final int hash;
+ final V value;
+
+ Entry(K key, int hash, V value) {
+ this.key = key;
+ this.hash = hash;
+ this.value = value;
+ }
+ }
+
+ private abstract class FasyCopyHashMapIterator<E> implements Iterator<E>
{
+ private int next = 0;
+ private int expectedCount = modCount;
+ private int current = -1;
+ private boolean hasNext;
+ Entry<K, V>[] table = FastCopyHashMap.this.table;
+
+ public boolean hasNext() {
+ if (hasNext == true)
+ return true;
+
+ Entry<K, V>[] table = this.table;
+ for (int i = next; i < table.length; i++) {
+ if (table[i] != null) {
+ next = i;
+ return hasNext = true;
+ }
+ }
+
+ next = table.length;
+ return false;
+ }
+
+ protected Entry<K, V> nextEntry() {
+ if (modCount != expectedCount)
+ throw new ConcurrentModificationException();
+
+ if (!hasNext && !hasNext())
+ throw new NoSuchElementException();
+
+ current = next++;
+ hasNext = false;
+
+ return table[current];
+ }
+
+ @SuppressWarnings("unchecked")
+ public void remove() {
+ if (modCount != expectedCount)
+ throw new ConcurrentModificationException();
+
+ int current = this.current;
+ int delete = current;
+
+ if (current == -1)
+ throw new IllegalStateException();
+
+ // Invalidate current (prevents multiple remove)
+ this.current = -1;
+
+ // Start were we relocate
+ next = delete;
+
+ Entry<K, V>[] table = this.table;
+ if (table != FastCopyHashMap.this.table) {
+ FastCopyHashMap.this.remove(table[delete].key);
+ table[delete] = null;
+ expectedCount = modCount;
+ return;
+ }
+
+
+ int length = table.length;
+ int i = delete;
+
+ table[delete] = null;
+ size--;
+
+ for (; ;) {
+ i = nextIndex(i, length);
+ Entry<K, V> e = table[i];
+ if (e == null)
+ break;
+
+ int prefer = index(e.hash, length);
+ if ((i < prefer && (prefer <= delete || delete <= i))
+ || (prefer <= delete && delete <= i)) {
+ // Snapshot the unseen portion of the table if we have
+ // to relocate an entry that was already seen by this iterator
+ if (i < current && current <= delete && table
== FastCopyHashMap.this.table) {
+ int remaining = length - current;
+ Entry<K, V>[] newTable = (Entry<K, V>[]) new
Entry[remaining];
+ System.arraycopy(table, current, newTable, 0, remaining);
+
+ // Replace iterator's table.
+ // Leave table local var pointing to the real table
+ this.table = newTable;
+ next = 0;
+ }
+
+ // Do the swap on the real table
+ table[delete] = e;
+ table[i] = null;
+ delete = i;
+ }
+ }
+ }
+ }
+
+
+ private class KeyIterator extends FasyCopyHashMapIterator<K> {
+ public K next() {
+ return unmaskNull(nextEntry().key);
+ }
+ }
+
+ private class ValueIterator extends FasyCopyHashMapIterator<V> {
+ public V next() {
+ return nextEntry().value;
+ }
+ }
+
+ private class EntryIterator extends FasyCopyHashMapIterator<Map.Entry<K,
V>> {
+ private class WriteThroughEntry extends SimpleEntry<K, V> {
+ WriteThroughEntry(K key, V value) {
+ super(key, value);
+ }
+
+ public V setValue(V value) {
+ if (table != FastCopyHashMap.this.table)
+ FastCopyHashMap.this.put(getKey(), value);
+
+ return super.setValue(value);
+ }
+ }
+
+ public Map.Entry<K, V> next() {
+ Entry<K, V> e = nextEntry();
+ return new WriteThroughEntry(unmaskNull(e.key), e.value);
+ }
+
+ }
+
+ private class KeySet extends AbstractSet<K> {
+ public Iterator<K> iterator() {
+ return new KeyIterator();
+ }
+
+ public void clear() {
+ FastCopyHashMap.this.clear();
+ }
+
+ public boolean contains(Object o) {
+ return containsKey(o);
+ }
+
+ public boolean remove(Object o) {
+ int size = size();
+ FastCopyHashMap.this.remove(o);
+ return size() < size;
+ }
+
+ public int size() {
+ return FastCopyHashMap.this.size();
+ }
+ }
+
+ private class Values extends AbstractCollection<V> {
+ public Iterator<V> iterator() {
+ return new ValueIterator();
+ }
+
+ public void clear() {
+ FastCopyHashMap.this.clear();
+ }
+
+ public int size() {
+ return FastCopyHashMap.this.size();
+ }
+ }
+
+ private class EntrySet extends AbstractSet<Map.Entry<K, V>> {
+ public Iterator<Map.Entry<K, V>> iterator() {
+ return new EntryIterator();
+ }
+
+ public boolean contains(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
+ Object value = get(entry.getKey());
+ return eq(entry.getValue(), value);
+ }
+
+ public void clear() {
+ FastCopyHashMap.this.clear();
+ }
+
+ public boolean isEmpty() {
+ return FastCopyHashMap.this.isEmpty();
+ }
+
+ public int size() {
+ return FastCopyHashMap.this.size();
+ }
+ }
+
+ protected static class SimpleEntry<K, V> implements Map.Entry<K, V> {
+ private K key;
+ private V value;
+
+ SimpleEntry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ SimpleEntry(Map.Entry<K, V> entry) {
+ this.key = entry.getKey();
+ this.value = entry.getValue();
+ }
+
+ public K getKey() {
+ return key;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ public V setValue(V value) {
+ V old = this.value;
+ this.value = value;
+ return old;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
+ return eq(key, e.getKey()) && eq(value, e.getValue());
+ }
+
+ public int hashCode() {
+ return (key == null ? 0 : hash(key)) ^
+ (value == null ? 0 : hash(value));
+ }
+
+ public String toString() {
+ return getKey() + "=" + getValue();
+ }
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/NameParser.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/NameParser.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/NameParser.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming.util;
+
+import javax.naming.CompositeName;
+import javax.naming.Name;
+import javax.naming.NamingException;
+
+/**
+ * Name parser used by the NamingContext instances. Relies on composite name instances.
+ *
+ * @author John E. Bailey
+ */
+public class NameParser implements javax.naming.NameParser {
+
+ public static final NameParser INSTANCE = new NameParser();
+
+ private NameParser() {
+ }
+
+ /**
+ * Parse the string name into a {@code javax.naming.Name} instance.
+ *
+ * @param name The name to parse
+ * @return The parsed name.
+ * @throws javax.naming.NamingException
+ */
+ public Name parse(String name) throws NamingException {
+ return new CompositeName(name);
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/NamingUtils.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/NamingUtils.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/NamingUtils.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,274 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming.util;
+
+import javax.naming.CannotProceedException;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.NotContextException;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * Common utility functions used by the naming implementation.
+ *
+ * @author John E. Bailey
+ */
+public class NamingUtils
+{
+ private NamingUtils() {}
+
+ /**
+ * Create a subcontext including any intermediate contexts.
+ * @param ctx the parent JNDI Context under which value will be bound
+ * @param name the name relative to ctx of the subcontext.
+ * @return The new or existing JNDI subcontext
+ * @throws javax.naming.NamingException on any JNDI failure
+ */
+ private static Context createSubcontext(Context ctx, final Name name) throws
NamingException {
+ Context subctx = ctx;
+ for (int pos = 0; pos < name.size(); pos++) {
+ final String ctxName = name.get(pos);
+ try {
+ subctx = (Context) ctx.lookup(ctxName);
+ }
+ catch (NameNotFoundException e) {
+ subctx = ctx.createSubcontext(ctxName);
+ }
+ // The current subctx will be the ctx for the next name component
+ ctx = subctx;
+ }
+ return subctx;
+ }
+
+ /**
+ * Get the last component of a name.
+ *
+ * @param name the name
+ * @return the last component
+ */
+ public static String getLastComponent(final Name name) {
+ if(name.size() > 0)
+ return name.get(name.size() - 1);
+ return "";
+ }
+
+ /**
+ * Determine if a name is empty, or if ot contains only one component which is the
empty string.
+ *
+ * @param name the name
+ * @return {@code true} if the name is empty or contains one empty component
+ */
+ public static boolean isEmpty(final Name name) {
+ return name.isEmpty() || (name.size() == 1 &&
"".equals(name.get(0)));
+ }
+
+ /**
+ * Determine whether the last component is empty.
+ *
+ * @param name the name to test
+ * @return {@code true} if the last component is empty, or if the name is empty
+ */
+ public static boolean isLastComponentEmpty(final Name name) {
+ return name.isEmpty() || getLastComponent(name).equals("");
+ }
+
+ /**
+ * Create a name-not-found exception.
+ *
+ * @param name the name
+ * @param contextName the context name
+ * @return the exception
+ */
+ public static NameNotFoundException nameNotFoundException(final String name, final
Name contextName) {
+ return new NameNotFoundException(String.format("Name '%s' not found
in context '%s'", name, contextName.toString()));
+ }
+
+ /**
+ * Create a name-already-bound exception.
+ *
+ * @param name the name
+ * @return the exception
+ */
+ public static NameAlreadyBoundException nameAlreadyBoundException(final Name name) {
+ return new NameAlreadyBoundException(name.toString());
+ }
+
+ /**
+ * Create an invalid name exception for an empty name.
+ *
+ * @return the exception
+ */
+ public static InvalidNameException emptyNameException() {
+ return new InvalidNameException("An empty name is not allowed");
+ }
+
+ /**
+ * Return a not-context exception for a name.
+ *
+ * @param name the name
+ * @return the exception
+ */
+ public static NotContextException notAContextException(Name name) {
+ return new NotContextException(name.toString());
+ }
+
+ /**
+ * Return a general naming exception with a root cause.
+ *
+ * @param message the message
+ * @param cause the exception cause, or {@code null} for none
+ * @return the exception
+ */
+ public static NamingException namingException(final String message, final Throwable
cause) {
+ final NamingException exception = new NamingException(message);
+ if (cause != null) exception.initCause(cause);
+ return exception;
+ }
+
+ /**
+ * Return a general naming exception with a root cause and a remaining name field.
+ *
+ * @param message the message
+ * @param cause the exception cause, or {@code null} for none
+ * @param remainingName the remaining name
+ * @return the exception
+ */
+ public static NamingException namingException(final String message, final Throwable
cause, final Name remainingName) {
+ final NamingException exception = namingException(message, cause);
+ exception.setRemainingName(remainingName);
+ return exception;
+ }
+
+ /**
+ * Return a cannot-proceed exception.
+ *
+ * @param resolvedObject the resolved object
+ * @param remainingName the remaining name
+ * @return the exception
+ */
+ public static CannotProceedException cannotProceedException(final Object
resolvedObject, final Name remainingName) {
+ final CannotProceedException cpe = new CannotProceedException();
+ cpe.setResolvedObj(resolvedObject);
+ cpe.setRemainingName(remainingName);
+ return cpe;
+ }
+
+ /**
+ * Return a naming enumeration over a collection.
+ *
+ * @param collection the collection
+ * @param <T> the member type
+ * @return the enumeration
+ */
+ public static <T> NamingEnumeration<T> namingEnumeration(final
Collection<T> collection) {
+ final Iterator<T> iterator = collection.iterator();
+ return new NamingEnumeration<T>() {
+ public T next() {
+ return nextElement();
+ }
+
+ public boolean hasMore() {
+ return hasMoreElements();
+ }
+
+ public void close() {
+ }
+
+ public boolean hasMoreElements() {
+ return iterator.hasNext();
+ }
+
+ public T nextElement() {
+ return iterator.next();
+ }
+ };
+ }
+
+ /**
+ * Rebind val to name in ctx, and make sure that all intermediate contexts exist
+ *
+ * @param ctx the parent JNDI Context under which value will be bound
+ * @param name the name relative to ctx where value will be bound
+ * @param value the value to bind.
+ * @throws javax.naming.NamingException for any error
+ */
+ public static void rebind(final Context ctx, final String name, final Object value)
throws NamingException {
+ final Name n = ctx.getNameParser("").parse(name);
+ rebind(ctx, n, value);
+ }
+
+ /**
+ * Rebind val to name in ctx, and make sure that all intermediate contexts exist
+ *
+ * @param ctx the parent JNDI Context under which value will be bound
+ * @param name the name relative to ctx where value will be bound
+ * @param value the value to bind.
+ * @throws javax.naming.NamingException for any error
+ */
+ public static void rebind(final Context ctx, final Name name, final Object value)
throws NamingException {
+ final int size = name.size();
+ final String atom = name.get(size - 1);
+ final Context parentCtx = createSubcontext(ctx, name.getPrefix(size - 1));
+ parentCtx.rebind(atom, value);
+ }
+
+ /**
+ * Unbinds a name from ctx, and removes parents if they are empty
+ *
+ * @param ctx the parent JNDI Context under which the name will be unbound
+ * @param name The name to unbind
+ * @throws javax.naming.NamingException for any error
+ */
+ public static void unbind(Context ctx, String name) throws NamingException {
+ unbind(ctx, ctx.getNameParser("").parse(name));
+ }
+
+ /**
+ * Unbinds a name from ctx, and removes parents if they are empty
+ *
+ * @param ctx the parent JNDI Context under which the name will be unbound
+ * @param name The name to unbind
+ * @throws javax.naming.NamingException for any error
+ */
+ public static void unbind(Context ctx, Name name) throws NamingException {
+ ctx.unbind(name); //unbind the end node in the name
+ int sz = name.size();
+ // walk the tree backwards, stopping at the domain
+ while (--sz > 0) {
+ Name pname = name.getPrefix(sz);
+ try {
+ ctx.destroySubcontext(pname);
+ }
+ catch (NamingException e) {
+ //log.trace("Unable to remove context " + pname, e);
+ break;
+ }
+ }
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/SecurityActions.java
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/SecurityActions.java
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/java/org/gatein/naming/util/SecurityActions.java 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,137 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.gatein.naming.util;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Package privileged actions
+ *
+ * @author Scott.Stark(a)jboss.org
+ * @author Jason T. Greene
+ * @author John E. Bailey
+ * @version $Id $
+ */
+public class SecurityActions
+{
+ private interface TCLAction {
+ class UTIL {
+ static TCLAction getTCLAction() {
+ return System.getSecurityManager() == null ? NON_PRIVILEGED :
PRIVILEGED;
+ }
+
+ static ClassLoader getContextClassLoader() {
+ return getTCLAction().getContextClassLoader();
+ }
+
+ static ClassLoader getContextClassLoader(Thread thread) {
+ return getTCLAction().getContextClassLoader(thread);
+ }
+
+ static void setContextClassLoader(ClassLoader cl) {
+ getTCLAction().setContextClassLoader(cl);
+ }
+
+ static void setContextClassLoader(Thread thread, ClassLoader cl) {
+ getTCLAction().setContextClassLoader(thread, cl);
+ }
+ }
+
+ TCLAction NON_PRIVILEGED = new TCLAction() {
+ public ClassLoader getContextClassLoader() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+
+ public ClassLoader getContextClassLoader(Thread thread) {
+ return thread.getContextClassLoader();
+ }
+
+ public void setContextClassLoader(ClassLoader cl) {
+ Thread.currentThread().setContextClassLoader(cl);
+ }
+
+ public void setContextClassLoader(Thread thread, ClassLoader cl) {
+ thread.setContextClassLoader(cl);
+ }
+ };
+
+ TCLAction PRIVILEGED = new TCLAction() {
+ private final PrivilegedAction<ClassLoader> getTCLPrivilegedAction =
new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ };
+
+ public ClassLoader getContextClassLoader() {
+ return AccessController.doPrivileged(getTCLPrivilegedAction);
+ }
+
+ public ClassLoader getContextClassLoader(final Thread thread) {
+ return AccessController.doPrivileged(new
PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return thread.getContextClassLoader();
+ }
+ });
+ }
+
+ public void setContextClassLoader(final ClassLoader cl) {
+ AccessController.doPrivileged(
+ new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ Thread.currentThread().setContextClassLoader(cl);
+ return null;
+ }
+ }
+ );
+ }
+
+ public void setContextClassLoader(final Thread thread, final ClassLoader cl)
{
+ AccessController.doPrivileged(
+ new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ thread.setContextClassLoader(cl);
+ return null;
+ }
+ }
+ );
+ }
+ };
+
+ ClassLoader getContextClassLoader();
+
+ ClassLoader getContextClassLoader(Thread thread);
+
+ void setContextClassLoader(ClassLoader cl);
+
+ void setContextClassLoader(Thread thread, ClassLoader cl);
+ }
+
+ protected static ClassLoader getContextClassLoaderProtected() {
+ return TCLAction.UTIL.getContextClassLoader();
+ }
+
+ protected static void setContextClassLoaderProtected(ClassLoader loader) {
+ TCLAction.UTIL.setContextClassLoader(loader);
+ }
+}
Added:
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/resources/jndi.properties
===================================================================
---
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/resources/jndi.properties
(rev 0)
+++
sandbox/as7_support/branches/gatein-as7/gatein-naming/src/main/resources/jndi.properties 2011-10-03
15:17:29 UTC (rev 7608)
@@ -0,0 +1,2 @@
+java.naming.factory.initial=org.gatein.naming.InitialContextFactory
+java.naming.factory.url.pkgs=org.gatein.naming.interfaces
\ No newline at end of file