001    /****************************************************************
002     * Licensed to the Apache Software Foundation (ASF) under one   *
003     * or more contributor license agreements.  See the NOTICE file *
004     * distributed with this work for additional information        *
005     * regarding copyright ownership.  The ASF licenses this file   *
006     * to you under the Apache License, Version 2.0 (the            *
007     * "License"); you may not use this file except in compliance   *
008     * with the License.  You may obtain a copy of the License at   *
009     *                                                              *
010     *   http://www.apache.org/licenses/LICENSE-2.0                 *
011     *                                                              *
012     * Unless required by applicable law or agreed to in writing,   *
013     * software distributed under the License is distributed on an  *
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015     * KIND, either express or implied.  See the License for the    *
016     * specific language governing permissions and limitations      *
017     * under the License.                                           *
018     ****************************************************************/
019    
020    package org.apache.james.jspf.impl;
021    
022    import org.apache.james.jspf.core.DNSRequest;
023    import org.apache.james.jspf.core.DNSService;
024    import org.apache.james.jspf.core.exceptions.TimeoutException;
025    import org.apache.james.jspf.executor.DNSAsynchLookupService;
026    import org.apache.james.jspf.executor.IResponseImpl;
027    import org.apache.james.jspf.executor.IResponseQueue;
028    
029    import java.util.LinkedList;
030    
031    /**
032     * Wrap a DNSService an execute the calls asynch in a new Thread
033     */
034    public class DNSServiceAsynchSimulator implements Runnable, DNSAsynchLookupService {
035    
036        private DNSService dnsService;
037        private Thread worker;
038        private LinkedList<Request> queue;
039        private int waitingThreads = 0;
040        private boolean multiThread;
041        
042        private static final class Request {
043            private final DNSRequest value;
044            private final Object id;
045            private final IResponseQueue responseQueue;
046            public Request(DNSRequest value, Object id, IResponseQueue responseQueue) {
047                this.value = value;
048                this.id = id;
049                this.responseQueue = responseQueue;
050            }
051            public DNSRequest getValue() {
052                return value;
053            }
054            public Object getId() {
055                return id;
056            }
057            public IResponseQueue getResponseQueue() {
058                return responseQueue;
059            }
060            
061        }
062    
063        public DNSServiceAsynchSimulator(DNSService service, boolean multiThread) {
064            this.dnsService = service;
065            this.multiThread = multiThread;
066    
067            this.queue = new LinkedList<Request>();
068            this.worker = new Thread(this);
069            this.worker.setDaemon(true);
070            this.worker.setName("DNSServiceAsynchSimulator");
071            this.worker.start();
072    
073        }
074    
075        /**
076         * @see org.apache.james.jspf.executor.DNSAsynchLookupService#getRecordsAsynch(org.apache.james.jspf.core.DNSRequest, int, org.apache.james.jspf.executor.IResponseQueue)
077         */
078        public void getRecordsAsynch(DNSRequest request, int id,
079                final IResponseQueue responsePool) {
080            
081            synchronized (queue) {
082                queue.addLast(new Request(request, new Integer(id), responsePool));
083                queue.notify();
084            }
085            
086        }
087    
088        /**
089         * Run the async dns call in a new thread
090         */
091        public void run() {
092            while (true) {
093                Request req;
094                synchronized (queue) {
095                    if ( (queue.size() - waitingThreads <= 0) ) {
096                        try {
097                            waitingThreads++; queue.wait();
098                        } catch (InterruptedException e) {
099                            Thread.interrupted();
100                        }
101                        waitingThreads--;
102                    }
103                    req = (Request) queue.removeFirst();
104                }
105                
106                Runnable runnable = new Runnable() {
107    
108                    private Request req;
109    
110                    public void run() {
111                        IResponseImpl response;
112                        try {
113                            response = new IResponseImpl(req.getId(), dnsService.getRecords(req.getValue()));
114                        } catch (TimeoutException e) {
115                            response = new IResponseImpl(req.getId(), e);
116                        }
117    
118                        req.getResponseQueue().insertResponse(response);
119                    }
120    
121                    public Runnable setRequest(Request req) {
122                        this.req = req;
123                        return this;
124                    }
125                    
126                }.setRequest(req);
127                
128                if (multiThread) {
129                    new Thread(runnable).start();
130                } else {
131                    runnable.run();
132                }
133            }
134        }
135    
136    }