001/*
002 * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.11/src/java/org/apache/commons/ssl/Util.java $
003 * $Revision: 132 $
004 * $Date: 2008-01-11 21:20:26 -0800 (Fri, 11 Jan 2008) $
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
032package org.apache.commons.ssl;
033
034import org.apache.commons.ssl.util.ByteArrayReadLine;
035
036import java.io.ByteArrayInputStream;
037import java.io.IOException;
038import java.io.InputStream;
039import java.io.OutputStream;
040import java.net.UnknownHostException;
041import java.util.LinkedList;
042import java.util.Map;
043import java.util.StringTokenizer;
044import java.util.TreeMap;
045
046/**
047 * @author Credit Union Central of British Columbia
048 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
049 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
050 * @since 28-Feb-2006
051 */
052public class Util {
053    public final static int SIZE_KEY = 0;
054    public final static int LAST_READ_KEY = 1;
055
056    public static boolean isYes(String yesString) {
057        if (yesString == null) {
058            return false;
059        }
060        String s = yesString.trim().toUpperCase();
061        return "1".equals(s) || "YES".equals(s) || "TRUE".equals(s) ||
062               "ENABLE".equals(s) || "ENABLED".equals(s) || "Y".equals(s) ||
063               "ON".equals(s);
064    }
065
066    public static String trim(final String s) {
067        if (s == null || "".equals(s)) {
068            return s;
069        }
070        int i = 0;
071        int j = s.length() - 1;
072        while (isWhiteSpace(s.charAt(i))) {
073            i++;
074        }
075        while (isWhiteSpace(s.charAt(j))) {
076            j--;
077        }
078        return j >= i ? s.substring(i, j + 1) : "";
079    }
080
081    public static boolean isWhiteSpace(final char c) {
082        switch (c) {
083            case 0:
084            case ' ':
085            case '\t':
086            case '\n':
087            case '\r':
088            case '\f':
089                return true;
090            default:
091                return false;
092        }
093    }
094
095    public static void pipeStream(InputStream in, OutputStream out)
096        throws IOException {
097        pipeStream(in, out, true);
098    }
099
100    public static void pipeStream(InputStream in, OutputStream out,
101                                  boolean autoClose)
102        throws IOException {
103        byte[] buf = new byte[8192];
104        IOException ioe = null;
105        try {
106            int bytesRead = in.read(buf);
107            while (bytesRead >= 0) {
108                if (bytesRead > 0) {
109                    out.write(buf, 0, bytesRead);
110                }
111                bytesRead = in.read(buf);
112            }
113        }
114        finally {
115            // Probably it's best to let consumer call "close", but I'm usually
116            // the consumer, and I want to be lazy.  [Julius, November 20th, 2006]
117            try { in.close(); } catch (IOException e) { ioe = e; }
118            if (autoClose) {
119                try { out.close(); } catch (IOException e) { ioe = e; }
120            }
121        }
122        if (ioe != null) {
123            throw ioe;
124        }
125    }
126
127    public static byte[] streamToBytes(final ByteArrayInputStream in,
128                                       int maxLength) {
129        byte[] buf = new byte[maxLength];
130        int[] status = fill(buf, 0, in);
131        int size = status[SIZE_KEY];
132        if (buf.length != size) {
133            byte[] smallerBuf = new byte[size];
134            System.arraycopy(buf, 0, smallerBuf, 0, size);
135            buf = smallerBuf;
136        }
137        return buf;
138    }
139
140    public static byte[] streamToBytes(final InputStream in, int maxLength)
141        throws IOException {
142        byte[] buf = new byte[maxLength];
143        int[] status = fill(buf, 0, in);
144        int size = status[SIZE_KEY];
145        if (buf.length != size) {
146            byte[] smallerBuf = new byte[size];
147            System.arraycopy(buf, 0, smallerBuf, 0, size);
148            buf = smallerBuf;
149        }
150        return buf;
151    }
152
153    public static byte[] streamToBytes(final InputStream in) throws IOException {
154        byte[] buf = new byte[4096];
155        try {
156            int[] status = fill(buf, 0, in);
157            int size = status[SIZE_KEY];
158            int lastRead = status[LAST_READ_KEY];
159            while (lastRead != -1) {
160                buf = resizeArray(buf);
161                status = fill(buf, size, in);
162                size = status[SIZE_KEY];
163                lastRead = status[LAST_READ_KEY];
164            }
165            if (buf.length != size) {
166                byte[] smallerBuf = new byte[size];
167                System.arraycopy(buf, 0, smallerBuf, 0, size);
168                buf = smallerBuf;
169            }
170        }
171        finally {
172            in.close();
173        }
174        return buf;
175    }
176
177    public static byte[] streamToBytes(final ByteArrayInputStream in) {
178        byte[] buf = new byte[4096];
179        int[] status = fill(buf, 0, in);
180        int size = status[SIZE_KEY];
181        int lastRead = status[LAST_READ_KEY];
182        while (lastRead != -1) {
183            buf = resizeArray(buf);
184            status = fill(buf, size, in);
185            size = status[SIZE_KEY];
186            lastRead = status[LAST_READ_KEY];
187        }
188        if (buf.length != size) {
189            byte[] smallerBuf = new byte[size];
190            System.arraycopy(buf, 0, smallerBuf, 0, size);
191            buf = smallerBuf;
192        }
193        // in.close();  <-- this is a no-op on ByteArrayInputStream.
194        return buf;
195    }
196
197    public static int[] fill(final byte[] buf, final int offset,
198                             final InputStream in)
199        throws IOException {
200        int read = in.read(buf, offset, buf.length - offset);
201        int lastRead = read;
202        if (read == -1) {
203            read = 0;
204        }
205        while (lastRead != -1 && read + offset < buf.length) {
206            lastRead = in.read(buf, offset + read, buf.length - read - offset);
207            if (lastRead != -1) {
208                read += lastRead;
209            }
210        }
211        return new int[]{offset + read, lastRead};
212    }
213
214    public static int[] fill(final byte[] buf, final int offset,
215                             final ByteArrayInputStream in) {
216        int read = in.read(buf, offset, buf.length - offset);
217        int lastRead = read;
218        if (read == -1) {
219            read = 0;
220        }
221        while (lastRead != -1 && read + offset < buf.length) {
222            lastRead = in.read(buf, offset + read, buf.length - read - offset);
223            if (lastRead != -1) {
224                read += lastRead;
225            }
226        }
227        return new int[]{offset + read, lastRead};
228    }
229
230    public static byte[] resizeArray(final byte[] bytes) {
231        byte[] biggerBytes = new byte[bytes.length * 2];
232        System.arraycopy(bytes, 0, biggerBytes, 0, bytes.length);
233        return biggerBytes;
234    }
235
236    public static String pad(String s, final int length, final boolean left) {
237        if (s == null) {
238            s = "";
239        }
240        int diff = length - s.length();
241        if (diff == 0) {
242            return s;
243        } else if (diff > 0) {
244            StringBuffer sb = new StringBuffer();
245            if (left) {
246                for (int i = 0; i < diff; i++) {
247                    sb.append(' ');
248                }
249            }
250            sb.append(s);
251            if (!left) {
252                for (int i = 0; i < diff; i++) {
253                    sb.append(' ');
254                }
255            }
256            return sb.toString();
257        } else {
258            return s;
259        }
260    }
261
262    public static Map parseArgs(final String[] cargs) {
263        Map args = new TreeMap();
264        Map ARGS_MATCH = Ping.ARGS_MATCH;
265
266        int l = cargs.length;
267        final String[] EMPTY_VALUES = {""};
268        for (int i = 0; i < l; i++) {
269            String k = cargs[i];
270            Ping.Arg a = (Ping.Arg) ARGS_MATCH.get(k);
271            if (l > i + 1) {
272                String v = cargs[++i];
273                while (ARGS_MATCH.containsKey(v)) {
274                    args.put(a, EMPTY_VALUES);
275                    a = (Ping.Arg) ARGS_MATCH.get(v);
276                    v = "";
277                    if (l > i + 1) {
278                        v = cargs[++i];
279                    }
280                }
281                String[] values = new String[1];
282                values[0] = v;
283                args.put(a, values);
284                if (l > i + 1 && !ARGS_MATCH.containsKey(cargs[i + 1])) {
285                    LinkedList list = new LinkedList();
286                    list.add(v);
287                    while (l > i + 1 && !ARGS_MATCH.containsKey(cargs[i + 1])) {
288                        v = cargs[++i];
289                        list.add(v);
290                    }
291                    args.put(a, list.toArray(new String[list.size()]));
292                }
293            } else {
294                args.put(a, EMPTY_VALUES);
295            }
296        }
297        return args;
298    }
299
300    public static HostPort toAddress(final String target,
301                                     final int defaultPort)
302        throws UnknownHostException {
303        String host = target;
304        int port = defaultPort;
305        StringTokenizer st = new StringTokenizer(target, ":");
306        if (st.hasMoreTokens()) {
307            host = st.nextToken().trim();
308        }
309        if (st.hasMoreTokens()) {
310            port = Integer.parseInt(st.nextToken().trim());
311        }
312        if (st.hasMoreTokens()) {
313            throw new IllegalArgumentException("Invalid host: " + target);
314        }
315        return new HostPort(host, port);
316    }
317
318    public static String cipherToAuthType(String cipher) {
319        if (cipher == null) {
320            return null;
321        }
322
323        // SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA  ==> "DHE_DSS_EXPORT"
324        // SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA      ==> "DHE_DSS"
325        // SSL_RSA_WITH_3DES_EDE_CBC_SHA          ==> "RSA"
326
327        StringTokenizer st = new StringTokenizer(cipher.trim(), "_");
328        if (st.hasMoreTokens()) {
329            st.nextToken();  // always skip first token
330        }
331        if (st.hasMoreTokens()) {
332            String tok = st.nextToken();
333            StringBuffer buf = new StringBuffer();
334            buf.append(tok);
335            if (st.hasMoreTokens()) {
336                tok = st.nextToken();
337                while (!"WITH".equalsIgnoreCase(tok)) {
338                    buf.append('_');
339                    buf.append(tok);
340                    tok = st.nextToken();
341                }
342            }
343            return buf.toString();
344        }
345        throw new IllegalArgumentException("not a valid cipher: " + cipher);
346    }
347
348
349    public static void main(String[] args) throws Exception {
350        String s = "line1\n\rline2\n\rline3";
351        ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes());
352        ByteArrayReadLine readLine = new ByteArrayReadLine(in);
353        String line = readLine.next();
354        while (line != null) {
355            System.out.println(line);
356            line = readLine.next();
357        }
358
359        System.out.println("--------- test 2 ----------");
360
361        s = "line1\n\rline2\n\rline3\n\r\n\r";
362        in = new ByteArrayInputStream(s.getBytes());
363        readLine = new ByteArrayReadLine(in);
364        line = readLine.next();
365        while (line != null) {
366            System.out.println(line);
367            line = readLine.next();
368        }
369
370    }
371
372
373}