001    /*
002     * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Util.java $
003     * $Revision: 121 $
004     * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
005     *
006     * ====================================================================
007     * Licensed to the Apache Software Foundation (ASF) under one
008     * or more contributor license agreements.  See the NOTICE file
009     * distributed with this work for additional information
010     * regarding copyright ownership.  The ASF licenses this file
011     * to you under the Apache License, Version 2.0 (the
012     * "License"); you may not use this file except in compliance
013     * with the License.  You may obtain a copy of the License at
014     *
015     *   http://www.apache.org/licenses/LICENSE-2.0
016     *
017     * Unless required by applicable law or agreed to in writing,
018     * software distributed under the License is distributed on an
019     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
020     * KIND, either express or implied.  See the License for the
021     * specific language governing permissions and limitations
022     * under the License.
023     * ====================================================================
024     *
025     * This software consists of voluntary contributions made by many
026     * individuals on behalf of the Apache Software Foundation.  For more
027     * information on the Apache Software Foundation, please see
028     * <http://www.apache.org/>.
029     *
030     */
031    
032    package org.apache.commons.ssl;
033    
034    import java.io.ByteArrayInputStream;
035    import java.io.IOException;
036    import java.io.InputStream;
037    import java.io.OutputStream;
038    import java.net.UnknownHostException;
039    import java.util.LinkedList;
040    import java.util.Map;
041    import java.util.StringTokenizer;
042    import java.util.TreeMap;
043    
044    /**
045     * @author Credit Union Central of British Columbia
046     * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
047     * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
048     * @since 28-Feb-2006
049     */
050    public class Util {
051        public final static int SIZE_KEY = 0;
052        public final static int LAST_READ_KEY = 1;
053    
054        public static boolean isYes(String yesString) {
055            if (yesString == null) {
056                return false;
057            }
058            String s = yesString.trim().toUpperCase();
059            return "1".equals(s) || "YES".equals(s) || "TRUE".equals(s) ||
060                   "ENABLE".equals(s) || "ENABLED".equals(s) || "Y".equals(s) ||
061                   "ON".equals(s);
062        }
063    
064        public static String trim(final String s) {
065            if (s == null || "".equals(s)) {
066                return s;
067            }
068            int i = 0;
069            int j = s.length() - 1;
070            while (isWhiteSpace(s.charAt(i))) {
071                i++;
072            }
073            while (isWhiteSpace(s.charAt(j))) {
074                j--;
075            }
076            return j >= i ? s.substring(i, j + 1) : "";
077        }
078    
079        public static boolean isWhiteSpace(final char c) {
080            switch (c) {
081                case 0:
082                case ' ':
083                case '\t':
084                case '\n':
085                case '\r':
086                case '\f':
087                    return true;
088                default:
089                    return false;
090            }
091        }
092    
093        public static void pipeStream(InputStream in, OutputStream out)
094            throws IOException {
095            pipeStream(in, out, true);
096        }
097    
098        public static void pipeStream(InputStream in, OutputStream out,
099                                      boolean autoClose)
100            throws IOException {
101            byte[] buf = new byte[4096];
102            IOException ioe = null;
103            try {
104                int bytesRead = in.read(buf);
105                while (bytesRead >= 0) {
106                    if (bytesRead > 0) {
107                        out.write(buf, 0, bytesRead);
108                    }
109                    bytesRead = in.read(buf);
110                }
111            }
112            finally {
113                // Probably it's best to let consumer call "close", but I'm usually
114                // the consumer, and I want to be lazy.  [Julius, November 20th, 2006]
115                try { in.close(); } catch (IOException e) { ioe = e; }
116                if (autoClose) {
117                    try { out.close(); } catch (IOException e) { ioe = e; }
118                }
119            }
120            if (ioe != null) {
121                throw ioe;
122            }
123        }
124    
125        public static byte[] streamToBytes(final ByteArrayInputStream in,
126                                           int maxLength) {
127            byte[] buf = new byte[maxLength];
128            int[] status = fill(buf, 0, in);
129            int size = status[SIZE_KEY];
130            if (buf.length != size) {
131                byte[] smallerBuf = new byte[size];
132                System.arraycopy(buf, 0, smallerBuf, 0, size);
133                buf = smallerBuf;
134            }
135            return buf;
136        }
137    
138        public static byte[] streamToBytes(final InputStream in, int maxLength)
139            throws IOException {
140            byte[] buf = new byte[maxLength];
141            int[] status = fill(buf, 0, in);
142            int size = status[SIZE_KEY];
143            if (buf.length != size) {
144                byte[] smallerBuf = new byte[size];
145                System.arraycopy(buf, 0, smallerBuf, 0, size);
146                buf = smallerBuf;
147            }
148            return buf;
149        }
150    
151        public static byte[] streamToBytes(final InputStream in) throws IOException {
152            byte[] buf = new byte[4096];
153            try {
154                int[] status = fill(buf, 0, in);
155                int size = status[SIZE_KEY];
156                int lastRead = status[LAST_READ_KEY];
157                while (lastRead != -1) {
158                    buf = resizeArray(buf);
159                    status = fill(buf, size, in);
160                    size = status[SIZE_KEY];
161                    lastRead = status[LAST_READ_KEY];
162                }
163                if (buf.length != size) {
164                    byte[] smallerBuf = new byte[size];
165                    System.arraycopy(buf, 0, smallerBuf, 0, size);
166                    buf = smallerBuf;
167                }
168            }
169            finally {
170                in.close();
171            }
172            return buf;
173        }
174    
175        public static byte[] streamToBytes(final ByteArrayInputStream in) {
176            byte[] buf = new byte[4096];
177            int[] status = fill(buf, 0, in);
178            int size = status[SIZE_KEY];
179            int lastRead = status[LAST_READ_KEY];
180            while (lastRead != -1) {
181                buf = resizeArray(buf);
182                status = fill(buf, size, in);
183                size = status[SIZE_KEY];
184                lastRead = status[LAST_READ_KEY];
185            }
186            if (buf.length != size) {
187                byte[] smallerBuf = new byte[size];
188                System.arraycopy(buf, 0, smallerBuf, 0, size);
189                buf = smallerBuf;
190            }
191            // in.close();  <-- this is a no-op on ByteArrayInputStream.
192            return buf;
193        }
194    
195        public static int[] fill(final byte[] buf, final int offset,
196                                 final InputStream in)
197            throws IOException {
198            int read = in.read(buf, offset, buf.length - offset);
199            int lastRead = read;
200            if (read == -1) {
201                read = 0;
202            }
203            while (lastRead != -1 && read + offset < buf.length) {
204                lastRead = in.read(buf, offset + read, buf.length - read - offset);
205                if (lastRead != -1) {
206                    read += lastRead;
207                }
208            }
209            return new int[]{offset + read, lastRead};
210        }
211    
212        public static int[] fill(final byte[] buf, final int offset,
213                                 final ByteArrayInputStream in) {
214            int read = in.read(buf, offset, buf.length - offset);
215            int lastRead = read;
216            if (read == -1) {
217                read = 0;
218            }
219            while (lastRead != -1 && read + offset < buf.length) {
220                lastRead = in.read(buf, offset + read, buf.length - read - offset);
221                if (lastRead != -1) {
222                    read += lastRead;
223                }
224            }
225            return new int[]{offset + read, lastRead};
226        }
227    
228        public static byte[] resizeArray(final byte[] bytes) {
229            byte[] biggerBytes = new byte[bytes.length * 2];
230            System.arraycopy(bytes, 0, biggerBytes, 0, bytes.length);
231            return biggerBytes;
232        }
233    
234        public static String pad(String s, final int length, final boolean left) {
235            if (s == null) {
236                s = "";
237            }
238            int diff = length - s.length();
239            if (diff == 0) {
240                return s;
241            } else if (diff > 0) {
242                StringBuffer sb = new StringBuffer();
243                if (left) {
244                    for (int i = 0; i < diff; i++) {
245                        sb.append(' ');
246                    }
247                }
248                sb.append(s);
249                if (!left) {
250                    for (int i = 0; i < diff; i++) {
251                        sb.append(' ');
252                    }
253                }
254                return sb.toString();
255            } else {
256                return s;
257            }
258        }
259    
260        public static Map parseArgs(final String[] cargs) {
261            Map args = new TreeMap();
262            Map ARGS_MATCH = Ping.ARGS_MATCH;
263    
264            int l = cargs.length;
265            final String[] EMPTY_VALUES = {""};
266            for (int i = 0; i < l; i++) {
267                String k = cargs[i];
268                Ping.Arg a = (Ping.Arg) ARGS_MATCH.get(k);
269                if (l > i + 1) {
270                    String v = cargs[++i];
271                    while (ARGS_MATCH.containsKey(v)) {
272                        args.put(a, EMPTY_VALUES);
273                        a = (Ping.Arg) ARGS_MATCH.get(v);
274                        v = "";
275                        if (l > i + 1) {
276                            v = cargs[++i];
277                        }
278                    }
279                    String[] values = new String[1];
280                    values[0] = v;
281                    args.put(a, values);
282                    if (l > i + 1 && !ARGS_MATCH.containsKey(cargs[i + 1])) {
283                        LinkedList list = new LinkedList();
284                        list.add(v);
285                        while (l > i + 1 && !ARGS_MATCH.containsKey(cargs[i + 1])) {
286                            v = cargs[++i];
287                            list.add(v);
288                        }
289                        args.put(a, list.toArray(new String[list.size()]));
290                    }
291                } else {
292                    args.put(a, EMPTY_VALUES);
293                }
294            }
295            return args;
296        }
297    
298        public static String readLine(final InputStream in) throws IOException {
299            StringBuffer buf = new StringBuffer(64);
300            int b = in.read();
301            while (b != -1) {
302                char c = (char) b;
303                if (c == '\n' || c == '\r') {
304                    if (buf.length() >= 1) {
305                        return buf.toString();
306                    }
307                } else {
308                    buf.append(c);
309                }
310                b = in.read();
311            }
312            return buf.length() >= 1 ? buf.toString() : null;
313        }
314    
315        public static String readLine(final ByteArrayInputStream in) {
316            StringBuffer buf = new StringBuffer(64);
317            int b = in.read();
318            while (b != -1) {
319                char c = (char) b;
320                if (c == '\n' || c == '\r') {
321                    if (buf.length() >= 1) {
322                        return buf.toString();
323                    }
324                } else {
325                    buf.append(c);
326                }
327                b = in.read();
328            }
329            return buf.length() >= 1 ? buf.toString() : null;
330        }
331    
332        public static HostPort toAddress(final String target,
333                                         final int defaultPort)
334            throws UnknownHostException {
335            String host = target;
336            int port = defaultPort;
337            StringTokenizer st = new StringTokenizer(target, ":");
338            if (st.hasMoreTokens()) {
339                host = st.nextToken().trim();
340            }
341            if (st.hasMoreTokens()) {
342                port = Integer.parseInt(st.nextToken().trim());
343            }
344            if (st.hasMoreTokens()) {
345                throw new IllegalArgumentException("Invalid host: " + target);
346            }
347            return new HostPort(host, port);
348        }
349    
350        public static String cipherToAuthType(String cipher) {
351            if (cipher == null) {
352                return null;
353            }
354    
355            // SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA  ==> "DHE_DSS_EXPORT"
356            // SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA      ==> "DHE_DSS"
357            // SSL_RSA_WITH_3DES_EDE_CBC_SHA          ==> "RSA"
358    
359            StringTokenizer st = new StringTokenizer(cipher.trim(), "_");
360            if (st.hasMoreTokens()) {
361                st.nextToken();  // always skip first token
362            }
363            if (st.hasMoreTokens()) {
364                String tok = st.nextToken();
365                StringBuffer buf = new StringBuffer();
366                buf.append(tok);
367                if (st.hasMoreTokens()) {
368                    tok = st.nextToken();
369                    while (!"WITH".equalsIgnoreCase(tok)) {
370                        buf.append('_');
371                        buf.append(tok);
372                        tok = st.nextToken();
373                    }
374                }
375                return buf.toString();
376            }
377            throw new IllegalArgumentException("not a valid cipher: " + cipher);
378        }
379    
380    
381        public static void main(String[] args) throws Exception {
382            String s = "line1\n\rline2\n\rline3";
383            InputStream in = new ByteArrayInputStream(s.getBytes());
384            String line = readLine(in);
385            while (line != null) {
386                System.out.println(line);
387                line = readLine(in);
388            }
389    
390            System.out.println("--------- test 2 ----------");
391    
392            s = "line1\n\rline2\n\rline3\n\r\n\r";
393            in = new ByteArrayInputStream(s.getBytes());
394            line = readLine(in);
395            while (line != null) {
396                System.out.println(line);
397                line = readLine(in);
398            }
399    
400        }
401    
402    
403    }