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.*;
021    
022    import java.net.InetSocketAddress;
023    import java.net.URI;
024    import java.util.LinkedList;
025    import java.util.concurrent.atomic.AtomicInteger;
026    
027    /**
028     *
029     * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
030     */
031    public class PipeTransportServer implements TransportServer {
032    
033        protected String connectURI;
034        protected TransportServerListener listener;
035        protected String name;
036        protected boolean marshal;
037        protected final AtomicInteger connectionCounter = new AtomicInteger();
038        DispatchQueue dispatchQueue;
039    
040        private CustomDispatchSource<PipeTransport,LinkedList<PipeTransport>> acceptSource;
041    
042    
043        public String getBoundAddress() {
044            return connectURI;
045        }
046    
047        public InetSocketAddress getSocketAddress() {
048            return null;
049        }
050    
051        public DispatchQueue getDispatchQueue() {
052            return dispatchQueue;
053        }
054    
055        public void setDispatchQueue(DispatchQueue queue) {
056            dispatchQueue = queue;
057        }
058    
059        public void suspend() {
060            acceptSource.suspend();
061        }
062    
063        public void resume() {
064            acceptSource.resume();
065        }
066    
067        public void setTransportServerListener(TransportServerListener listener) {
068            this.listener = listener;
069        }
070    
071        @Deprecated
072        public void start(Runnable onCompleted) throws Exception {
073            start(new TaskWrapper(onCompleted));
074        }
075        @Deprecated
076        public void stop(Runnable onCompleted) throws Exception {
077            stop(new TaskWrapper(onCompleted));
078        }
079    
080        public void start(Task onCompleted) throws Exception {
081            acceptSource = Dispatch.createSource(EventAggregators.<PipeTransport>linkedList(), dispatchQueue);
082            acceptSource.setEventHandler(new Task() {
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(Task 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    }