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    package javax.xml.soap;
020    
021    import java.util.Iterator;
022    import java.util.Vector;
023    
024    /**
025     * A container for <CODE>MimeHeader</CODE> objects, which represent the MIME headers present in a
026     * MIME part of a message.</P>
027     * <p/>
028     * <P>This class is used primarily when an application wants to retrieve specific attachments based
029     * on certain MIME headers and values. This class will most likely be used by implementations of
030     * <CODE>AttachmentPart</CODE> and other MIME dependent parts of the JAXM API.
031     *
032     * @see SOAPMessage#getAttachments() SOAPMessage.getAttachments()
033     * @see AttachmentPart AttachmentPart
034     */
035    public class MimeHeaders {
036    
037        class MatchingIterator implements Iterator {
038    
039            private Object nextMatch() {
040    
041                label0:
042                while (iterator.hasNext()) {
043                    MimeHeader mimeheader = (MimeHeader)iterator.next();
044    
045                    if (names == null) {
046                        return match
047                                ? null
048                                : mimeheader;
049                    }
050    
051                    for (int i = 0; i < names.length; i++) {
052                        if (!mimeheader.getName().equalsIgnoreCase(names[i])) {
053                            continue;
054                        }
055    
056                        if (match) {
057                            return mimeheader;
058                        }
059    
060                        continue label0;
061                    }
062    
063                    if (!match) {
064                        return mimeheader;
065                    }
066                }
067    
068                return null;
069            }
070    
071            public boolean hasNext() {
072    
073                if (nextHeader == null) {
074                    nextHeader = nextMatch();
075                }
076    
077                return nextHeader != null;
078            }
079    
080            public Object next() {
081    
082                if (nextHeader != null) {
083                    Object obj = nextHeader;
084    
085                    nextHeader = null;
086    
087                    return obj;
088                }
089    
090                if (hasNext()) {
091                    return nextHeader;
092                } else {
093                    return null;
094                }
095            }
096    
097            public void remove() {
098                iterator.remove();
099            }
100    
101            private boolean match;
102    
103            private Iterator iterator;
104    
105            private String names[];
106    
107            private Object nextHeader;
108    
109            MatchingIterator(String as[], boolean flag) {
110    
111                match = flag;
112                names = as;
113                iterator = headers.iterator();
114            }
115        }
116    
117        /**
118         * Constructs a default <CODE>MimeHeaders</CODE> object initialized with an empty
119         * <CODE>Vector</CODE> object.
120         */
121        public MimeHeaders() {
122            headers = new Vector();
123        }
124    
125        /**
126         * Returns all of the values for the specified header as an array of <CODE>String</CODE>
127         * objects.
128         *
129         * @param name the name of the header for which values will be returned
130         * @return a <CODE>String</CODE> array with all of the values for the specified header
131         * @see #setHeader(String, String) setHeader(java.lang.String,
132         *      java.lang.String)
133         */
134        public String[] getHeader(String name) {
135    
136            Vector vector = new Vector();
137    
138            for (int i = 0; i < headers.size(); i++) {
139                MimeHeader mimeheader = (MimeHeader)headers.elementAt(i);
140    
141                if (mimeheader.getName().equalsIgnoreCase(name)
142                        && (mimeheader.getValue() != null)) {
143                    vector.addElement(mimeheader.getValue());
144                }
145            }
146    
147            if (vector.size() == 0) {
148                return null;
149            } else {
150                String as[] = new String[vector.size()];
151    
152                vector.copyInto(as);
153    
154                return as;
155            }
156        }
157    
158        /**
159         * Replaces the current value of the first header entry whose name matches the given name with
160         * the given value, adding a new header if no existing header name matches. This method also
161         * removes all matching headers after the first one.
162         * <p/>
163         * <P>Note that RFC822 headers can contain only US-ASCII characters.</P>
164         *
165         * @param name  a <CODE>String</CODE> with the name of the header for which to search
166         * @param value a <CODE>String</CODE> with the value that will replace the current value of the
167         *              specified header
168         * @throws IllegalArgumentException
169         *          if there was a problem in the mime header name or the value being set
170         * @see #getHeader(String) getHeader(java.lang.String)
171         */
172        public void setHeader(String name, String value) {
173    
174            boolean flag = false;
175    
176            if ((name == null) || "".equals(name)) {
177                throw new IllegalArgumentException("Illegal MimeHeader name");
178            }
179    
180            for (int i = 0; i < headers.size(); i++) {
181                MimeHeader mimeheader = (MimeHeader)headers.elementAt(i);
182    
183                if (mimeheader.getName().equalsIgnoreCase(name)) {
184                    if (!flag) {
185                        headers.setElementAt(new MimeHeader(mimeheader
186                                .getName(), value), i);
187    
188                        flag = true;
189                    } else {
190                        headers.removeElementAt(i--);
191                    }
192                }
193            }
194    
195            if (!flag) {
196                addHeader(name, value);
197            }
198        }
199    
200        /**
201         * Adds a <CODE>MimeHeader</CODE> object with the specified name and value to this
202         * <CODE>MimeHeaders</CODE> object's list of headers.
203         * <p/>
204         * <P>Note that RFC822 headers can contain only US-ASCII characters.</P>
205         *
206         * @param name  a <CODE>String</CODE> with the name of the header to be added
207         * @param value a <CODE>String</CODE> with the value of the header to be added
208         * @throws IllegalArgumentException
209         *          if there was a problem in the mime header name or value being added
210         */
211        public void addHeader(String name, String value) {
212    
213            if ((name == null) || "".equals(name)) {
214                throw new IllegalArgumentException("Illegal MimeHeader name");
215            }
216    
217            int i = headers.size();
218    
219            for (int j = i - 1; j >= 0; j--) {
220                MimeHeader mimeheader = (MimeHeader)headers.elementAt(j);
221    
222                if (mimeheader.getName().equalsIgnoreCase(name)) {
223                    headers.insertElementAt(new MimeHeader(name, value), j + 1);
224    
225                    return;
226                }
227            }
228    
229            headers.addElement(new MimeHeader(name, value));
230        }
231    
232        /**
233         * Remove all <CODE>MimeHeader</CODE> objects whose name matches the the given name.
234         *
235         * @param name a <CODE>String</CODE> with the name of the header for which to search
236         */
237        public void removeHeader(String name) {
238    
239            for (int i = 0; i < headers.size(); i++) {
240                MimeHeader mimeheader = (MimeHeader)headers.elementAt(i);
241    
242                if (mimeheader.getName().equalsIgnoreCase(name)) {
243                    headers.removeElementAt(i--);
244                }
245            }
246        }
247    
248        /** Removes all the header entries from this <CODE> MimeHeaders</CODE> object. */
249        public void removeAllHeaders() {
250            headers.removeAllElements();
251        }
252    
253        /**
254         * Returns all the headers in this <CODE>MimeHeaders</CODE> object.
255         *
256         * @return an <CODE>Iterator</CODE> object over this <CODE> MimeHeaders</CODE> object's list of
257         *         <CODE> MimeHeader</CODE> objects
258         */
259        public Iterator getAllHeaders() {
260            return headers.iterator();
261        }
262    
263        /**
264         * Returns all the <CODE>MimeHeader</CODE> objects whose name matches a name in the given array
265         * of names.
266         *
267         * @param names an array of <CODE>String</CODE> objects with the names for which to search
268         * @return an <CODE>Iterator</CODE> object over the <CODE> MimeHeader</CODE> objects whose name
269         *         matches one of the names in the given list
270         */
271        public Iterator getMatchingHeaders(String names[]) {
272            return new MatchingIterator(names, true);
273        }
274    
275        /**
276         * Returns all of the <CODE>MimeHeader</CODE> objects whose name does not match a name in the
277         * given array of names.
278         *
279         * @param names an array of <CODE>String</CODE> objects with the names for which to search
280         * @return an <CODE>Iterator</CODE> object over the <CODE> MimeHeader</CODE> objects whose name
281         *         does not match one of the names in the given list
282         */
283        public Iterator getNonMatchingHeaders(String names[]) {
284            return new MatchingIterator(names, false);
285        }
286    
287        // fixme: does this need to be a Vector? Will a non-synchronized impl of
288        // List do?
289        /** A <code>Vector</code> containing the headers as <code>MimeHeader</code> instances. */
290        private Vector headers;
291    }