001    /*
002     * Copyright 2001-2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package javax.xml.soap;
017    
018    import java.util.Iterator;
019    import java.util.Vector;
020    
021    /**
022     * A container for <CODE>MimeHeader</CODE> objects, which
023     *   represent the MIME headers present in a MIME part of a
024     *   message.</P>
025     *
026     *   <P>This class is used primarily when an application wants to
027     *   retrieve specific attachments based on certain MIME headers and
028     *   values. This class will most likely be used by implementations
029     *   of <CODE>AttachmentPart</CODE> and other MIME dependent parts
030     *   of the JAXM API.
031     * @see SOAPMessage#getAttachments() SOAPMessage.getAttachments()
032     * @see AttachmentPart AttachmentPart
033     */
034    public class MimeHeaders {
035    
036        class MatchingIterator implements Iterator {
037    
038            private Object nextMatch() {
039    
040                label0:
041                while (iterator.hasNext()) {
042                    MimeHeader mimeheader = (MimeHeader) iterator.next();
043    
044                    if (names == null) {
045                        return match
046                               ? null
047                               : mimeheader;
048                    }
049    
050                    for (int i = 0; i < names.length; i++) {
051                        if (!mimeheader.getName().equalsIgnoreCase(names[i])) {
052                            continue;
053                        }
054    
055                        if (match) {
056                            return mimeheader;
057                        }
058    
059                        continue label0;
060                    }
061    
062                    if (!match) {
063                        return mimeheader;
064                    }
065                }
066    
067                return null;
068            }
069    
070            public boolean hasNext() {
071    
072                if (nextHeader == null) {
073                    nextHeader = nextMatch();
074                }
075    
076                return nextHeader != null;
077            }
078    
079            public Object next() {
080    
081                if (nextHeader != null) {
082                    Object obj = nextHeader;
083    
084                    nextHeader = null;
085    
086                    return obj;
087                }
088    
089                if (hasNext()) {
090                    return nextHeader;
091                } else {
092                    return null;
093                }
094            }
095    
096            public void remove() {
097                iterator.remove();
098            }
099    
100            private boolean match;
101    
102            private Iterator iterator;
103    
104            private String names[];
105    
106            private Object nextHeader;
107    
108            MatchingIterator(String as[], boolean flag) {
109    
110                match    = flag;
111                names    = as;
112                iterator = headers.iterator();
113            }
114        }
115    
116        /**
117         * Constructs
118         *   a default <CODE>MimeHeaders</CODE> object initialized with
119         *   an empty <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
127         * array of <CODE>String</CODE> objects.
128         * @param   name  the name of the header for which
129         *     values will be returned
130         * @return a <CODE>String</CODE> array with all of the values
131         *     for the specified header
132         * @see #setHeader(java.lang.String, java.lang.String) setHeader(java.lang.String, 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
160         *   name matches the given name with the given value, adding a
161         *   new header if no existing header name matches. This method
162         *   also removes all matching headers after the first one.
163         *
164         *   <P>Note that RFC822 headers can contain only US-ASCII
165         *   characters.</P>
166         * @param  name a <CODE>String</CODE> with the
167         *     name of the header for which to search
168         * @param  value a <CODE>String</CODE> with the
169         *     value that will replace the current value of the
170         *     specified header
171         * @throws java.lang.IllegalArgumentException if there was a
172         * problem in the mime header name or the value being set
173         * @see #getHeader(java.lang.String) getHeader(java.lang.String)
174         */
175        public void setHeader(String name, String value) {
176    
177            boolean flag = false;
178    
179            if ((name == null) || name.equals("")) {
180                throw new IllegalArgumentException(
181                    "Illegal MimeHeader name");
182            }
183    
184            for (int i = 0; i < headers.size(); i++) {
185                MimeHeader mimeheader = (MimeHeader) headers.elementAt(i);
186    
187                if (mimeheader.getName().equalsIgnoreCase(name)) {
188                    if (!flag) {
189                        headers.setElementAt(new MimeHeader(mimeheader
190                            .getName(), value), i);
191    
192                        flag = true;
193                    } else {
194                        headers.removeElementAt(i--);
195                    }
196                }
197            }
198    
199            if (!flag) {
200                addHeader(name, value);
201            }
202        }
203    
204        /**
205         * Adds a <CODE>MimeHeader</CODE> object with the specified
206         *   name and value to this <CODE>MimeHeaders</CODE> object's
207         *   list of headers.
208         *
209         *   <P>Note that RFC822 headers can contain only US-ASCII
210         *   characters.</P>
211         * @param  name   a <CODE>String</CODE> with the
212         *     name of the header to be added
213         * @param  value  a <CODE>String</CODE> with the
214         *     value of the header to be added
215         * @throws java.lang.IllegalArgumentException if
216         *     there was a problem in the mime header name or value
217         *     being added
218         */
219        public void addHeader(String name, String value) {
220    
221            if ((name == null) || name.equals("")) {
222                throw new IllegalArgumentException(
223                    "Illegal MimeHeader name");
224            }
225    
226            int i = headers.size();
227    
228            for (int j = i - 1; j >= 0; j--) {
229                MimeHeader mimeheader = (MimeHeader) headers.elementAt(j);
230    
231                if (mimeheader.getName().equalsIgnoreCase(name)) {
232                    headers.insertElementAt(new MimeHeader(name, value), j + 1);
233    
234                    return;
235                }
236            }
237    
238            headers.addElement(new MimeHeader(name, value));
239        }
240    
241        /**
242         * Remove all <CODE>MimeHeader</CODE> objects whose name
243         * matches the the given name.
244         * @param  name  a <CODE>String</CODE> with the
245         *     name of the header for which to search
246         */
247        public void removeHeader(String name) {
248    
249            for (int i = 0; i < headers.size(); i++) {
250                MimeHeader mimeheader = (MimeHeader) headers.elementAt(i);
251    
252                if (mimeheader.getName().equalsIgnoreCase(name)) {
253                    headers.removeElementAt(i--);
254                }
255            }
256        }
257    
258        /**
259         * Removes all the header entries from this <CODE>
260         * MimeHeaders</CODE> object.
261         */
262        public void removeAllHeaders() {
263            headers.removeAllElements();
264        }
265    
266        /**
267         * Returns all the headers in this <CODE>MimeHeaders</CODE>
268         * object.
269         * @return  an <CODE>Iterator</CODE> object over this <CODE>
270         *     MimeHeaders</CODE> object's list of <CODE>
271         *     MimeHeader</CODE> objects
272         */
273        public Iterator getAllHeaders() {
274            return headers.iterator();
275        }
276    
277        /**
278         * Returns all the <CODE>MimeHeader</CODE> objects whose
279         * name matches a name in the given array of names.
280         * @param   names an array of <CODE>String</CODE>
281         *    objects with the names for which to search
282         * @return  an <CODE>Iterator</CODE> object over the <CODE>
283         *     MimeHeader</CODE> objects whose name matches one of the
284         *     names in the given list
285         */
286        public Iterator getMatchingHeaders(String names[]) {
287            return new MatchingIterator(names, true);
288        }
289    
290        /**
291         * Returns all of the <CODE>MimeHeader</CODE> objects whose
292         * name does not match a name in the given array of names.
293         * @param   names  an array of <CODE>String</CODE>
294         *     objects with the names for which to search
295         * @return an <CODE>Iterator</CODE> object over the <CODE>
296         *     MimeHeader</CODE> objects whose name does not match one
297         *     of the names in the given list
298         */
299        public Iterator getNonMatchingHeaders(String names[]) {
300            return new MatchingIterator(names, false);
301        }
302    
303        // fixme: does this need to be a Vector? Will a non-synchronized impl of
304        // List do?
305        /**
306         * A <code>Vector</code> containing the headers as <code>MimeHeader</code>
307         *              instances.
308         */
309        private Vector headers;
310    }