Save This Page
Home » openjdk-7 » sun.security » provider » [javadoc | source]
    1   /*
    2    * Copyright 1998-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package sun.security.provider;
   27   
   28   import java.io;
   29   import java.util.Collection;
   30   import java.util;
   31   import java.security.cert;
   32   import sun.security.x509.X509CertImpl;
   33   import sun.security.x509.X509CRLImpl;
   34   import sun.security.pkcs.PKCS7;
   35   import sun.security.provider.certpath.X509CertPath;
   36   import sun.security.provider.certpath.X509CertificatePair;
   37   import sun.security.util.DerValue;
   38   import sun.security.util.Cache;
   39   import sun.misc.BASE64Decoder;
   40   
   41   /**
   42    * This class defines a certificate factory for X.509 v3 certificates &
   43    * certification paths, and X.509 v2 certificate revocation lists (CRLs).
   44    *
   45    * @author Jan Luehe
   46    * @author Hemma Prafullchandra
   47    * @author Sean Mullan
   48    *
   49    *
   50    * @see java.security.cert.CertificateFactorySpi
   51    * @see java.security.cert.Certificate
   52    * @see java.security.cert.CertPath
   53    * @see java.security.cert.CRL
   54    * @see java.security.cert.X509Certificate
   55    * @see java.security.cert.X509CRL
   56    * @see sun.security.x509.X509CertImpl
   57    * @see sun.security.x509.X509CRLImpl
   58    */
   59   
   60   public class X509Factory extends CertificateFactorySpi {
   61   
   62       public static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
   63       public static final String END_CERT = "-----END CERTIFICATE-----";
   64   
   65       private static final int defaultExpectedLineLength = 80;
   66   
   67       private static final char[] endBoundary = "-----END".toCharArray();
   68   
   69       private static final int ENC_MAX_LENGTH = 4096 * 1024; // 4 MB MAX
   70   
   71       private static final Cache certCache = Cache.newSoftMemoryCache(750);
   72       private static final Cache crlCache = Cache.newSoftMemoryCache(750);
   73   
   74       /**
   75        * Generates an X.509 certificate object and initializes it with
   76        * the data read from the input stream <code>is</code>.
   77        *
   78        * @param is an input stream with the certificate data.
   79        *
   80        * @return an X.509 certificate object initialized with the data
   81        * from the input stream.
   82        *
   83        * @exception CertificateException on parsing errors.
   84        */
   85       public Certificate engineGenerateCertificate(InputStream is)
   86           throws CertificateException
   87       {
   88           if (is == null) {
   89               // clear the caches (for debugging)
   90               certCache.clear();
   91               X509CertificatePair.clearCache();
   92               throw new CertificateException("Missing input stream");
   93           }
   94           try {
   95               if (is.markSupported() == false) {
   96                   // consume the entire input stream
   97                   byte[] totalBytes;
   98                   totalBytes = getTotalBytes(new BufferedInputStream(is));
   99                   is = new ByteArrayInputStream(totalBytes);
  100               }
  101               byte[] encoding = readSequence(is);
  102               if (encoding != null) {
  103                   X509CertImpl cert = (X509CertImpl)getFromCache(certCache, encoding);
  104                   if (cert != null) {
  105                       return cert;
  106                   }
  107                   cert = new X509CertImpl(encoding);
  108                   addToCache(certCache, cert.getEncodedInternal(), cert);
  109                   return cert;
  110               } else {
  111                   X509CertImpl cert;
  112                   // determine if binary or Base64 encoding. If Base64 encoding,
  113                   // the certificate must be bounded at the beginning by
  114                   // "-----BEGIN".
  115                   if (isBase64(is)) {
  116                       // Base64
  117                       byte[] data = base64_to_binary(is);
  118                       cert = new X509CertImpl(data);
  119                   } else {
  120                       // binary
  121                       cert = new X509CertImpl(new DerValue(is));
  122                   }
  123                   return intern(cert);
  124               }
  125           } catch (IOException ioe) {
  126               throw (CertificateException)new CertificateException
  127               ("Could not parse certificate: " + ioe.toString()).initCause(ioe);
  128           }
  129       }
  130   
  131       /**
  132        * Read a DER SEQUENCE from an InputStream and return the encoding.
  133        * If data does not represent a SEQUENCE, it uses indefinite length
  134        * encoding, or is longer than ENC_MAX_LENGTH, the stream is reset
  135        * and this method returns null.
  136        */
  137       private static byte[] readSequence(InputStream in) throws IOException {
  138           in.mark(ENC_MAX_LENGTH);
  139           byte[] b = new byte[4];
  140           int i = readFully(in, b, 0, b.length);
  141           if ((i != b.length) || (b[0] != 0x30)) { // first byte must be SEQUENCE
  142               in.reset();
  143               return null;
  144           }
  145           i = b[1] & 0xff;
  146           int totalLength;
  147           if (i < 0x80) {
  148               int valueLength = i;
  149               totalLength = valueLength + 2;
  150           } else if (i == 0x81) {
  151               int valueLength = b[2] & 0xff;
  152               totalLength = valueLength + 3;
  153           } else if (i == 0x82) {
  154               int valueLength = ((b[2] & 0xff) << 8) | (b[3] & 0xff);
  155               totalLength = valueLength + 4;
  156           } else { // ignore longer length forms
  157               in.reset();
  158               return null;
  159           }
  160           if (totalLength > ENC_MAX_LENGTH) {
  161               in.reset();
  162               return null;
  163           }
  164           byte[] encoding = new byte[totalLength];
  165           if( totalLength < b.length ) {
  166               in.reset();
  167               i = readFully(in, encoding, 0, totalLength);
  168               if( i != totalLength ) {
  169                   in.reset();
  170                   return null;
  171               }
  172           } else {
  173               System.arraycopy(b, 0, encoding, 0, b.length);
  174               int n = totalLength - b.length;
  175               i = readFully(in, encoding, b.length, n);
  176               if (i != n) {
  177                   in.reset();
  178                   return null;
  179               }
  180           }
  181           return encoding;
  182       }
  183   
  184       /**
  185        * Read from the stream until length bytes have been read or EOF has
  186        * been reached. Return the number of bytes actually read.
  187        */
  188       private static int readFully(InputStream in, byte[] buffer, int offset,
  189               int length) throws IOException {
  190           int read = 0;
  191           while (length > 0) {
  192               int n = in.read(buffer, offset, length);
  193               if (n <= 0) {
  194                   break;
  195               }
  196               read += n;
  197               length -= n;
  198               offset += n;
  199           }
  200           return read;
  201       }
  202   
  203       /**
  204        * Return an interned X509CertImpl for the given certificate.
  205        * If the given X509Certificate or X509CertImpl is already present
  206        * in the cert cache, the cached object is returned. Otherwise,
  207        * if it is a X509Certificate, it is first converted to a X509CertImpl.
  208        * Then the X509CertImpl is added to the cache and returned.
  209        *
  210        * Note that all certificates created via generateCertificate(InputStream)
  211        * are already interned and this method does not need to be called.
  212        * It is useful for certificates that cannot be created via
  213        * generateCertificate() and for converting other X509Certificate
  214        * implementations to an X509CertImpl.
  215        */
  216       public static synchronized X509CertImpl intern(X509Certificate c)
  217               throws CertificateException {
  218           if (c == null) {
  219               return null;
  220           }
  221           boolean isImpl = c instanceof X509CertImpl;
  222           byte[] encoding;
  223           if (isImpl) {
  224               encoding = ((X509CertImpl)c).getEncodedInternal();
  225           } else {
  226               encoding = c.getEncoded();
  227           }
  228           X509CertImpl newC = (X509CertImpl)getFromCache(certCache, encoding);
  229           if (newC != null) {
  230               return newC;
  231           }
  232           if (isImpl) {
  233               newC = (X509CertImpl)c;
  234           } else {
  235               newC = new X509CertImpl(encoding);
  236               encoding = newC.getEncodedInternal();
  237           }
  238           addToCache(certCache, encoding, newC);
  239           return newC;
  240       }
  241   
  242       /**
  243        * Return an interned X509CRLImpl for the given certificate.
  244        * For more information, see intern(X509Certificate).
  245        */
  246       public static synchronized X509CRLImpl intern(X509CRL c)
  247               throws CRLException {
  248           if (c == null) {
  249               return null;
  250           }
  251           boolean isImpl = c instanceof X509CRLImpl;
  252           byte[] encoding;
  253           if (isImpl) {
  254               encoding = ((X509CRLImpl)c).getEncodedInternal();
  255           } else {
  256               encoding = c.getEncoded();
  257           }
  258           X509CRLImpl newC = (X509CRLImpl)getFromCache(crlCache, encoding);
  259           if (newC != null) {
  260               return newC;
  261           }
  262           if (isImpl) {
  263               newC = (X509CRLImpl)c;
  264           } else {
  265               newC = new X509CRLImpl(encoding);
  266               encoding = newC.getEncodedInternal();
  267           }
  268           addToCache(crlCache, encoding, newC);
  269           return newC;
  270       }
  271   
  272       /**
  273        * Get the X509CertImpl or X509CRLImpl from the cache.
  274        */
  275       private static synchronized Object getFromCache(Cache cache,
  276               byte[] encoding) {
  277           Object key = new Cache.EqualByteArray(encoding);
  278           Object value = cache.get(key);
  279           return value;
  280       }
  281   
  282       /**
  283        * Add the X509CertImpl or X509CRLImpl to the cache.
  284        */
  285       private static synchronized void addToCache(Cache cache, byte[] encoding,
  286               Object value) {
  287           if (encoding.length > ENC_MAX_LENGTH) {
  288               return;
  289           }
  290           Object key = new Cache.EqualByteArray(encoding);
  291           cache.put(key, value);
  292       }
  293   
  294       /**
  295        * Generates a <code>CertPath</code> object and initializes it with
  296        * the data read from the <code>InputStream</code> inStream. The data
  297        * is assumed to be in the default encoding.
  298        *
  299        * @param inStream an <code>InputStream</code> containing the data
  300        * @return a <code>CertPath</code> initialized with the data from the
  301        *   <code>InputStream</code>
  302        * @exception CertificateException if an exception occurs while decoding
  303        * @since 1.4
  304        */
  305       public CertPath engineGenerateCertPath(InputStream inStream)
  306           throws CertificateException
  307       {
  308           if (inStream == null) {
  309               throw new CertificateException("Missing input stream");
  310           }
  311           try {
  312               if (inStream.markSupported() == false) {
  313                   // consume the entire input stream
  314                   byte[] totalBytes;
  315                   totalBytes = getTotalBytes(new BufferedInputStream(inStream));
  316                   inStream = new ByteArrayInputStream(totalBytes);
  317               }
  318               // determine if binary or Base64 encoding. If Base64 encoding,
  319               // each certificate must be bounded at the beginning by
  320               // "-----BEGIN".
  321               if (isBase64(inStream)) {
  322                   // Base64
  323                   byte[] data = base64_to_binary(inStream);
  324                   return new X509CertPath(new ByteArrayInputStream(data));
  325               } else {
  326                   return new X509CertPath(inStream);
  327               }
  328           } catch (IOException ioe) {
  329               throw new CertificateException(ioe.getMessage());
  330           }
  331       }
  332   
  333       /**
  334        * Generates a <code>CertPath</code> object and initializes it with
  335        * the data read from the <code>InputStream</code> inStream. The data
  336        * is assumed to be in the specified encoding.
  337        *
  338        * @param inStream an <code>InputStream</code> containing the data
  339        * @param encoding the encoding used for the data
  340        * @return a <code>CertPath</code> initialized with the data from the
  341        *   <code>InputStream</code>
  342        * @exception CertificateException if an exception occurs while decoding or
  343        *   the encoding requested is not supported
  344        * @since 1.4
  345        */
  346       public CertPath engineGenerateCertPath(InputStream inStream,
  347           String encoding) throws CertificateException
  348       {
  349           if (inStream == null) {
  350               throw new CertificateException("Missing input stream");
  351           }
  352           try {
  353               if (inStream.markSupported() == false) {
  354                   // consume the entire input stream
  355                   byte[] totalBytes;
  356                   totalBytes = getTotalBytes(new BufferedInputStream(inStream));
  357                   inStream = new ByteArrayInputStream(totalBytes);
  358               }
  359               // determine if binary or Base64 encoding. If Base64 encoding,
  360               // each certificate must be bounded at the beginning by
  361               // "-----BEGIN".
  362               if (isBase64(inStream)) {
  363                   // Base64
  364                   byte[] data = base64_to_binary(inStream);
  365                   return new X509CertPath(new ByteArrayInputStream(data), encoding);
  366               } else {
  367                   return(new X509CertPath(inStream, encoding));
  368               }
  369           } catch (IOException ioe) {
  370               throw new CertificateException(ioe.getMessage());
  371           }
  372       }
  373   
  374       /**
  375        * Generates a <code>CertPath</code> object and initializes it with
  376        * a <code>List</code> of <code>Certificate</code>s.
  377        * <p>
  378        * The certificates supplied must be of a type supported by the
  379        * <code>CertificateFactory</code>. They will be copied out of the supplied
  380        * <code>List</code> object.
  381        *
  382        * @param certificates a <code>List</code> of <code>Certificate</code>s
  383        * @return a <code>CertPath</code> initialized with the supplied list of
  384        *   certificates
  385        * @exception CertificateException if an exception occurs
  386        * @since 1.4
  387        */
  388       public CertPath
  389           engineGenerateCertPath(List<? extends Certificate> certificates)
  390           throws CertificateException
  391       {
  392           return(new X509CertPath(certificates));
  393       }
  394   
  395       /**
  396        * Returns an iteration of the <code>CertPath</code> encodings supported
  397        * by this certificate factory, with the default encoding first.
  398        * <p>
  399        * Attempts to modify the returned <code>Iterator</code> via its
  400        * <code>remove</code> method result in an
  401        * <code>UnsupportedOperationException</code>.
  402        *
  403        * @return an <code>Iterator</code> over the names of the supported
  404        *         <code>CertPath</code> encodings (as <code>String</code>s)
  405        * @since 1.4
  406        */
  407       public Iterator<String> engineGetCertPathEncodings() {
  408           return(X509CertPath.getEncodingsStatic());
  409       }
  410   
  411       /**
  412        * Returns a (possibly empty) collection view of X.509 certificates read
  413        * from the given input stream <code>is</code>.
  414        *
  415        * @param is the input stream with the certificates.
  416        *
  417        * @return a (possibly empty) collection view of X.509 certificate objects
  418        * initialized with the data from the input stream.
  419        *
  420        * @exception CertificateException on parsing errors.
  421        */
  422       public Collection<? extends java.security.cert.Certificate>
  423               engineGenerateCertificates(InputStream is)
  424               throws CertificateException {
  425           if (is == null) {
  426               throw new CertificateException("Missing input stream");
  427           }
  428           try {
  429               if (is.markSupported() == false) {
  430                   // consume the entire input stream
  431                   is = new ByteArrayInputStream
  432                        (getTotalBytes(new BufferedInputStream(is)));
  433               }
  434               return parseX509orPKCS7Cert(is);
  435           } catch (IOException ioe) {
  436               throw new CertificateException(ioe);
  437           }
  438       }
  439   
  440       /**
  441        * Generates an X.509 certificate revocation list (CRL) object and
  442        * initializes it with the data read from the given input stream
  443        * <code>is</code>.
  444        *
  445        * @param is an input stream with the CRL data.
  446        *
  447        * @return an X.509 CRL object initialized with the data
  448        * from the input stream.
  449        *
  450        * @exception CRLException on parsing errors.
  451        */
  452       public CRL engineGenerateCRL(InputStream is)
  453           throws CRLException
  454       {
  455           if (is == null) {
  456               // clear the cache (for debugging)
  457               crlCache.clear();
  458               throw new CRLException("Missing input stream");
  459           }
  460           try {
  461               if (is.markSupported() == false) {
  462                   // consume the entire input stream
  463                   byte[] totalBytes;
  464                   totalBytes = getTotalBytes(new BufferedInputStream(is));
  465                   is = new ByteArrayInputStream(totalBytes);
  466               }
  467               byte[] encoding = readSequence(is);
  468               if (encoding != null) {
  469                   X509CRLImpl crl = (X509CRLImpl)getFromCache(crlCache, encoding);
  470                   if (crl != null) {
  471                       return crl;
  472                   }
  473                   crl = new X509CRLImpl(encoding);
  474                   addToCache(crlCache, crl.getEncodedInternal(), crl);
  475                   return crl;
  476               } else {
  477                   X509CRLImpl crl;
  478                   // determine if binary or Base64 encoding. If Base64 encoding,
  479                   // the CRL must be bounded at the beginning by
  480                   // "-----BEGIN".
  481                   if (isBase64(is)) {
  482                       // Base64
  483                       byte[] data = base64_to_binary(is);
  484                       crl = new X509CRLImpl(data);
  485                   } else {
  486                       // binary
  487                       crl = new X509CRLImpl(new DerValue(is));
  488                   }
  489                   return intern(crl);
  490               }
  491           } catch (IOException ioe) {
  492               throw new CRLException(ioe.getMessage());
  493           }
  494       }
  495   
  496       /**
  497        * Returns a (possibly empty) collection view of X.509 CRLs read
  498        * from the given input stream <code>is</code>.
  499        *
  500        * @param is the input stream with the CRLs.
  501        *
  502        * @return a (possibly empty) collection view of X.509 CRL objects
  503        * initialized with the data from the input stream.
  504        *
  505        * @exception CRLException on parsing errors.
  506        */
  507       public Collection<? extends java.security.cert.CRL> engineGenerateCRLs(InputStream
  508   is)
  509           throws CRLException
  510       {
  511           if (is == null) {
  512               throw new CRLException("Missing input stream");
  513           }
  514           try {
  515               if (is.markSupported() == false) {
  516                   // consume the entire input stream
  517                   is = new ByteArrayInputStream
  518                       (getTotalBytes(new BufferedInputStream(is)));
  519               }
  520               return parseX509orPKCS7CRL(is);
  521           } catch (IOException ioe) {
  522               throw new CRLException(ioe.getMessage());
  523           }
  524       }
  525   
  526       /*
  527        * Parses the data in the given input stream as a sequence of DER
  528        * encoded X.509 certificates (in binary or base 64 encoded format) OR
  529        * as a single PKCS#7 encoded blob (in binary or base64 encoded format).
  530        */
  531       private Collection<? extends java.security.cert.Certificate>
  532           parseX509orPKCS7Cert(InputStream is)
  533           throws CertificateException, IOException
  534       {
  535           Collection<X509CertImpl> coll = new ArrayList<X509CertImpl>();
  536           boolean first = true;
  537           while (is.available() != 0) {
  538               // determine if binary or Base64 encoding. If Base64 encoding,
  539               // each certificate must be bounded at the beginning by
  540               // "-----BEGIN".
  541               InputStream is2 = is;
  542               if (isBase64(is2)) {
  543                   // Base64
  544                   is2 = new ByteArrayInputStream(base64_to_binary(is2));
  545               }
  546               if (first)
  547                   is2.mark(is2.available());
  548               try {
  549                   // treat as X.509 cert
  550                   coll.add(intern(new X509CertImpl(new DerValue(is2))));
  551               } catch (CertificateException e) {
  552                   Throwable cause = e.getCause();
  553                   // only treat as PKCS#7 if this is the first cert parsed
  554                   // and the root cause of the decoding failure is an IOException
  555                   if (first && cause != null && (cause instanceof IOException)) {
  556                       // treat as PKCS#7
  557                       is2.reset();
  558                       PKCS7 pkcs7 = new PKCS7(is2);
  559                       X509Certificate[] certs = pkcs7.getCertificates();
  560                       // certs are optional in PKCS #7
  561                       if (certs != null) {
  562                           return Arrays.asList(certs);
  563                       } else {
  564                           // no certs provided
  565                           return new ArrayList<X509Certificate>(0);
  566                       }
  567                   } else {
  568                       throw e;
  569                   }
  570               }
  571               first = false;
  572           }
  573           return coll;
  574       }
  575   
  576       /*
  577        * Parses the data in the given input stream as a sequence of DER encoded
  578        * X.509 CRLs (in binary or base 64 encoded format) OR as a single PKCS#7
  579        * encoded blob (in binary or base 64 encoded format).
  580        */
  581       private Collection<? extends java.security.cert.CRL>
  582           parseX509orPKCS7CRL(InputStream is)
  583           throws CRLException, IOException
  584       {
  585           Collection<X509CRLImpl> coll = new ArrayList<X509CRLImpl>();
  586           boolean first = true;
  587           while (is.available() != 0) {
  588               // determine if binary or Base64 encoding. If Base64 encoding,
  589               // the CRL must be bounded at the beginning by
  590               // "-----BEGIN".
  591               InputStream is2 = is;
  592               if (isBase64(is)) {
  593                   // Base64
  594                   is2 = new ByteArrayInputStream(base64_to_binary(is2));
  595               }
  596               if (first)
  597                   is2.mark(is2.available());
  598               try {
  599                   // treat as X.509 CRL
  600                   coll.add(new X509CRLImpl(is2));
  601               } catch (CRLException e) {
  602                   // only treat as PKCS#7 if this is the first CRL parsed
  603                   if (first) {
  604                       is2.reset();
  605                       PKCS7 pkcs7 = new PKCS7(is2);
  606                       X509CRL[] crls = pkcs7.getCRLs();
  607                       // CRLs are optional in PKCS #7
  608                       if (crls != null) {
  609                           return Arrays.asList(crls);
  610                       } else {
  611                           // no crls provided
  612                           return new ArrayList<X509CRL>(0);
  613                       }
  614                   }
  615               }
  616               first = false;
  617           }
  618           return coll;
  619       }
  620   
  621       /*
  622        * Converts a Base64-encoded X.509 certificate or X.509 CRL or PKCS#7 data
  623        * to binary encoding.
  624        * In all cases, the data must be bounded at the beginning by
  625        * "-----BEGIN", and must be bounded at the end by "-----END".
  626        */
  627       private byte[] base64_to_binary(InputStream is)
  628           throws IOException
  629       {
  630           long len = 0; // total length of base64 encoding, including boundaries
  631   
  632           is.mark(is.available());
  633   
  634           BufferedInputStream bufin = new BufferedInputStream(is);
  635           BufferedReader br =
  636               new BufferedReader(new InputStreamReader(bufin, "ASCII"));
  637   
  638           // First read all of the data that is found between
  639           // the "-----BEGIN" and "-----END" boundaries into a buffer.
  640           String temp;
  641           if ((temp=readLine(br))==null || !temp.startsWith("-----BEGIN")) {
  642               throw new IOException("Unsupported encoding");
  643           } else {
  644               len += temp.length();
  645           }
  646           StringBuffer strBuf = new StringBuffer();
  647           while ((temp=readLine(br))!=null && !temp.startsWith("-----END")) {
  648               strBuf.append(temp);
  649           }
  650           if (temp == null) {
  651               throw new IOException("Unsupported encoding");
  652           } else {
  653               len += temp.length();
  654           }
  655   
  656           // consume only as much as was needed
  657           len += strBuf.length();
  658           is.reset();
  659           is.skip(len);
  660   
  661           // Now, that data is supposed to be a single X.509 certificate or
  662           // X.509 CRL or PKCS#7 formatted data... Base64 encoded.
  663           // Decode into binary and return the result.
  664           BASE64Decoder decoder = new BASE64Decoder();
  665           return decoder.decodeBuffer(strBuf.toString());
  666       }
  667   
  668       /*
  669        * Reads the entire input stream into a byte array.
  670        */
  671       private byte[] getTotalBytes(InputStream is) throws IOException {
  672           byte[] buffer = new byte[8192];
  673           ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
  674           int n;
  675           baos.reset();
  676           while ((n = is.read(buffer, 0, buffer.length)) != -1) {
  677               baos.write(buffer, 0, n);
  678           }
  679           return baos.toByteArray();
  680       }
  681   
  682       /*
  683        * Determines if input is binary or Base64 encoded.
  684        */
  685       private boolean isBase64(InputStream is) throws IOException {
  686           if (is.available() >= 10) {
  687               is.mark(10);
  688               int c1 = is.read();
  689               int c2 = is.read();
  690               int c3 = is.read();
  691               int c4 = is.read();
  692               int c5 = is.read();
  693               int c6 = is.read();
  694               int c7 = is.read();
  695               int c8 = is.read();
  696               int c9 = is.read();
  697               int c10 = is.read();
  698               is.reset();
  699               if (c1 == '-' && c2 == '-' && c3 == '-' && c4 == '-'
  700                   && c5 == '-' && c6 == 'B' && c7 == 'E' && c8 == 'G'
  701                   && c9 == 'I' && c10 == 'N') {
  702                   return true;
  703               } else {
  704                   return false;
  705               }
  706           } else {
  707               return false;
  708           }
  709       }
  710   
  711       /*
  712        * Read a line of text.  A line is considered to be terminated by any one
  713        * of a line feed ('\n'), a carriage return ('\r'), a carriage return
  714        * followed immediately by a linefeed, or an end-of-certificate marker.
  715        *
  716        * @return     A String containing the contents of the line, including
  717        *             any line-termination characters, or null if the end of the
  718        *             stream has been reached.
  719        */
  720       private String readLine(BufferedReader br) throws IOException {
  721           int c;
  722           int i = 0;
  723           boolean isMatch = true;
  724           boolean matched = false;
  725           StringBuffer sb = new StringBuffer(defaultExpectedLineLength);
  726           do {
  727               c = br.read();
  728               if (isMatch && (i < endBoundary.length)) {
  729                   isMatch = ((char)c != endBoundary[i++]) ? false : true;
  730               }
  731               if (!matched)
  732                   matched = (isMatch && (i == endBoundary.length));
  733               sb.append((char)c);
  734           } while ((c != -1) && (c != '\n') && (c != '\r'));
  735   
  736           if (!matched && c == -1) {
  737               return null;
  738           }
  739           if (c == '\r') {
  740               br.mark(1);
  741               int c2 = br.read();
  742               if (c2 == '\n') {
  743                   sb.append((char)c);
  744               } else {
  745                   br.reset();
  746               }
  747           }
  748           return sb.toString();
  749       }
  750   }

Save This Page
Home » openjdk-7 » sun.security » provider » [javadoc | source]