001 /**
002 * Copyright (C) 2012 FuseSource, Inc.
003 * http://fusesource.com
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.fusesource.hawtdispatch.transport;
019
020 import org.fusesource.hawtdispatch.CustomDispatchSource;
021 import org.fusesource.hawtdispatch.Dispatch;
022 import org.fusesource.hawtdispatch.DispatchQueue;
023 import org.fusesource.hawtdispatch.EventAggregators;
024
025 import java.net.InetSocketAddress;
026 import java.net.URI;
027 import java.util.LinkedList;
028 import java.util.concurrent.atomic.AtomicInteger;
029
030 /**
031 *
032 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
033 */
034 public class PipeTransportServer implements TransportServer {
035
036 protected String connectURI;
037 protected TransportServerListener listener;
038 protected String name;
039 protected boolean marshal;
040 protected final AtomicInteger connectionCounter = new AtomicInteger();
041 DispatchQueue dispatchQueue;
042
043 private CustomDispatchSource<PipeTransport,LinkedList<PipeTransport>> acceptSource;
044
045
046 public String getBoundAddress() {
047 return connectURI;
048 }
049
050 public InetSocketAddress getSocketAddress() {
051 return null;
052 }
053
054 public DispatchQueue getDispatchQueue() {
055 return dispatchQueue;
056 }
057
058 public void setDispatchQueue(DispatchQueue queue) {
059 dispatchQueue = queue;
060 }
061
062 public void suspend() {
063 acceptSource.suspend();
064 }
065
066 public void resume() {
067 acceptSource.resume();
068 }
069
070 public void setTransportServerListener(TransportServerListener listener) {
071 this.listener = listener;
072 }
073
074 public void start() throws Exception {
075 start(null);
076 }
077 public void start(Runnable onCompleted) throws Exception {
078 acceptSource = Dispatch.createSource(EventAggregators.<PipeTransport>linkedList(), dispatchQueue);
079 acceptSource.setEventHandler(new Runnable() {
080 public void run() {
081 LinkedList<PipeTransport> transports = acceptSource.getData();
082 for (PipeTransport transport : transports) {
083 try {
084 listener.onAccept(transport);
085 } catch (Exception e) {
086 listener.onAcceptError(e);
087 }
088 }
089 }
090 });
091 acceptSource.resume();
092 if( onCompleted!=null ) {
093 dispatchQueue.execute(onCompleted);
094 }
095 }
096
097 public void stop() throws Exception {
098 stop(null);
099 }
100 public void stop(Runnable onCompleted) throws Exception {
101 PipeTransportRegistry.unbind(this);
102 acceptSource.setCancelHandler(onCompleted);
103 acceptSource.cancel();
104 }
105
106 public void setConnectURI(String connectURI) {
107 this.connectURI = connectURI;
108 }
109
110 public void setName(String name) {
111 this.name = name;
112 }
113
114 public String getName() {
115 return name;
116 }
117
118 public PipeTransport connect() {
119 int connectionId = connectionCounter.incrementAndGet();
120 String remoteAddress = connectURI.toString() + "#" + connectionId;
121 assert this.listener != null : "Server does not have an accept listener";
122
123 PipeTransport clientTransport = createClientTransport();
124 PipeTransport serverTransport = createServerTransport();
125 clientTransport.peer = serverTransport;
126 serverTransport.peer = clientTransport;
127
128 clientTransport.setRemoteAddress(remoteAddress);
129 serverTransport.setRemoteAddress(remoteAddress);
130
131 serverTransport.setMarshal(marshal);
132 this.acceptSource.merge(serverTransport);
133 return clientTransport;
134 }
135
136 protected PipeTransport createClientTransport() {
137 return new PipeTransport(this);
138 }
139
140 protected PipeTransport createServerTransport() {
141 return new PipeTransport(this);
142 }
143
144 public boolean isMarshal() {
145 return marshal;
146 }
147
148 public void setMarshal(boolean marshal) {
149 this.marshal = marshal;
150 }
151 }