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 setTransportServerListener(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 try {
087 listener.onAccept(transport);
088 } catch (Exception e) {
089 listener.onAcceptError(e);
090 }
091 }
092 }
093 });
094 acceptSource.resume();
095 if( onCompleted!=null ) {
096 dispatchQueue.execute(onCompleted);
097 }
098 }
099
100 public void stop() throws Exception {
101 stop(null);
102 }
103 public void stop(Runnable onCompleted) throws Exception {
104 PipeTransportRegistry.unbind(this);
105 acceptSource.setCancelHandler(onCompleted);
106 acceptSource.cancel();
107 }
108
109 public void setConnectURI(String connectURI) {
110 this.connectURI = connectURI;
111 }
112
113 public void setName(String name) {
114 this.name = name;
115 }
116
117 public String getName() {
118 return name;
119 }
120
121 public PipeTransport connect() {
122 int connectionId = connectionCounter.incrementAndGet();
123 String remoteAddress = connectURI.toString() + "#" + connectionId;
124 assert this.listener != null : "Server does not have an accept listener";
125
126 PipeTransport clientTransport = createClientTransport();
127 PipeTransport serverTransport = createServerTransport();
128 clientTransport.peer = serverTransport;
129 serverTransport.peer = clientTransport;
130
131 clientTransport.setRemoteAddress(remoteAddress);
132 serverTransport.setRemoteAddress(remoteAddress);
133
134 serverTransport.setMarshal(marshal);
135 this.acceptSource.merge(serverTransport);
136 return clientTransport;
137 }
138
139 protected PipeTransport createClientTransport() {
140 return new PipeTransport(this);
141 }
142
143 protected PipeTransport createServerTransport() {
144 return new PipeTransport(this);
145 }
146
147 public boolean isMarshal() {
148 return marshal;
149 }
150
151 public void setMarshal(boolean marshal) {
152 this.marshal = marshal;
153 }
154 }