001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. 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 package org.fusesource.hawtdispatch.transport;
018
019 import org.fusesource.hawtdispatch.CustomDispatchSource;
020 import org.fusesource.hawtdispatch.Dispatch;
021 import org.fusesource.hawtdispatch.DispatchQueue;
022 import org.fusesource.hawtdispatch.EventAggregators;
023
024 import java.net.InetSocketAddress;
025 import java.net.URI;
026 import java.util.LinkedList;
027 import java.util.concurrent.atomic.AtomicInteger;
028
029 /**
030 *
031 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
032 */
033 public class PipeTransportServer implements TransportServer {
034
035 protected String connectURI;
036 protected TransportServerListener listener;
037 protected String name;
038 protected boolean marshal;
039 protected final AtomicInteger connectionCounter = new AtomicInteger();
040 DispatchQueue dispatchQueue;
041
042 private CustomDispatchSource<PipeTransport,LinkedList<PipeTransport>> acceptSource;
043
044
045 public String getBoundAddress() {
046 return connectURI;
047 }
048
049 public String getConnectAddress() {
050 return connectURI;
051 }
052
053 public InetSocketAddress getSocketAddress() {
054 return null;
055 }
056
057 public DispatchQueue getDispatchQueue() {
058 return dispatchQueue;
059 }
060
061 public void setDispatchQueue(DispatchQueue queue) {
062 dispatchQueue = queue;
063 }
064
065 public void suspend() {
066 acceptSource.suspend();
067 }
068
069 public void resume() {
070 acceptSource.resume();
071 }
072
073 public void setAcceptListener(TransportServerListener listener) {
074 this.listener = listener;
075 }
076
077 public void start() throws Exception {
078 start(null);
079 }
080 public void start(Runnable onCompleted) throws Exception {
081 acceptSource = Dispatch.createSource(EventAggregators.<PipeTransport>linkedList(), dispatchQueue);
082 acceptSource.setEventHandler(new Runnable() {
083 public void run() {
084 LinkedList<PipeTransport> transports = acceptSource.getData();
085 for (PipeTransport transport : transports) {
086 listener.onAccept(transport);
087 }
088 }
089 });
090 acceptSource.resume();
091 if( onCompleted!=null ) {
092 dispatchQueue.execute(onCompleted);
093 }
094 }
095
096 public void stop() throws Exception {
097 stop(null);
098 }
099 public void stop(Runnable onCompleted) throws Exception {
100 PipeTransportRegistry.unbind(this);
101 acceptSource.setCancelHandler(onCompleted);
102 acceptSource.cancel();
103 }
104
105 public void setConnectURI(String connectURI) {
106 this.connectURI = connectURI;
107 }
108
109 public void setName(String name) {
110 this.name = name;
111 }
112
113 public String getName() {
114 return name;
115 }
116
117 public PipeTransport connect() {
118 int connectionId = connectionCounter.incrementAndGet();
119 String remoteAddress = connectURI.toString() + "#" + connectionId;
120 assert this.listener != null : "Server does not have an accept listener";
121
122 PipeTransport clientTransport = createClientTransport();
123 PipeTransport serverTransport = createServerTransport();
124 clientTransport.peer = serverTransport;
125 serverTransport.peer = clientTransport;
126
127 clientTransport.setRemoteAddress(remoteAddress);
128 serverTransport.setRemoteAddress(remoteAddress);
129
130 serverTransport.setMarshal(marshal);
131 this.acceptSource.merge(serverTransport);
132 return clientTransport;
133 }
134
135 protected PipeTransport createClientTransport() {
136 return new PipeTransport(this);
137 }
138
139 protected PipeTransport createServerTransport() {
140 return new PipeTransport(this);
141 }
142
143 public boolean isMarshal() {
144 return marshal;
145 }
146
147 public void setMarshal(boolean marshal) {
148 this.marshal = marshal;
149 }
150 }