[jboss-svn-commits] JBoss Common SVN: r4190 - invokablecontainer/trunk/api/src/main/java/org/jboss/invokable.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Thu Mar 25 11:05:25 EDT 2010
Author: david.lloyd at jboss.com
Date: 2010-03-25 11:05:24 -0400 (Thu, 25 Mar 2010)
New Revision: 4190
Added:
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ClientInvocationContext.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/CopyOnWriteHashMap.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatcherLocation.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatcherLocationScheme.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatchingInvocationProcessor.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ExportedInvocationDispatcher.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FieldSetter.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationForwarder.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationReply.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoClientContextException.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoNodeContextException.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoServerContextException.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeAssociation.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeAssociationHandle.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeInvocationContext.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeLocation.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/RemoteInvokerContext.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ServerInvocationContext.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Visitor.java
Modified:
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FastCopyHashMap.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Invocation.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationDispatcher.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationProcessor.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Keys.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ObjectInvocationDispatcher.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProcessingInvocationDispatcher.java
invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProxyInvocationHandler.java
Log:
Commit this before I break it again...!
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ClientInvocationContext.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ClientInvocationContext.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ClientInvocationContext.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,77 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.util.Map;
+
+/**
+ * A client invocation context is an invocation environment which supports outbound method invocations only.
+ *
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+public class ClientInvocationContext {
+ static {
+ // configure the global context (todo)
+ globalContext = null;
+ }
+
+ ClientInvocationContext() {
+ }
+
+ private static final ClientInvocationContext globalContext;
+
+ private static final ThreadLocal<ClientInvocationContext> current = new ThreadLocal<ClientInvocationContext>();
+
+ public static ClientInvocationContext getCurrent() {
+ final ClientInvocationContext context = current.get();
+ return context == null ? globalContext : context;
+ }
+
+ public static ClientInvocationContext requireCurrent() throws NoClientContextException {
+ final ClientInvocationContext context = getCurrent();
+ if (context == null) {
+ throw new NoClientContextException();
+ }
+ return context;
+ }
+
+ private final Map<String, InvocationForwarder> forwarders = new CopyOnWriteHashMap<String, InvocationForwarder>();
+
+ protected InvocationForwarder getForwarder(String remoteNodeName, String remoteContextName) {
+ return forwarders.get(remoteContextName);
+ }
+
+ public void start() {
+ if (current.get() != null) {
+ throw new IllegalStateException("A client invocation context is already associated with the current thread");
+ }
+ current.set(this);
+ }
+
+ public void end() {
+ if (current.get() == this) {
+ current.set(null);
+ }
+ }
+
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/CopyOnWriteHashMap.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/CopyOnWriteHashMap.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/CopyOnWriteHashMap.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,197 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ * @param <K> key type
+ * @param <V> value type
+ */
+final class CopyOnWriteHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> {
+ private volatile Map<K, V> map = Collections.emptyMap();
+
+ public V putIfAbsent(final K key, final V value) {
+ if (key == null) {
+ throw new IllegalArgumentException("key is null");
+ }
+ synchronized (this) {
+ final Map<K, V> map = this.map;
+ if (map.containsKey(key)) {
+ return map.get(key);
+ }
+ this.map = new FastCopyHashMap<K, V>(map, key, value);
+ return null;
+ }
+ }
+
+ public boolean remove(final Object key, final Object value) {
+ if (key == null) return false;
+ synchronized (this) {
+ final Map<K, V> map = this.map;
+ final V mapVal = map.get(key);
+ if (value == null && mapVal == null || value != null && value.equals(mapVal)) {
+ if (map.size() == 1) {
+ this.map = Collections.emptyMap();
+ } else {
+ final FastCopyHashMap<K, V> newMap = new FastCopyHashMap<K, V>(map);
+ newMap.remove(key);
+ this.map = newMap;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean replace(final K key, final V oldValue, final V newValue) {
+ if (key == null) {
+ throw new IllegalArgumentException("key is null");
+ }
+ synchronized (this) {
+ final Map<K, V> map = this.map;
+ final V mapVal = map.get(key);
+ if (oldValue == null && mapVal == null || oldValue != null && oldValue.equals(mapVal)) {
+ this.map = new FastCopyHashMap<K, V>(map, key, newValue);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public V replace(final K key, final V value) {
+ if (key == null) {
+ throw new IllegalArgumentException("key is null");
+ }
+ synchronized (this) {
+ final Map<K, V> map = this.map;
+ if (map.containsKey(key)) {
+ try {
+ return map.get(key);
+ } finally {
+ this.map = new FastCopyHashMap<K, V>(map, key, value);
+ }
+ }
+ }
+ return null;
+ }
+
+ public Set<Entry<K, V>> entrySet() {
+ return Collections.unmodifiableSet(map.entrySet());
+ }
+
+ public V get(final Object key) {
+ return map.get(key);
+ }
+
+ public int size() {
+ return map.size();
+ }
+
+ public boolean containsKey(final Object key) {
+ return map.containsKey(key);
+ }
+
+ public boolean containsValue(final Object value) {
+ return map.containsValue(value);
+ }
+
+ public void clear() {
+ map = Collections.emptyMap();
+ }
+
+ public Set<K> keySet() {
+ return Collections.unmodifiableSet(map.keySet());
+ }
+
+ public Collection<V> values() {
+ return Collections.unmodifiableCollection(map.values());
+ }
+
+ public V put(final K key, final V value) {
+ if (key == null) {
+ throw new IllegalArgumentException("key is null");
+ }
+ synchronized (this) {
+ final Map<K, V> map = this.map;
+ try {
+ return map.get(key);
+ } finally {
+ this.map = new FastCopyHashMap<K,V>(map, key, value);
+ }
+ }
+ }
+
+ public V remove(final Object key) {
+ if (key == null) return null;
+ synchronized (this) {
+ final Map<K, V> map = this.map;
+ if (map.containsKey(key)) {
+ if (map.size() == 1) {
+ try {
+ return map.get(key);
+ } finally {
+ this.map = Collections.emptyMap();
+ }
+ } else {
+ final FastCopyHashMap<K, V> newMap = new FastCopyHashMap<K, V>(map);
+ try {
+ return newMap.remove(key);
+ } finally {
+ this.map = newMap;
+ }
+ }
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public void putAll(final Map<? extends K, ? extends V> m) {
+ synchronized (this) {
+ final FastCopyHashMap<K, V> newMap = new FastCopyHashMap<K, V>(map);
+ newMap.putAll(m);
+ map = newMap;
+ }
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ protected CopyOnWriteHashMap<K, V> clone() {
+ try {
+ final CopyOnWriteHashMap<K, V> clone = (CopyOnWriteHashMap<K, V>) super.clone();
+ final Map<K, V> map = this.map;
+ if (! map.isEmpty()) {
+ clone.map = new FastCopyHashMap<K, V>(map);
+ }
+ return clone;
+ } catch (CloneNotSupportedException e) {
+ throw new IllegalStateException();
+ }
+ }
+}
\ No newline at end of file
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatcherLocation.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatcherLocation.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatcherLocation.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,95 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+public final class DispatcherLocation implements Serializable {
+
+ private static final long serialVersionUID = -8104174497055191121L;
+
+ private static final FieldSetter<DispatcherLocation> hashCodeSetter = FieldSetter.forField(DispatcherLocation.class, "hashCode");
+
+ private final NodeLocation nodeLocation;
+ private final String contextName;
+ private final String dispatcherName;
+ private transient final int hashCode;
+
+ public DispatcherLocation(final NodeLocation nodeLocation, final String contextName, final String dispatcherName) {
+ if (nodeLocation == null) {
+ throw new IllegalArgumentException("nodeLocation is null");
+ }
+ if (contextName == null) {
+ throw new IllegalArgumentException("contextName is null");
+ }
+ if (dispatcherName == null) {
+ throw new IllegalArgumentException("dispatcherName is null");
+ }
+ this.nodeLocation = nodeLocation;
+ this.contextName = contextName;
+ this.dispatcherName = dispatcherName;
+ hashCode = hashCode(nodeLocation, contextName, dispatcherName);
+ }
+
+ private static int hashCode(final NodeLocation nodeLocation, final String contextName, final String dispatcherName) {
+ return (nodeLocation.hashCode() * 31 + contextName.hashCode()) * 31 + dispatcherName.hashCode();
+ }
+
+ public NodeLocation getNodeLocation() {
+ return nodeLocation;
+ }
+
+ public String getContextName() {
+ return contextName;
+ }
+
+ public String getDispatcherName() {
+ return dispatcherName;
+ }
+
+ public boolean equals(final Object obj) {
+ return obj instanceof DispatcherLocation && equals((DispatcherLocation) obj);
+ }
+
+ public boolean equals(final DispatcherLocation other) {
+ return this == other || other != null
+ && nodeLocation.equals(other.nodeLocation)
+ && contextName.equals(other.contextName)
+ && dispatcherName.equals(other.dispatcherName);
+ }
+
+ public int hashCode() {
+ return hashCode;
+ }
+
+ private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+ ois.defaultReadObject();
+ hashCodeSetter.setInt(this, hashCode(nodeLocation, contextName, dispatcherName));
+ }
+
+ public String toString() {
+ return String.format("Dispatcher location {nodeLocation=\"%s\", contextName=\"%s\", dispatcherName=\"%s\"}", nodeLocation, contextName, dispatcherName);
+ }
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatcherLocationScheme.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatcherLocationScheme.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatcherLocationScheme.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,39 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+/**
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+public interface DispatcherLocationScheme {
+
+ /**
+ * Get a dispatcher. Returns {@code null} if no dispatcher matches the given specification.
+ *
+ * @param locationName the location name
+ * @param remoteContextName the remote context name
+ * @param dispatcherName the dispatcher name
+ * @return the dispatcher
+ */
+ InvocationDispatcher getInvocationDispatcher(String locationName, String remoteContextName, String dispatcherName);
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatchingInvocationProcessor.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatchingInvocationProcessor.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/DispatchingInvocationProcessor.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+class DispatchingInvocationProcessor implements InvocationProcessor, Serializable {
+
+ private static final long serialVersionUID = 2537460849611664946L;
+
+ DispatchingInvocationProcessor() {
+ }
+
+ public InvocationReply processInvocation(final InvocationDispatcher dispatcher, final Invocation invocation) throws InvocationException {
+ return dispatcher.dispatch(invocation);
+ }
+
+ public <I> void accept(final Visitor<InvocationProcessor, I> visitor, final I param) {
+ visitor.visit(this, param);
+ }
+
+ protected Object readResolve() {
+ return InvocationProcessor.DISPATCHING;
+ }
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ExportedInvocationDispatcher.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ExportedInvocationDispatcher.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ExportedInvocationDispatcher.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.io.IOError;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+final class ExportedInvocationDispatcher implements InvocationDispatcher, Serializable {
+
+ private static final long serialVersionUID = -3950038476252367014L;
+
+ private transient final NodeInvocationContext nodeInvocationContext;
+ private final DispatcherLocation dispatcherLocation;
+
+ private static final FieldSetter<ExportedInvocationDispatcher> nodeInvocationContextSetter = FieldSetter.forField(ExportedInvocationDispatcher.class, "nodeInvocationContext");
+
+ ExportedInvocationDispatcher(final NodeInvocationContext nodeInvocationContext, final DispatcherLocation dispatcherLocation) {
+ this.nodeInvocationContext = nodeInvocationContext;
+ this.dispatcherLocation = dispatcherLocation;
+ }
+
+ public InvocationReply dispatch(final Invocation invocation) throws InvocationException {
+ final NodeAssociation association = nodeInvocationContext.getNodeAssociation(dispatcherLocation.getNodeLocation());
+ final InvocationForwarder forwarder = association.getInvocationForwarder(dispatcherLocation.getContextName());
+ try {
+ return forwarder.dispatch(dispatcherLocation.getDispatcherName(), invocation);
+ } catch (IOException e) {
+ throw new IOError(e);
+ }
+ }
+
+ public <I> void accept(final Visitor<InvocationDispatcher, I> visitor, final I param) {
+ visitor.visit(this, param);
+ }
+
+
+ private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+ ois.defaultReadObject();
+ nodeInvocationContextSetter.set(this, NodeInvocationContext.requireCurrent());
+ }
+}
Modified: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FastCopyHashMap.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FastCopyHashMap.java 2010-03-23 20:10:38 UTC (rev 4189)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FastCopyHashMap.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -47,7 +47,7 @@
*
* @author Jason T. Greene
*/
-class FastCopyHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable
+final class FastCopyHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable
{
/**
* Marks null keys.
@@ -138,6 +138,12 @@
}
}
+ public FastCopyHashMap(final Map<K, V> map, final K key, final V value)
+ {
+ this(map);
+ put(key, value);
+ }
+
@SuppressWarnings("unchecked")
private void init(int initialCapacity, float loadFactor)
{
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FieldSetter.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FieldSetter.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FieldSetter.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,121 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+final class FieldSetter<T> {
+ private final Field field;
+
+ private FieldSetter(final Field field) {
+ this.field = field;
+ }
+
+ static <T> FieldSetter<T> forField(final Class<T> clazz, final String name) {
+ return AccessController.doPrivileged(new PrivilegedAction<FieldSetter<T>>() {
+ public FieldSetter<T> run() {
+ try {
+ final Field field = clazz.getDeclaredField(name);
+ field.setAccessible(true);
+ return new FieldSetter<T>(field);
+ } catch (NoSuchFieldException e) {
+ throw new NoSuchFieldError(e.getMessage());
+ }
+ }
+ });
+ }
+
+ public void set(final T obj, final Object value) {
+ try {
+ field.set(obj, value);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+
+ public void setBoolean(final T obj, final boolean z) {
+ try {
+ field.setBoolean(obj, z);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+
+ public void setByte(final T obj, final byte b) {
+ try {
+ field.setByte(obj, b);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+
+ public void setChar(final T obj, final char c) {
+ try {
+ field.setChar(obj, c);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+
+ public void setShort(final T obj, final short s) {
+ try {
+ field.setShort(obj, s);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+
+ public void setInt(final T obj, final int i) {
+ try {
+ field.setInt(obj, i);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+
+ public void setLong(final T obj, final long l) {
+ try {
+ field.setLong(obj, l);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+
+ public void setFloat(final T obj, final float f) {
+ try {
+ field.setFloat(obj, f);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+
+ public void setDouble(final T obj, final double d) {
+ try {
+ field.setDouble(obj, d);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAccessError(e.getMessage());
+ }
+ }
+}
Modified: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Invocation.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Invocation.java 2010-03-23 20:10:38 UTC (rev 4189)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Invocation.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -25,13 +25,8 @@
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.io.ObjectStreamField;
import java.io.Serializable;
-import java.lang.reflect.Field;
import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Arrays;
/**
* A unified view of a {@link Method} invocation. Composes the target method, arguments, and mapped context into a single
@@ -44,46 +39,30 @@
public final class Invocation implements Serializable {
private static final long serialVersionUID = 2691631710015102611L;
- private static final Field targetMethodField;
/**
- * Serialization of an {@code Invocation} is handled specially. The {@code args} and {@code context} fields are
- * serialized normally, but because {@link Method} is not serializable, the {@code targetMethod} field is not directly
- * serialized. Instead, it is written (after the two aforementioned fields) as three distinct objects:
- * <ol>
- * <li><b>Declaring Class</b> - this is the result of {@code targetMethod.getDeclaringClass()}.</li>
- * <li><b>Method Name</b> - this is the string name, as returned by {@code targetMethod.getName()}.</li>
- * <li><b>Parameter Types</b> - this is an array of {@code Class} objects which represents the method's parameter
- * types, as returned by {@code targetMethod.getParameterTypes()}.
- * </ol>
- * On deserialization, the method is then looked up on the declaring class. If no valid, matching public method
- * is found, an {@link java.io.InvalidObjectException} is thrown and deserialization fails.
+ * This field contains the method-call arguments.
*/
- private static final ObjectStreamField[] serialPersistentFields = {
- new ObjectStreamField("args", Object[].class),
- new ObjectStreamField("context", InvocationProperties.class),
- };
+ private transient final Object[] args;
/**
- * This field contains the method-call arguments.
- *
- * @serial
+ * This field specifies the target method.
*/
- private final Object[] args;
-
- private static final Object[] NONE = new Object[0];
-
- @SuppressWarnings({ "InstanceVariableMayNotBeInitializedByReadObject" })
private transient final Method targetMethod;
/**
* This field contains the invocation context. As a special case, if the context is empty at serialization
* time, it is written as {@code null} to conserve bandwidth.
- *
- * @serial
*/
- private volatile InvocationProperties properties;
+ private transient volatile InvocationProperties properties;
+ private static final Object[] NO_OBJECTS = new Object[0];
+ private static final Class<?>[] NO_CLASSES = new Class[0];
+
+ private static final FieldSetter<Invocation> argsSetter = FieldSetter.forField(Invocation.class, "args");
+ private static final FieldSetter<Invocation> targetMethodSetter = FieldSetter.forField(Invocation.class, "targetMethod");
+ private static final FieldSetter<Invocation> propertiesSetter = FieldSetter.forField(Invocation.class, "properties");
+
/**
* Construct a new instance.
*
@@ -96,7 +75,7 @@
throw new IllegalArgumentException("targetMethod is null");
}
this.targetMethod = targetMethod;
- this.args = defaulted(args, NONE);
+ this.args = defaulted(args, NO_OBJECTS);
this.properties = defaulted(properties, InvocationProperties.EMPTY);
}
@@ -116,23 +95,9 @@
* @param targetMethod the method being invoked
*/
public Invocation(final Method targetMethod) {
- this(InvocationProperties.EMPTY, targetMethod, NONE);
+ this(InvocationProperties.EMPTY, targetMethod, NO_OBJECTS);
}
- static {
- targetMethodField = AccessController.doPrivileged(new PrivilegedAction<Field>() {
- public Field run() {
- try {
- final Field field = Invocation.class.getDeclaredField("targetMethod");
- field.setAccessible(true);
- return field;
- } catch (NoSuchFieldException e) {
- throw new IllegalStateException(e);
- }
- }
- });
- }
-
//-------------------------------------------------------------------------------------||
// Contracts --------------------------------------------------------------------------||
//-------------------------------------------------------------------------------------||
@@ -178,86 +143,42 @@
// Serialization ----------------------------------------------------------------------||
//-------------------------------------------------------------------------------------||
- /**
- * Serializes the invocation with a custom form
- *
- * @serialData After all non-transient fields are written, we pipe out the target method's declaring class, method
- * name, and array of parameter types. These are used to reconstitute the target Method, which is not itself
- * Serializable
- */
- private void writeObject(final ObjectOutputStream out) throws IOException {
- // Default write of non-transient fields
- out.defaultWriteObject();
- // Write out the target method by decomposing it into Serializable parts
+ private void writeObject(ObjectOutputStream oos) throws IOException {
+ oos.defaultWriteObject();
final Method targetMethod = this.targetMethod;
- final Class<?> declaringClass = targetMethod.getDeclaringClass();
- final String name = targetMethod.getName();
- final Class<?>[] paramTypes = targetMethod.getParameterTypes();
- out.writeObject(declaringClass);
- out.writeObject(name);
- out.writeObject(paramTypes);
- // See if the invocation context is empty
+ oos.writeObject(targetMethod.getDeclaringClass());
+ oos.writeUTF(targetMethod.getName());
+ final Class<?>[] parameterTypes = targetMethod.getParameterTypes();
+ oos.writeObject(parameterTypes.length == 0 ? null : parameterTypes);
+ final Object[] args = this.args;
+ oos.writeObject(args.length == 0 ? null : args);
final InvocationProperties properties = this.properties;
- if (properties.isEmpty()) {
- // Null out; we don't need to send empty properties. On deserialization
- // we'll just re-instantiate.
- out.writeObject(null);
- } else {
- // Write invocation context
- out.writeObject(properties);
- }
+ oos.writeObject(properties.isEmpty() ? null : properties);
}
- private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
- // Get default form
- in.defaultReadObject();
- // Assert invariants
- if (getArgs() == null) {
- throw new IllegalArgumentException("Deserialization resulted in null arguments to the target method");
- }
- // Reconstruct the Method by getting the declaring class, method name, and signature
- final Class<?> declaringClass = (Class<?>) in.readObject();
- final String methodName = (String) in.readObject();
- final Class<?>[] paramTypes = (Class<?>[]) in.readObject();
- // Some more assertions
- if (declaringClass == null) {
- throw new InvalidObjectException("Declaring class was not read in during deserialization");
- }
- if (methodName == null) {
- throw new InvalidObjectException("Target method name was not read in during deserialization");
- }
- if (paramTypes == null) {
- throw new InvalidObjectException(
- "Parameter types of the target method were not read in during deserialization");
- }
- // Obtain the target method
+ private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+ ois.defaultReadObject();
+ final Class<?> declaringClass = nonNull((Class<?>) ois.readObject());
+ final String name = ois.readUTF();
+ final Class<?>[] parameterTypes = defaulted((Class<?>[]) ois.readObject(), NO_CLASSES);
final Method targetMethod;
try {
- targetMethod = declaringClass.getMethod(methodName, paramTypes);
- } catch (final NoSuchMethodException e) {
- throw new InvalidObjectException("Could not deserialize; no target method \"" + methodName + "\" found in "
- + declaringClass.getName() + " with param types " + Arrays.asList(paramTypes));
+ targetMethod = declaringClass.getMethod(name, parameterTypes);
+ } catch (NoSuchMethodException e) {
+ throw new InvalidObjectException("Invocation references a missing method");
}
- // Set the target method
- setTargetMethod(targetMethod);
- // Set the InvocationContext
- final InvocationProperties properties = (InvocationProperties) in.readObject();
- // If no context is provided
- if (properties == null) {
- // Replace with a new instance; this signals empty properties were present when the instance
- // was serialized
- this.properties = InvocationProperties.EMPTY;
- } else {
- this.properties = properties;
- }
+ targetMethodSetter.set(this, targetMethod);
+ final Object[] args = defaulted((Object[]) ois.readObject(), NO_OBJECTS);
+ argsSetter.set(this, args);
+ final InvocationProperties properties = defaulted((InvocationProperties) ois.readObject(), InvocationProperties.EMPTY);
+ propertiesSetter.set(this, properties);
}
- private void setTargetMethod(Method method) {
- try {
- targetMethodField.set(this, method);
- } catch (IllegalAccessException e) {
- throw new IllegalStateException(e);
+ private static <T> T nonNull(T value) throws InvalidObjectException {
+ if (value == null) {
+ throw new InvalidObjectException("unexpected null value");
}
+ return value;
}
private static <T> T defaulted(T value, T defaultValue) {
Modified: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationDispatcher.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationDispatcher.java 2010-03-23 20:10:38 UTC (rev 4189)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationDispatcher.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -42,5 +42,14 @@
* obtained via {@link InvocationException#getCause()}
* @throws IllegalArgumentException If the invocation is not specified (i.e. {@code null})
*/
- Object dispatch(Invocation invocation) throws InvocationException;
+ InvocationReply dispatch(Invocation invocation) throws InvocationException;
+
+ /**
+ * Pass this dispatcher to a visitor, followed by any delegate dispatcher.
+ *
+ * @param visitor the visitor to visit
+ * @param param the parameter
+ * @param <I> the parameter type, possibly {@link Void}
+ */
+ <I> void accept(Visitor<InvocationDispatcher, I> visitor, I param);
}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationForwarder.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationForwarder.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationForwarder.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,47 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.io.IOException;
+
+/**
+ * Forwards an invocation to a remote Server Invocation Context, possibly across some network connection. While an
+ * {@code InvocationDispatcher} represents a single invocation target, instances of this interface represent a single
+ * network path to a peer, which may have many {@code InvocationDispatcher}s on the receiving side. An instance of
+ * this interface is associated with one remote Server Invocation Context or a cluster of Server Invocation Contexts.
+ *
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+public interface InvocationForwarder {
+
+ /**
+ * Send an invocation across the network.
+ *
+ * @param dispatcherName the identifier of the dispatcher to use on the remote side
+ * @param invocation the invocation to execute
+ * @return the result of the invocation
+ * @throws IOException if an I/O error occurs
+ * @throws InvocationException if a remote invocation failed
+ */
+ InvocationReply dispatch(String dispatcherName, Invocation invocation) throws IOException, InvocationException;
+}
Modified: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationProcessor.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationProcessor.java 2010-03-23 20:10:38 UTC (rev 4189)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationProcessor.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -40,14 +40,19 @@
* obtained via {@link InvocationException#getCause()}
* @throws IllegalArgumentException If the invocation or dispatcher is not specified (i.e. {@code null})
*/
- Object processInvocation(InvocationDispatcher dispatcher, Invocation invocation) throws InvocationException, IllegalArgumentException;
+ InvocationReply processInvocation(InvocationDispatcher dispatcher, Invocation invocation) throws InvocationException, IllegalArgumentException;
/**
- * A simple dispatching invocation processor, used typically at the end of an interceptor chain.
+ * Pass this processor to a visitor, followed by any delegate processor.
+ *
+ * @param visitor the visitor to visit
+ * @param param the parameter
+ * @param <I> the parameter type, possibly {@link Void}
*/
- InvocationProcessor DISPATCHING = new InvocationProcessor() {
- public Object processInvocation(final InvocationDispatcher dispatcher, final Invocation invocation) throws InvocationException {
- return dispatcher.dispatch(invocation);
- }
- };
+ <I> void accept(Visitor<InvocationProcessor, I> visitor, I param);
+
+ /**
+ * A simple (serializable) dispatching invocation processor, used typically at the end of an interceptor chain.
+ */
+ InvocationProcessor DISPATCHING = new DispatchingInvocationProcessor();
}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationReply.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationReply.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationReply.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+public final class InvocationReply implements Serializable {
+
+ private static final long serialVersionUID = 4330152364952496586L;
+
+ private static final FieldSetter<InvocationReply> replySetter = FieldSetter.forField(InvocationReply.class, "reply");
+
+ private transient final Object reply;
+ private transient volatile InvocationProperties properties;
+
+ public InvocationReply(final Object reply) {
+ this.reply = reply;
+ }
+
+ public InvocationReply(final Object reply, final InvocationProperties properties) {
+ this.reply = reply;
+ this.properties = properties;
+ }
+
+ public Object getReply() {
+ return reply;
+ }
+
+ public InvocationProperties getProperties() {
+ return properties;
+ }
+
+ public void setProperties(final InvocationProperties properties) {
+ this.properties = properties;
+ }
+
+ private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+ ois.defaultReadObject();
+ replySetter.set(this, ois.readObject());
+ properties = defaulted((InvocationProperties) ois.readObject(), InvocationProperties.EMPTY);
+ }
+
+ private static <T> T defaulted(T value, T defaultValue) {
+ return value == null ? defaultValue : value;
+ }
+}
Modified: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Keys.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Keys.java 2010-03-23 20:10:38 UTC (rev 4189)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Keys.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -38,4 +38,8 @@
* The transaction associated with this invocation. Should yield a {@link javax.transaction.Transaction} (?).
*/
TRANSACTION,
+ /**
+ * The session identifier, for distinguishing between more than one target instance for a given dispatcher.
+ */
+ SESSION,
}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoClientContextException.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoClientContextException.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoClientContextException.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+public final class NoClientContextException extends IllegalStateException {
+
+ private static final long serialVersionUID = -1739332805464223362L;
+
+ /**
+ * Constructs a {@code NoClientContextException} with no detail message. The cause is not initialized, and may
+ * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}.
+ */
+ public NoClientContextException() {
+ }
+
+ /**
+ * Constructs a {@code NoClientContextException} with the specified detail message. The cause is not initialized, and
+ * may subsequently be initialized by a call to {@link #initCause(Throwable) initCause}.
+ *
+ * @param msg the detail message
+ */
+ public NoClientContextException(final String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a {@code NoClientContextException} with the specified cause. The detail message is set to:
+ * <pre>(cause == null ? null : cause.toString())</pre>
+ * (which typically contains the class and detail message of {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method)
+ */
+ public NoClientContextException(final Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a {@code NoClientContextException} with the specified detail message and cause.
+ *
+ * @param msg the detail message
+ * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method)
+ */
+ public NoClientContextException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoNodeContextException.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoNodeContextException.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoNodeContextException.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+public final class NoNodeContextException extends IllegalStateException {
+
+ private static final long serialVersionUID = -4218112918054622891L;
+
+ /**
+ * Constructs a {@code NoNodeContextException} with no detail message. The cause is not initialized, and may
+ * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}.
+ */
+ public NoNodeContextException() {
+ }
+
+ /**
+ * Constructs a {@code NoNodeContextException} with the specified detail message. The cause is not initialized, and may
+ * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}.
+ *
+ * @param msg the detail message
+ */
+ public NoNodeContextException(final String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a {@code NoNodeContextException} with the specified cause. The detail message is set to:
+ * <pre>(cause == null ? null : cause.toString())</pre>
+ * (which typically contains the class and detail message of {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method)
+ */
+ public NoNodeContextException(final Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a {@code NoNodeContextException} with the specified detail message and cause.
+ *
+ * @param msg the detail message
+ * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method)
+ */
+ public NoNodeContextException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+
+}
\ No newline at end of file
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoServerContextException.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoServerContextException.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NoServerContextException.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+public final class NoServerContextException extends IllegalStateException {
+
+ private static final long serialVersionUID = 3873017282274298512L;
+
+ /**
+ * Constructs a {@code NoServerContextException} with no detail message. The cause is not initialized, and may
+ * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}.
+ */
+ public NoServerContextException() {
+ }
+
+ /**
+ * Constructs a {@code NoServerContextException} with the specified detail message. The cause is not initialized, and
+ * may subsequently be initialized by a call to {@link #initCause(Throwable) initCause}.
+ *
+ * @param msg the detail message
+ */
+ public NoServerContextException(final String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a {@code NoServerContextException} with the specified cause. The detail message is set to:
+ * <pre>(cause == null ? null : cause.toString())</pre>
+ * (which typically contains the class and detail message of {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method)
+ */
+ public NoServerContextException(final Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a {@code NoServerContextException} with the specified detail message and cause.
+ *
+ * @param msg the detail message
+ * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method)
+ */
+ public NoServerContextException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeAssociation.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeAssociation.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeAssociation.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,39 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+/**
+ * An association with a node. This should be an active or "live" association.
+ *
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+public interface NodeAssociation {
+
+ /**
+ * Get an invocation forwarder for the associated remote node.
+ *
+ * @param contextName the context name
+ * @return the dispatcher, or {@code null} if none matched
+ */
+ InvocationForwarder getInvocationForwarder(String contextName);
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeAssociationHandle.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeAssociationHandle.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeAssociationHandle.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,39 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.io.Closeable;
+
+/**
+ * A handle for a node association, used to indicate to the client invocation context that the node association has
+ * ended.
+ *
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+public interface NodeAssociationHandle extends Closeable {
+
+ /**
+ * Call when the node association has been closed.
+ */
+ void close();
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeInvocationContext.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeInvocationContext.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeInvocationContext.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public final class NodeInvocationContext {
+ private final ConcurrentMap<NodeLocation, NodeAssociation> nodeAssociations = new ConcurrentHashMap<NodeLocation, NodeAssociation>();
+
+ private static final ThreadLocal<NodeInvocationContext> current = new ThreadLocal<NodeInvocationContext>();
+
+ private static final NodeInvocationContext global = null; // (todo - configure)
+
+ public NodeAssociationHandle addNodeAssociation(final NodeLocation location, final NodeAssociation association) throws IllegalArgumentException {
+ if (location == null) {
+ throw new IllegalArgumentException("location is null");
+ }
+ if (association == null) {
+ throw new IllegalArgumentException("association is null");
+ }
+ final String transport = location.getTransport();
+ if (transport.length() == 0 || transport.equals("*")) {
+ throw new IllegalArgumentException(location.toString() + " does not specify a specific transport");
+ }
+ final NodeAssociation appearing = nodeAssociations.putIfAbsent(location, association);
+ if (appearing != null) {
+ throw new IllegalArgumentException(location.toString() + " is already registered");
+ }
+ return new NodeAssociationHandle() {
+ public void close() {
+ nodeAssociations.remove(location, association);
+ }
+ };
+ }
+
+ public InvocationDispatcher createDispatcher(final DispatcherLocation dispatcherLocation) {
+ return new ExportedInvocationDispatcher(this, dispatcherLocation);
+ }
+
+ public static NodeInvocationContext getCurrent() {
+ return defaulted(current.get(), global);
+ }
+
+ public static NodeInvocationContext requireCurrent() {
+ final NodeInvocationContext context = getCurrent();
+ if (context == null) {
+ throw new NoNodeContextException();
+ }
+ return context;
+ }
+
+ public void start() {
+ if (current.get() != null) {
+ throw new IllegalStateException("A node invocation context is already associated with the current thread");
+ }
+ current.set(this);
+ }
+
+ public void end() {
+ if (current.get() == this) {
+ current.set(null);
+ }
+ }
+
+ private static <T> T defaulted(T val, T defVal) {
+ return val == null ? defVal : val;
+ }
+
+ public NodeAssociation getNodeAssociation(final NodeLocation nodeLocation) {
+ // (todo - access check)
+ final String transport = nodeLocation.getTransport();
+ if (transport.length() == 0 || transport.equals("*")) {
+ // (todo - index by transport type)
+ for (Map.Entry<NodeLocation, NodeAssociation> entry : nodeAssociations.entrySet()) {
+ if (nodeLocation.isSameNode(entry.getKey())) {
+ return entry.getValue();
+ }
+ }
+ return null;
+ } else {
+ return nodeAssociations.get(nodeLocation);
+ }
+ }
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeLocation.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeLocation.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/NodeLocation.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+public final class NodeLocation implements Serializable {
+
+ private static final long serialVersionUID = -4658944294566402276L;
+
+ private static final FieldSetter<NodeLocation> hashCodeSetter = FieldSetter.forField(NodeLocation.class, "hashCode");
+
+ private final String transport;
+ private final String scheme;
+ private final String name;
+ private transient final int hashCode;
+
+ public NodeLocation(final String transport, final String scheme, final String name) {
+ if (transport == null) {
+ throw new IllegalArgumentException("transport is null");
+ }
+ if (scheme == null) {
+ throw new IllegalArgumentException("scheme is null");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("name is null");
+ }
+ this.transport = transport;
+ this.scheme = scheme;
+ this.name = name;
+ hashCode = hashCode(transport, scheme, name);
+ }
+
+ private static int hashCode(final String transport, final String scheme, final String name) {
+ return (transport.hashCode() * 31 + scheme.hashCode()) * 31 + name.hashCode();
+ }
+
+ public String getScheme() {
+ return scheme;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getTransport() {
+ return transport;
+ }
+
+ public int hashCode() {
+ return hashCode;
+ }
+
+ public boolean isSameNode(final NodeLocation other) {
+ return this == other || other != null && scheme.equals(other.scheme) && name.equals(other.name);
+ }
+
+ public boolean equals(final Object obj) {
+ return obj instanceof NodeLocation && equals((NodeLocation) obj);
+ }
+
+ public boolean equals(final NodeLocation other) {
+ return this == other || other != null && hashCode == other.hashCode && scheme.equals(other.scheme) && name.equals(other.name) && transport.equals(other.transport);
+ }
+
+ private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+ ois.defaultReadObject();
+ if (transport == null) {
+ throw new IllegalArgumentException("transport is null");
+ }
+ if (scheme == null) {
+ throw new InvalidObjectException("scheme is null");
+ }
+ if (name == null) {
+ throw new InvalidObjectException("name is null");
+ }
+ hashCodeSetter.setInt(this, hashCode(transport, scheme, name));
+ }
+
+ public String toString() {
+ return String.format("Node location \"%s:%s\" via \"%s\"", scheme, name, transport);
+ }
+}
Modified: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ObjectInvocationDispatcher.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ObjectInvocationDispatcher.java 2010-03-23 20:10:38 UTC (rev 4189)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ObjectInvocationDispatcher.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -49,9 +49,9 @@
}
/** {@inheritDoc} */
- public Object dispatch(final Invocation invocation) throws InvocationException {
+ public InvocationReply dispatch(final Invocation invocation) throws InvocationException {
try {
- return invocation.getTargetMethod().invoke(target, invocation.getArgs());
+ return new InvocationReply(invocation.getTargetMethod().invoke(target, invocation.getArgs()));
} catch (IllegalAccessException e) {
throw new InvocationException(new IllegalAccessError(e.getMessage()));
} catch (InvocationTargetException e) {
@@ -59,6 +59,11 @@
}
}
+ /** {@inheritDoc} */
+ public <I> void accept(final Visitor<InvocationDispatcher, I> visitor, final I param) {
+ visitor.visit(this, param);
+ }
+
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
final SecurityManager sm = System.getSecurityManager();
Modified: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProcessingInvocationDispatcher.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProcessingInvocationDispatcher.java 2010-03-23 20:10:38 UTC (rev 4189)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProcessingInvocationDispatcher.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -67,10 +67,15 @@
}
/** {@inheritDoc} This implementation passes the invocation through its processor. */
- public Object dispatch(final Invocation invocation) throws InvocationException {
+ public InvocationReply dispatch(final Invocation invocation) throws InvocationException {
return processor.processInvocation(dispatcher, invocation);
}
+ public <I> void accept(final Visitor<InvocationDispatcher, I> visitor, final I param) {
+ visitor.visit(this, param);
+ dispatcher.accept(visitor, param);
+ }
+
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
if (dispatcher == null) {
Modified: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProxyInvocationHandler.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProxyInvocationHandler.java 2010-03-23 20:10:38 UTC (rev 4189)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProxyInvocationHandler.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -59,7 +59,7 @@
*/
public ProxyInvocationHandler(final InvocationProcessor processor, final InvocationDispatcher dispatcher) {
this.dispatcher = dispatcher;
- this.processor = processor;
+ this.processor = processor == null ? InvocationProcessor.DISPATCHING : processor;
}
/**
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/RemoteInvokerContext.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/RemoteInvokerContext.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/RemoteInvokerContext.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,102 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+/**
+ * The invocation context.
+ */
+public final class RemoteInvokerContext {
+
+
+ private final String name;
+
+ private static final ThreadLocal<RemoteInvokerContext> current = new ThreadLocal<RemoteInvokerContext>();
+
+ RemoteInvokerContext(final String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void begin() {
+ final ThreadLocal<RemoteInvokerContext> current = RemoteInvokerContext.current;
+ if (current.get() != null) {
+ throw new IllegalStateException("Another remote invocation context is already in effect");
+ }
+ current.set(this);
+ }
+
+ public void end() {
+ final ThreadLocal<RemoteInvokerContext> current = RemoteInvokerContext.current;
+ if (current.get() == this) {
+ current.set(null);
+ }
+ }
+
+ public static RemoteInvokerContext getCurrent() {
+ return current.get();
+ }
+
+ public static RemoteInvokerContext requireCurrent() throws IllegalStateException {
+ final RemoteInvokerContext context = getCurrent();
+ if (context == null) {
+ throw new IllegalStateException("No active invocation context");
+ }
+ return context;
+ }
+
+ /**
+ * Register a
+ * @param name
+ * @param remoteDispatcher
+ */
+ public void addPeer(String name, InvocationDispatcher remoteDispatcher) {
+
+ }
+
+ /**
+ * Register a local invocation dispatcher, returning a serializable dispatcher which can be sent to remote clients or used
+ * locally.
+ *
+ * @param processor the invocation processor
+ * @param targetDispatcher the target dispatcher
+ * @return a serializable dispatcher
+ */
+ public InvocationDispatcher register(final InvocationProcessor processor, final InvocationDispatcher targetDispatcher) {
+ return null;
+ }
+
+ InvocationDispatcher getLocalDispatcher(final String dispatcherId) {
+ return null;
+ }
+
+ InvocationDispatcher requireLocalDispatcher(final String dispatcherId) {
+ final InvocationDispatcher dispatcher = getLocalDispatcher(dispatcherId);
+ if (dispatcher == null) {
+ throw new IllegalArgumentException("No dispatcher found");
+ }
+ return dispatcher;
+ }
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ServerInvocationContext.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ServerInvocationContext.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ServerInvocationContext.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,152 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * A server invocation context is an invocation environment which supports inbound and outbound invocations.
+ *
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+public class ServerInvocationContext extends ClientInvocationContext {
+ private final String name;
+
+ private static final String NODE_NAME;
+
+ static {
+ // Inside the AS, this will use the AS settings. Outside, it will get the node name in a similar way.
+ String hostName = System.getProperty("jboss.host.name");
+ String qualifiedHostName = System.getProperty("jboss.qualified.host.name");
+ if (qualifiedHostName == null) {
+ // if host name is specified, don't pick a qualified host name that isn't related to it
+ qualifiedHostName = hostName;
+ if (qualifiedHostName == null) {
+ // POSIX-like OSes including Mac should have this set
+ qualifiedHostName = System.getenv("HOSTNAME");
+ }
+ if (qualifiedHostName == null) {
+ // Certain versions of Windows
+ qualifiedHostName = System.getenv("COMPUTERNAME");
+ }
+ if (qualifiedHostName == null) {
+ try {
+ qualifiedHostName = InetAddress.getLocalHost().getHostName();
+ } catch (UnknownHostException e) {
+ qualifiedHostName = null;
+ }
+ }
+ if (qualifiedHostName != null && qualifiedHostName.matches("^\\d+\\.\\d+\\.\\d+\\.\\d+$|:")) {
+ // IP address is not acceptable
+ qualifiedHostName = null;
+ }
+ if (qualifiedHostName == null) {
+ // Give up
+ qualifiedHostName = "unknown-host.unknown-domain";
+ }
+ qualifiedHostName = qualifiedHostName.trim().toLowerCase();
+ }
+ if (hostName == null) {
+ // Use the host part of the qualified host name
+ final int idx = qualifiedHostName.indexOf('.');
+ hostName = idx == -1 ? qualifiedHostName : qualifiedHostName.substring(0, idx);
+ }
+ // Set up the node name
+ String nodeName = System.getProperty("jboss.node.name");
+ if (nodeName == null) {
+ nodeName = hostName;
+ }
+ NODE_NAME = nodeName;
+ }
+
+ ServerInvocationContext(final String name) {
+ this.name = name;
+ }
+
+ public static ServerInvocationContext getCurrent() {
+ final ClientInvocationContext current = ClientInvocationContext.getCurrent();
+ if (current instanceof ServerInvocationContext) {
+ return (ServerInvocationContext) current;
+ } else {
+ return null;
+ }
+ }
+
+ public static ServerInvocationContext requireCurrent() throws NoServerContextException {
+ final ServerInvocationContext context = getCurrent();
+ if (context == null) {
+ throw new NoServerContextException();
+ }
+ return context;
+ }
+
+ public static ServerInvocationContext create(final String name) {
+ return new ServerInvocationContext(name);
+ }
+
+ private final ConcurrentMap<String, Reg> exportedDispatchers = new ConcurrentHashMap<String, Reg>();
+
+ private static final class Reg {
+ private final InvocationDispatcher localDispatcher;
+ private final InvocationProcessor processor;
+
+ private Reg(final InvocationDispatcher localDispatcher, final InvocationProcessor processor) {
+ this.localDispatcher = localDispatcher;
+ this.processor = processor;
+ }
+ }
+
+ private final InvocationForwarder loopback = new InvocationForwarder() {
+ public InvocationReply dispatch(final String identifier, final Invocation invocation) throws IOException, InvocationException {
+ final Reg reg = exportedDispatchers.get(identifier);
+ if (reg != null) {
+ return reg.processor.processInvocation(reg.localDispatcher, invocation);
+ } else {
+ throw new IOException("No dispatcher found named \"" + identifier + "\"");
+ }
+ }
+ };
+
+ public InvocationDispatcher export(InvocationDispatcher dispatcher) {
+ dispatcher.accept(new Visitor<InvocationDispatcher, Void>() {
+ public void visit(final InvocationDispatcher visited, final Void parameter) {
+ if (visited instanceof ExportedInvocationDispatcher) {
+ throw new IllegalArgumentException("Dispatcher is already exported");
+ }
+ }
+ }, null);
+ return new ExportedInvocationDispatcher(null, null, name, null, this);
+ }
+
+ protected InvocationForwarder getForwarder(final String remoteNodeName, final String remoteContextName) {
+ if (name.equals(remoteContextName) && remoteNodeName.equals(NODE_NAME)) {
+ return loopback;
+ } else {
+ return super.getForwarder(remoteNodeName, remoteContextName);
+ }
+ }
+}
Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Visitor.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Visitor.java (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Visitor.java 2010-03-25 15:05:24 UTC (rev 4190)
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.invokable;
+
+/**
+ * A visitor for some type.
+ *
+ * @param <T> the type being visited
+ * @param <P> the parameter type (possibly {@link Void}
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ */
+public interface Visitor<T, P> {
+
+ /**
+ * Visit a node.
+ *
+ * @param visited the visited object
+ * @param parameter the visitor parameter
+ */
+ void visit(T visited, P parameter);
+}
More information about the jboss-svn-commits
mailing list