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 java.util.List;
023
024 import org.apache.james.jspf.core.DNSRequest;
025 import org.apache.james.jspf.core.exceptions.TimeoutException;
026 import org.apache.james.jspf.executor.DNSAsynchLookupService;
027 import org.apache.james.jspf.executor.IResponse;
028 import org.apache.james.jspf.executor.IResponseQueue;
029 import org.xbill.DNS.DClass;
030 import org.xbill.DNS.Message;
031 import org.xbill.DNS.Name;
032 import org.xbill.DNS.Record;
033 import org.xbill.DNS.Resolver;
034 import org.xbill.DNS.TextParseException;
035 import org.xbill.DNS.Type;
036
037 import uk.nominet.dnsjnio.ExtendedNonblockingResolver;
038 import uk.nominet.dnsjnio.LookupAsynch;
039
040 public class DNSJnioAsynchService implements DNSAsynchLookupService {
041
042 private ExtendedNonblockingResolver resolver;
043
044 public DNSJnioAsynchService(ExtendedNonblockingResolver resolver) {
045 this.resolver = resolver;
046 LookupAsynch.setDefaultResolver(resolver);
047 }
048
049 /**
050 * Set the timeout for the resolvers
051 * @param timeout
052 */
053 public synchronized void setTimeout(int timeout) {
054 Resolver[] res = resolver.getResolvers();
055 for (int i = 0; i < res.length; i++) {
056 res[i].setTimeout(timeout);
057 }
058 }
059
060 /**
061 * @see org.apache.james.jspf.executor.DNSAsynchLookupService#getRecordsAsynch(org.apache.james.jspf.core.DNSRequest, int, org.apache.james.jspf.executor.IResponseQueue)
062 */
063 public void getRecordsAsynch(DNSRequest request, int id,
064 IResponseQueue responsePool) {
065
066 Message message;
067 try {
068 message = makeQuery(request, id);
069 LookupAsynch la = new LookupAsynch(message.getQuestion().getName(), message.getQuestion().getType());
070 la.runAsynch(new Runnable() {
071
072 private IResponseQueue responsePool;
073 private Integer id;
074 private LookupAsynch lookup;
075
076 public void run() {
077 responsePool.insertResponse(new IResponse() {
078
079 public Exception getException() {
080 if (lookup.getResult() == LookupAsynch.TRY_AGAIN) {
081 return new TimeoutException(lookup.getErrorString());
082 } else {
083 return null;
084 }
085 }
086
087 public Object getId() {
088 return id;
089 }
090
091 public List<String> getValue() {
092 return (DNSServiceXBillImpl.convertRecordsToList(lookup.getAnswers()));
093 }
094
095 });
096 }
097
098 public Runnable setResponsePool(LookupAsynch la, IResponseQueue responsePool,
099 Integer integer) {
100 this.lookup = la;
101 this.responsePool = responsePool;
102 this.id = integer;
103 return this;
104 }
105
106 }.setResponsePool(la, responsePool, new Integer(id)));
107 // this.resolver.sendAsync(message, new Integer(id), new ResponseQueueAdaptor(responsePool));
108 } catch (TextParseException e) {
109 // TODO Auto-generated catch block
110 e.printStackTrace();
111 }
112 }
113
114 private Message makeQuery(DNSRequest request, int id) throws TextParseException {
115 Name name = Name.fromString(request.getHostname(), Name.root);
116
117 int type;
118 switch (request.getRecordType()) {
119 case DNSRequest.A: type = Type.A; break;
120 case DNSRequest.AAAA: type = Type.AAAA; break;
121 case DNSRequest.MX: type = Type.MX; break;
122 case DNSRequest.PTR: type = Type.PTR; break;
123 case DNSRequest.SPF: type = Type.SPF; break;
124 case DNSRequest.TXT: type = Type.TXT; break;
125 default:
126 throw new UnsupportedOperationException("Unknown query type: "+request.getRecordType());
127 }
128
129 Record question = Record.newRecord(name, type, DClass.ANY);
130 Message query = Message.newQuery(question);
131 query.getHeader().setID(id);
132 return query;
133 }
134 }