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    }