1 /**************************************************************** 2 * Licensed to the Apache Software Foundation (ASF) under one * 3 * or more contributor license agreements. See the NOTICE file * 4 * distributed with this work for additional information * 5 * regarding copyright ownership. The ASF licenses this file * 6 * to you under the Apache License, Version 2.0 (the * 7 * "License"); you may not use this file except in compliance * 8 * with the License. You may obtain a copy of the License at * 9 * * 10 * http://www.apache.org/licenses/LICENSE-2.0 * 11 * * 12 * Unless required by applicable law or agreed to in writing, * 13 * software distributed under the License is distributed on an * 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 15 * KIND, either express or implied. See the License for the * 16 * specific language governing permissions and limitations * 17 * under the License. * 18 ****************************************************************/ 19 20 package org.apache.james.mime4j.field.address; 21 22 import java.util.ArrayList; 23 import java.util.Iterator; 24 25 import org.apache.james.mime4j.decoder.DecoderUtil; 26 import org.apache.james.mime4j.field.address.parser.ASTaddr_spec; 27 import org.apache.james.mime4j.field.address.parser.ASTaddress; 28 import org.apache.james.mime4j.field.address.parser.ASTaddress_list; 29 import org.apache.james.mime4j.field.address.parser.ASTangle_addr; 30 import org.apache.james.mime4j.field.address.parser.ASTdomain; 31 import org.apache.james.mime4j.field.address.parser.ASTgroup_body; 32 import org.apache.james.mime4j.field.address.parser.ASTlocal_part; 33 import org.apache.james.mime4j.field.address.parser.ASTmailbox; 34 import org.apache.james.mime4j.field.address.parser.ASTname_addr; 35 import org.apache.james.mime4j.field.address.parser.ASTphrase; 36 import org.apache.james.mime4j.field.address.parser.ASTroute; 37 import org.apache.james.mime4j.field.address.parser.Node; 38 import org.apache.james.mime4j.field.address.parser.SimpleNode; 39 import org.apache.james.mime4j.field.address.parser.Token; 40 41 /** 42 * Transforms the JJTree-generated abstract syntax tree 43 * into a graph of org.apache.james.mime4j.field.address objects. 44 * 45 * 46 */ 47 class Builder { 48 49 private static Builder singleton = new Builder(); 50 getInstance()51 public static Builder getInstance() { 52 return singleton; 53 } 54 55 56 buildAddressList(ASTaddress_list node)57 public AddressList buildAddressList(ASTaddress_list node) { 58 ArrayList<Address> list = new ArrayList<Address>(); 59 for (int i = 0; i < node.jjtGetNumChildren(); i++) { 60 ASTaddress childNode = (ASTaddress) node.jjtGetChild(i); 61 Address address = buildAddress(childNode); 62 list.add(address); 63 } 64 return new AddressList(list, true); 65 } 66 buildAddress(ASTaddress node)67 private Address buildAddress(ASTaddress node) { 68 ChildNodeIterator it = new ChildNodeIterator(node); 69 Node n = it.nextNode(); 70 if (n instanceof ASTaddr_spec) { 71 return buildAddrSpec((ASTaddr_spec)n); 72 } 73 else if (n instanceof ASTangle_addr) { 74 return buildAngleAddr((ASTangle_addr)n); 75 } 76 else if (n instanceof ASTphrase) { 77 String name = buildString((ASTphrase)n, false); 78 Node n2 = it.nextNode(); 79 if (n2 instanceof ASTgroup_body) { 80 return new Group(name, buildGroupBody((ASTgroup_body)n2)); 81 } 82 else if (n2 instanceof ASTangle_addr) { 83 name = DecoderUtil.decodeEncodedWords(name); 84 return new NamedMailbox(name, buildAngleAddr((ASTangle_addr)n2)); 85 } 86 else { 87 throw new IllegalStateException(); 88 } 89 } 90 else { 91 throw new IllegalStateException(); 92 } 93 } 94 95 96 buildGroupBody(ASTgroup_body node)97 private MailboxList buildGroupBody(ASTgroup_body node) { 98 ArrayList<Address> results = new ArrayList<Address>(); 99 ChildNodeIterator it = new ChildNodeIterator(node); 100 while (it.hasNext()) { 101 Node n = it.nextNode(); 102 if (n instanceof ASTmailbox) 103 results.add(buildMailbox((ASTmailbox)n)); 104 else 105 throw new IllegalStateException(); 106 } 107 return new MailboxList(results, true); 108 } 109 buildMailbox(ASTmailbox node)110 private Mailbox buildMailbox(ASTmailbox node) { 111 ChildNodeIterator it = new ChildNodeIterator(node); 112 Node n = it.nextNode(); 113 if (n instanceof ASTaddr_spec) { 114 return buildAddrSpec((ASTaddr_spec)n); 115 } 116 else if (n instanceof ASTangle_addr) { 117 return buildAngleAddr((ASTangle_addr)n); 118 } 119 else if (n instanceof ASTname_addr) { 120 return buildNameAddr((ASTname_addr)n); 121 } 122 else { 123 throw new IllegalStateException(); 124 } 125 } 126 buildNameAddr(ASTname_addr node)127 private NamedMailbox buildNameAddr(ASTname_addr node) { 128 ChildNodeIterator it = new ChildNodeIterator(node); 129 Node n = it.nextNode(); 130 String name; 131 if (n instanceof ASTphrase) { 132 name = buildString((ASTphrase)n, false); 133 } 134 else { 135 throw new IllegalStateException(); 136 } 137 138 n = it.nextNode(); 139 if (n instanceof ASTangle_addr) { 140 name = DecoderUtil.decodeEncodedWords(name); 141 return new NamedMailbox(name, buildAngleAddr((ASTangle_addr) n)); 142 } 143 else { 144 throw new IllegalStateException(); 145 } 146 } 147 buildAngleAddr(ASTangle_addr node)148 private Mailbox buildAngleAddr(ASTangle_addr node) { 149 ChildNodeIterator it = new ChildNodeIterator(node); 150 DomainList route = null; 151 Node n = it.nextNode(); 152 if (n instanceof ASTroute) { 153 route = buildRoute((ASTroute)n); 154 n = it.nextNode(); 155 } 156 else if (n instanceof ASTaddr_spec) 157 ; // do nothing 158 else 159 throw new IllegalStateException(); 160 161 if (n instanceof ASTaddr_spec) 162 return buildAddrSpec(route, (ASTaddr_spec)n); 163 else 164 throw new IllegalStateException(); 165 } 166 buildRoute(ASTroute node)167 private DomainList buildRoute(ASTroute node) { 168 ArrayList<String> results = new ArrayList<String>(node.jjtGetNumChildren()); 169 ChildNodeIterator it = new ChildNodeIterator(node); 170 while (it.hasNext()) { 171 Node n = it.nextNode(); 172 if (n instanceof ASTdomain) 173 results.add(buildString((ASTdomain)n, true)); 174 else 175 throw new IllegalStateException(); 176 } 177 return new DomainList(results, true); 178 } 179 buildAddrSpec(ASTaddr_spec node)180 private Mailbox buildAddrSpec(ASTaddr_spec node) { 181 return buildAddrSpec(null, node); 182 } buildAddrSpec(DomainList route, ASTaddr_spec node)183 private Mailbox buildAddrSpec(DomainList route, ASTaddr_spec node) { 184 ChildNodeIterator it = new ChildNodeIterator(node); 185 String localPart = buildString((ASTlocal_part)it.nextNode(), true); 186 String domain = buildString((ASTdomain)it.nextNode(), true); 187 return new Mailbox(route, localPart, domain); 188 } 189 190 buildString(SimpleNode node, boolean stripSpaces)191 private String buildString(SimpleNode node, boolean stripSpaces) { 192 Token head = node.firstToken; 193 Token tail = node.lastToken; 194 StringBuffer out = new StringBuffer(); 195 196 while (head != tail) { 197 out.append(head.image); 198 head = head.next; 199 if (!stripSpaces) 200 addSpecials(out, head.specialToken); 201 } 202 out.append(tail.image); 203 204 return out.toString(); 205 } 206 addSpecials(StringBuffer out, Token specialToken)207 private void addSpecials(StringBuffer out, Token specialToken) { 208 if (specialToken != null) { 209 addSpecials(out, specialToken.specialToken); 210 out.append(specialToken.image); 211 } 212 } 213 214 private static class ChildNodeIterator implements Iterator<Node> { 215 216 private SimpleNode simpleNode; 217 private int index; 218 private int len; 219 ChildNodeIterator(SimpleNode simpleNode)220 public ChildNodeIterator(SimpleNode simpleNode) { 221 this.simpleNode = simpleNode; 222 this.len = simpleNode.jjtGetNumChildren(); 223 this.index = 0; 224 } 225 remove()226 public void remove() { 227 throw new UnsupportedOperationException(); 228 } 229 hasNext()230 public boolean hasNext() { 231 return index < len; 232 } 233 next()234 public Node next() { 235 return nextNode(); 236 } 237 nextNode()238 public Node nextNode() { 239 return simpleNode.jjtGetChild(index++); 240 } 241 242 } 243 } 244