Author: david.lloyd(a)jboss.com
Date: 2008-11-13 23:08:51 -0500 (Thu, 13 Nov 2008)
New Revision: 4678
Added:
remoting3/trunk/api/src/main/java/org/jboss/remoting/ServiceRegistrationException.java
remoting3/trunk/api/src/main/java/org/jboss/remoting/spi/NamedServiceRegistry.java
remoting3/trunk/util/src/main/java/org/jboss/remoting/util/QualifiedName.java
Log:
Named service registry
Added:
remoting3/trunk/api/src/main/java/org/jboss/remoting/ServiceRegistrationException.java
===================================================================
---
remoting3/trunk/api/src/main/java/org/jboss/remoting/ServiceRegistrationException.java
(rev 0)
+++
remoting3/trunk/api/src/main/java/org/jboss/remoting/ServiceRegistrationException.java 2008-11-14
04:08:51 UTC (rev 4678)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, 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.remoting;
+
+import org.jboss.remoting.RemotingException;
+
+/**
+ *
+ */
+public class ServiceRegistrationException extends RemotingException {
+
+ private static final long serialVersionUID = 6416792968397444648L;
+
+ /**
+ * Constructs a <tt>ServiceRegistrationException</tt> with no detail
message. The cause is not initialized, and may
+ * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}.
+ */
+ public ServiceRegistrationException() {
+ }
+
+ /**
+ * Constructs a <tt>ServiceRegistrationException</tt> 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 ServiceRegistrationException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a <tt>ServiceRegistrationException</tt> 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
<tt>cause</tt>).
+ *
+ * @param cause the cause (which is saved for later retrieval by the {@link
#getCause()} method)
+ */
+ public ServiceRegistrationException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a <tt>ServiceRegistrationException</tt> 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 ServiceRegistrationException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+}
Added: remoting3/trunk/api/src/main/java/org/jboss/remoting/spi/NamedServiceRegistry.java
===================================================================
--- remoting3/trunk/api/src/main/java/org/jboss/remoting/spi/NamedServiceRegistry.java
(rev 0)
+++
remoting3/trunk/api/src/main/java/org/jboss/remoting/spi/NamedServiceRegistry.java 2008-11-14
04:08:51 UTC (rev 4678)
@@ -0,0 +1,81 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, 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.remoting.spi;
+
+import java.util.concurrent.ConcurrentMap;
+import java.io.IOException;
+import org.jboss.remoting.util.QualifiedName;
+import org.jboss.remoting.util.CollectionUtil;
+import org.jboss.remoting.ServiceRegistrationException;
+import org.jboss.remoting.CloseHandler;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.log.Logger;
+
+/**
+ *
+ */
+public final class NamedServiceRegistry {
+ public static final Logger log =
Logger.getLogger("org.jboss.remoting.named-registry");
+
+ private final ConcurrentMap<QualifiedName, Handle<RequestHandlerSource>>
map = CollectionUtil.concurrentMap();
+
+ public NamedServiceRegistry() {
+ }
+
+ public Handle<RequestHandlerSource> registerService(final QualifiedName path,
final RequestHandlerSource service) throws IOException {
+ if (path == null) {
+ throw new NullPointerException("path is null");
+ }
+ if (service == null) {
+ throw new NullPointerException("service is null");
+ }
+ final Handle<RequestHandlerSource> handle = service.getHandle();
+ boolean ok = false;
+ try {
+ final Handle<RequestHandlerSource> oldHandle = map.putIfAbsent(path,
handle);
+ if (oldHandle != null) {
+ throw new ServiceRegistrationException(String.format("Failed to
register a service at path \"%s\" on %s (a service is already registered at that
location)", path, this));
+ }
+ handle.addCloseHandler(new
CloseHandler<Handle<RequestHandlerSource>>() {
+ public void handleClose(final Handle<RequestHandlerSource> closed)
{
+ if (map.remove(path, service)) {
+ log.trace("Removed service %s at path \"%s\" on %s
(service handle was closed)", service, path, this);
+ }
+ }
+ });
+ log.trace("Registered %s at path \"%s\" on %s", service,
path, this);
+ ok = true;
+ return handle;
+ } finally {
+ if (! ok) IoUtils.safeClose(handle);
+ }
+ }
+
+ public Handle<RequestHandlerSource> lookupService(QualifiedName path) {
+ return map.get(path);
+ }
+
+ public String toString() {
+ return "named service registry <" + Integer.toHexString(hashCode())
+ ">";
+ }
+}
Added: remoting3/trunk/util/src/main/java/org/jboss/remoting/util/QualifiedName.java
===================================================================
--- remoting3/trunk/util/src/main/java/org/jboss/remoting/util/QualifiedName.java
(rev 0)
+++
remoting3/trunk/util/src/main/java/org/jboss/remoting/util/QualifiedName.java 2008-11-14
04:08:51 UTC (rev 4678)
@@ -0,0 +1,142 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, 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.remoting.util;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.io.UnsupportedEncodingException;
+
+/**
+ *
+ */
+public final class QualifiedName implements Comparable<QualifiedName>,
Iterable<String> {
+ private final String[] segments;
+
+ public QualifiedName(final String[] segments) {
+ if (segments == null) {
+ throw new NullPointerException("segments is null");
+ }
+ for (String s : segments) {
+ if (s == null) {
+ throw new NullPointerException("a segment is null");
+ }
+ }
+ this.segments = segments;
+ }
+
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (! (o instanceof QualifiedName)) return false;
+ final QualifiedName name = (QualifiedName) o;
+ if (!Arrays.equals(segments, name.segments)) return false;
+ return true;
+ }
+
+ public int hashCode() {
+ return Arrays.hashCode(segments);
+ }
+
+ public int compareTo(final QualifiedName o) {
+ if (this == o) return 0;
+ String[] a = segments;
+ String[] b = o.segments;
+ final int alen = a.length;
+ final int blen = b.length;
+ for (int i = 0; i < alen && i < blen; i ++) {
+ final int cmp = a[i].compareTo(b[i]);
+ if (cmp != 0) {
+ return cmp;
+ }
+ }
+ if (alen < blen) {
+ return -1;
+ } else if (alen > blen) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ if (segments.length == 0) {
+ return "/";
+ } else for (String segment : segments) {
+ try {
+ builder.append('/');
+ builder.append(URLEncoder.encode(segment, "utf-8"));
+ } catch (UnsupportedEncodingException e) {
+ // cannot happen
+ throw new IllegalStateException(e);
+ }
+ }
+ return builder.toString();
+ }
+
+ public static QualifiedName parse(String path) {
+ List<String> decoded = new ArrayList<String>();
+ for (String segment : CollectionUtil.split("/", path)) {
+ if (segment.length() == 0) {
+ throw new IllegalArgumentException("Empty segment in path");
+ }
+ try {
+ decoded.add(URLDecoder.decode(segment, "utf-8"));
+ } catch (UnsupportedEncodingException e) {
+ // cannot happen
+ throw new IllegalStateException(e);
+ }
+ }
+ return new QualifiedName(decoded.toArray(new String[decoded.size()]));
+ }
+
+ public Iterator<String> iterator() {
+ return new Iterator<String>() {
+ int i;
+
+ public boolean hasNext() {
+ return i < segments.length;
+ }
+
+ public String next() {
+ try {
+ return segments[i++];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new NoSuchElementException("next() past end");
+ }
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException("remove()");
+ }
+ };
+ }
+
+ public int length() {
+ return segments.length;
+ }
+}