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    }