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