• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 /**
19 * @author Alexander V. Astapchuk
20 */
21 
22 package org.apache.harmony.security.tests.support;
23 
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.ObjectInputStream;
27 import java.io.ObjectOutputStream;
28 import java.io.Serializable;
29 import java.io.StreamCorruptedException;
30 import java.math.BigInteger;
31 
32 import java.security.InvalidKeyException;
33 import java.security.NoSuchAlgorithmException;
34 import java.security.NoSuchProviderException;
35 import java.security.Principal;
36 import java.security.Provider;
37 import java.security.PublicKey;
38 import java.security.Security;
39 import java.security.SignatureException;
40 
41 import java.security.cert.*;
42 import java.util.*;
43 
44 import javax.security.auth.x500.X500Principal;
45 
46 /**
47  * The class contains various utility methods used during the java.security
48  * classes testing.
49  *
50  */
51 
52 public final class TestCertUtils {
53 
TestCertUtils()54     private TestCertUtils() {
55         throw new Error("statics only");
56     }
57 
58     /**
59      * Returns new instance of test certificate each time the method is called.
60      *
61      * @return test certificate
62      */
getCert()63     public static Certificate getCert() {
64         return new TestCertificate();
65     }
66 
67     /**
68      * Returns an array of 3 test certificates. IMP: The array returned is not
69      * real chain of certificates, it's just an array of 3 certs. The method
70      * returns new array each time it's called. The number of 3 was chosen
71      * arbitrarily and is subject to change.
72      *
73      * @return an array of 3 certificates
74      */
getCertChain()75     public static Certificate[] getCertChain() {
76         Certificate[] chain = { new TestCertificate(), new TestCertificate(),
77                 new TestCertificate() };
78         return chain;
79     }
80 
81     /**
82      * Returns a test CertPath, which uses getCertChain() to obtain a list of
83      * certificates to store.
84      *
85      * @return test cert path
86      */
getCertPath()87     public static CertPath getCertPath() {
88         return new TestCertPath();
89     }
90 
91     /**
92      * Generates and returns an instance of TestCertPath.<br>
93      * TestCertificate-s included in the CertPath will be uniq (will have
94      * different numbers passed to their ctor-s).<br>
95      * The second arguments shows which number will have the first Certificate
96      * in the CertPath. The second certificate will have (startID+1) number
97      * and so on.
98      *
99      * @param howMany - shows how many TestCerts must contain the CertPath generated
100      * @param startID - specifies the starting ID which the first certificate will have
101      * @return TestCertPath
102      */
genCertPath(int howMany, int startID)103     public static CertPath genCertPath(int howMany, int startID) {
104         Certificate[] certs = new Certificate[howMany];
105         for (int i = 0; i < howMany; i++) {
106             certs[i] = new TestCertificate(Integer.toString(startID + i));
107         }
108         return new TestCertPath(certs);
109     }
110 
111     private static Provider provider = null;
112 
113     private static final String providerName = "TstPrvdr";
114 
115     /**
116      * A Principal used to form rootCA's certificate
117      */
118     public static final X500Principal rootPrincipal = new X500Principal(
119             UniGen.rootName);
120 
121     /**
122      * Some fake rootCA's certificate.
123      */
124     public static final X509Certificate rootCA = new TestX509Certificate(
125             rootPrincipal, rootPrincipal);
126 
install_test_x509_factory()127     public static void install_test_x509_factory() {
128         if (provider == null) {
129             provider = new TestProvider(providerName, 0.01,
130                     "Test provider for serialization testing");
131             Security.insertProviderAt(provider, 1);
132         }
133     }
134 
uninstall_test_x509_factory()135     public static void uninstall_test_x509_factory() {
136         if (provider != null) {
137             Security.removeProvider(providerName);
138             provider = null;
139         }
140     }
141 
142     /**
143      * The class represents test certificate path.
144      *
145      */
146 
147     public static final class TestCertPath extends CertPath implements
148             Serializable {
149 
150         private static final byte[] encoded = new byte[] { 1, 2, 3, 4, 5, 6, 7,
151                 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF };
152 
153         private static final String serializedData = "Just a dummy string to be serialized instead of real data";
154 
155         private Certificate[] certs;
156 
157         /**
158          * Default ctor for TestCertPath. Uses {@link TestCertUtils#getCertChain()}
159          * to obtain list of certificates.<br>
160          * All TestCertPath-s constructed via this ctor will be equals() to each
161          * other.
162          */
TestCertPath()163         public TestCertPath() {
164             super("testCertPath");
165             certs = getCertChain();
166         }
167 
168         /**
169          * Constructs TestCertPath and keeps the given array of certificates.<br>
170          * The TestCertPaths constructed via this ctor may be different (if they
171          * have different set of certificates)<br>
172          * @see TestCertUtils#genCertPath(int, int)
173          * @param certs
174          */
TestCertPath(Certificate[] certs)175         public TestCertPath(Certificate[] certs) {
176             super("testCertPath");
177             this.certs = certs;
178         }
179 
180         /**
181          * @see java.security.cert.CertPath#getCertificates()
182          */
getCertificates()183         public List getCertificates() {
184             return Arrays.asList(certs);
185         }
186 
187         /**
188          * @see java.security.cert.CertPath#getEncoded()
189          */
getEncoded()190         public byte[] getEncoded() throws CertificateEncodingException {
191             return encoded.clone();
192         }
193 
194         /**
195          * @see java.security.cert.CertPath#getEncoded(java.lang.String)
196          */
getEncoded(String encoding)197         public byte[] getEncoded(String encoding)
198                 throws CertificateEncodingException {
199             return encoded.clone();
200         }
201 
202         /**
203          * @see java.security.cert.CertPath#getEncodings()
204          */
getEncodings()205         public Iterator getEncodings() {
206             Vector v = new Vector();
207             v.add("myTestEncoding");
208             return v.iterator();
209         }
210 
toString()211         public String toString() {
212             StringBuffer buf = new StringBuffer(200);
213             buf.append("TestCertPath. certs count=");
214             if( certs == null ) {
215                 buf.append("0\n");
216             }
217             else {
218                 buf.append(certs.length).append("\n");
219                 for( int i=0; i<certs.length; i++) {
220                     buf.append("\t").append(i).append(" ");
221                     buf.append(certs[i]).append("\n");
222                 }
223             }
224             return buf.toString();
225         }
226 
227         /**
228          * Writes<br>
229          * (String) serializedData<br>
230          * (int) number of certificates in this CertPath<br>
231          * <array of certificates>
232          *
233          * @param out
234          * @throws IOException
235          */
writeObject(ObjectOutputStream out)236         private void writeObject(ObjectOutputStream out) throws IOException {
237             out.writeUTF(serializedData);
238             if (certs == null) {
239                 out.writeInt(0);
240             } else {
241                 out.writeInt(certs.length);
242                 for (int i = 0; i < certs.length; i++) {
243                     out.writeObject(certs[i]);
244                 }
245             }
246         }
247 
readObject(ObjectInputStream in)248         private void readObject(ObjectInputStream in) throws IOException,
249                 ClassNotFoundException {
250             String s = in.readUTF();
251             if (!serializedData.equals(s)) {
252                 throw new StreamCorruptedException("expect [" + serializedData
253                         + "] got [" + s + "]");
254             }
255             int count = in.readInt();
256             certs = new Certificate[count];
257             for (int i = 0; i < count; i++) {
258                 certs[i] = (Certificate) in.readObject();
259             }
260         }
261 
writeReplace()262         protected Object writeReplace() {
263             return this;
264         }
265 
readResolve()266         protected Object readResolve() {
267             return this;
268         }
269     }
270 
271     /**
272      * The class represents empty PublicKey.
273      *
274      */
275 
276     public static final class TestPublicKey implements PublicKey {
277         private static final String algo = "testPublicKeyAlgorithm";
278 
279         private static final byte[] encoded = new byte[] { 1, 2, 3, 4, 5, 6, 7,
280                 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF };
281 
282         private static final String format = "testPublicKeyFormat";
283 
getAlgorithm()284         public String getAlgorithm() {
285             return algo;
286         }
287 
getEncoded()288         public byte[] getEncoded() {
289             return encoded.clone();
290         }
291 
getFormat()292         public String getFormat() {
293             return format;
294         }
295     }
296 
297     /**
298      * The class represents test certificate.
299      *
300      */
301 
302     public static class TestCertificate extends Certificate implements
303             Serializable {
304 
305         private static final byte[] encoded = new byte[] { 1, 2, 3, 4, 5, 6, 7,
306                 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF };
307 
308         public static final String TYPE = "Test";
309 
310         //
311         // A String that makes different TestCertificates to be different.
312         //
313         private String diff = null;
314 
315         /**
316          * Default ctor. All the TestCertificate-s created with this ctor are equals() to each other.
317          * Use TestCertificate(String) if you need non equal TestCertificate-s.
318          */
TestCertificate()319         public TestCertificate() {
320             super(TYPE);
321         }
322 
323         /**
324          * A special purpose ctor. Pass different String-s to have different TestCertificates.
325          * TestCertificate-s with the same String passed to this ctor are considered equal.
326          */
TestCertificate(String diff)327         public TestCertificate(String diff) {
328             super(TYPE);
329             this.diff = diff;
330         }
331 
332         /**
333          * A ctor that allows to specify both the TYPE of certificate and the
334          * diff. Leave the <code>diff</code> null when no difference needed.
335          *
336          * @param diff
337          * @param type
338          */
TestCertificate(String diff, String type)339         public TestCertificate(String diff, String type) {
340             super(type);
341             this.diff = diff;
342         }
343 
getEncoded()344         public byte[] getEncoded() throws CertificateEncodingException {
345             return encoded.clone();
346         }
347 
verify(PublicKey key)348         public void verify(PublicKey key) throws CertificateException,
349                 NoSuchAlgorithmException, InvalidKeyException,
350                 NoSuchProviderException, SignatureException {
351             // do nothing
352         }
353 
verify(PublicKey key, String sigProvider)354         public void verify(PublicKey key, String sigProvider)
355                 throws CertificateException, NoSuchAlgorithmException,
356                 InvalidKeyException, NoSuchProviderException,
357                 SignatureException {
358             // do nothing
359 
360         }
361 
toString()362         public String toString() {
363             return "Test certificate - for unit testing only";
364         }
365 
equals(Object obj)366         public boolean equals(Object obj) {
367             if (obj == null || !(obj instanceof TestCertificate)) {
368                 return false;
369             }
370             TestCertificate that = (TestCertificate) obj;
371             if (this == that) {
372                 return true;
373             }
374             if (this.diff == null) {
375                 return that.diff == null;
376             }
377             return this.diff.equals(that.diff);
378         }
379 
getPublicKey()380         public PublicKey getPublicKey() {
381             return new TestPublicKey();
382         }
383 
384         /**
385          * Writes:<br>
386          * boolean - true if this certificate has a diff string,
387          * false otherwise, followed by <br>
388          * writeUTF() of string (if presented)
389          *
390          * @param out
391          * @throws IOException
392          */
writeObject(ObjectOutputStream out)393         private void writeObject(ObjectOutputStream out) throws IOException {
394             if (diff == null) {
395                 out.writeBoolean(false);
396             } else {
397                 out.writeBoolean(false);
398                 out.writeUTF(diff);
399             }
400         }
401 
readObject(ObjectInputStream in)402         private void readObject(ObjectInputStream in) throws IOException,
403                 ClassNotFoundException {
404             boolean hasDiffString = in.readBoolean();
405             if (hasDiffString) {
406                 diff = in.readUTF();
407             }
408         }
409 
writeReplace()410         protected Object writeReplace() {
411             return this;
412         }
413 
readResolve()414         protected Object readResolve() {
415             return this;
416         }
417     }
418 
419     public static class TestInvalidX509Certificate extends TestX509Certificate {
TestInvalidX509Certificate(X500Principal subj, X500Principal issuer)420         public TestInvalidX509Certificate(X500Principal subj,
421                 X500Principal issuer) {
422             super(subj, issuer);
423         }
424     }
425 
426     /**
427      *
428      * TestX509CErtificate.<br>
429      * Does nothing interesting, but<br>
430      * a) is not abstract, so it can be instantiated<br>
431      * b) returns Encoded form<br>
432      *
433      */
434     public static class TestX509Certificate extends X509Certificate {
435         private X500Principal subject;
436 
437         private X500Principal issuer;
438 
TestX509Certificate(X500Principal subj, X500Principal issuer)439         public TestX509Certificate(X500Principal subj, X500Principal issuer) {
440             this.subject = subj;
441             this.issuer = issuer;
442         }
443 
getIssuerX500Principal()444         public X500Principal getIssuerX500Principal() {
445             return issuer;
446         }
447 
getSubjectX500Principal()448         public X500Principal getSubjectX500Principal() {
449             return subject;
450         }
451 
452         /**
453          * The encoded for of this X509Certificate is a byte array where
454          * first are bytes of encoded form of Subject (as X500Principal),
455          * followed by one zero byte
456          * and followed by the encoded form of Issuer (as X500Principal)
457          *
458          */
getEncoded()459         public byte[] getEncoded() throws CertificateEncodingException {
460             byte[] asubj = subject.getEncoded();
461             byte[] aissuer = issuer.getEncoded();
462             byte[] data = new byte[asubj.length + aissuer.length + 1];
463 
464             System.arraycopy(asubj, 0, data, 0, asubj.length);
465             //data[asubj.length] = 0;
466             System
467                     .arraycopy(aissuer, 0, data, asubj.length + 1,
468                             aissuer.length);
469             return data;
470         }
471 
checkValidity()472         public void checkValidity() throws CertificateExpiredException,
473                 CertificateNotYetValidException {
474         }
475 
checkValidity(Date date)476         public void checkValidity(Date date)
477                 throws CertificateExpiredException,
478                 CertificateNotYetValidException {
479         }
480 
getBasicConstraints()481         public int getBasicConstraints() {
482             return 0;
483         }
484 
getIssuerDN()485         public Principal getIssuerDN() {
486             return null;
487         }
488 
getIssuerUniqueID()489         public boolean[] getIssuerUniqueID() {
490             return null;
491         }
492 
getKeyUsage()493         public boolean[] getKeyUsage() {
494             return null;
495         }
496 
getNotAfter()497         public Date getNotAfter() {
498             return null;
499         }
500 
getNotBefore()501         public Date getNotBefore() {
502             return null;
503         }
504 
getSerialNumber()505         public BigInteger getSerialNumber() {
506             return null;
507         }
508 
getSigAlgName()509         public String getSigAlgName() {
510             return null;
511         }
512 
getSigAlgOID()513         public String getSigAlgOID() {
514             return null;
515         }
516 
getSigAlgParams()517         public byte[] getSigAlgParams() {
518             return null;
519         }
520 
getSignature()521         public byte[] getSignature() {
522             return null;
523         }
524 
getSubjectDN()525         public Principal getSubjectDN() {
526             return null;
527         }
528 
getSubjectUniqueID()529         public boolean[] getSubjectUniqueID() {
530             return null;
531         }
532 
getTBSCertificate()533         public byte[] getTBSCertificate() throws CertificateEncodingException {
534             return null;
535         }
536 
getVersion()537         public int getVersion() {
538             return 0;
539         }
540 
getCriticalExtensionOIDs()541         public Set getCriticalExtensionOIDs() {
542             return null;
543         }
544 
getExtensionValue(String oid)545         public byte[] getExtensionValue(String oid) {
546             return null;
547         }
548 
getNonCriticalExtensionOIDs()549         public Set getNonCriticalExtensionOIDs() {
550             return null;
551         }
552 
hasUnsupportedCriticalExtension()553         public boolean hasUnsupportedCriticalExtension() {
554             return false;
555         }
556 
getPublicKey()557         public PublicKey getPublicKey() {
558             return null;
559         }
560 
toString()561         public String toString() {
562             return null;
563         }
564 
verify(PublicKey key, String sigProvider)565         public void verify(PublicKey key, String sigProvider)
566                 throws CertificateException, NoSuchAlgorithmException,
567                 InvalidKeyException, NoSuchProviderException,
568                 SignatureException {
569 
570         }
571 
verify(PublicKey key)572         public void verify(PublicKey key) throws CertificateException,
573                 NoSuchAlgorithmException, InvalidKeyException,
574                 NoSuchProviderException, SignatureException {
575 
576         }
577     }
578 
579     /**
580      * TestProvider. Does nothing, but pretends to
581      * implement X.509 CertificateFactory.
582      */
583     public static class TestProvider extends Provider {
584 
585         private Provider.Service serv;
586 
TestProvider(String name, double version, String info)587         public TestProvider(String name, double version, String info) {
588             super(name, version, info);
589             serv = new Provider.Service(this, "CertificateFactory", "X.509",
590                     TestFactorySpi.class.getName(), new ArrayList(), null);
591         }
592 
getServices()593         public synchronized Set getServices() {
594             HashSet s = new HashSet();
595             s.add(serv);
596             return s;
597         }
598     }
599 
600     /**
601      * Some kind of Certificate Factory, used during unit testing.
602      *
603      *
604      */
605     public static class TestFactorySpi extends CertificateFactorySpi {
606 
607         /**
608          * Tries to create an instance of TestX509Certificate, basing
609          * on the presumption that its {@link TestX509Certificate#getEncoded()
610          * encoded} form is stored.<br>
611          * @throws CertificateException is the presumption is not met or if
612          * any IO problem occurs.
613          */
engineGenerateCertificate(InputStream is)614         public Certificate engineGenerateCertificate(InputStream is)
615                 throws CertificateException {
616             byte[] data = new byte[0];
617             byte[] chunk = new byte[1024];
618             int len;
619             try {
620                 while ((len = is.read(chunk)) > 0) {
621                     byte[] tmp = new byte[data.length + len];
622                     System.arraycopy(data, 0, tmp, 0, data.length);
623                     System.arraycopy(chunk, 0, tmp, data.length, len);
624                     data = tmp;
625                 }
626             } catch (IOException ex) {
627                 throw new CertificateException("IO problem", ex);
628             }
629             int pos = Arrays.binarySearch(data, (byte) 0);
630             if (pos < 0) {
631                 throw new CertificateException("invalid format");
632             }
633             byte[] subjNameData = new byte[pos];
634             System.arraycopy(data, 0, subjNameData, 0, subjNameData.length);
635             byte[] issNameData = new byte[data.length - pos - 1];
636             System.arraycopy(data, pos + 1, issNameData, 0, issNameData.length);
637             X500Principal subjName = new X500Principal(subjNameData);
638             X500Principal issName = new X500Principal(issNameData);
639             return new TestX509Certificate(subjName, issName);
640         }
641 
642         /**
643          * Not supported yet.
644          * @throws UnsupportedOperationException
645          */
engineGenerateCertificates(InputStream inStream)646         public Collection engineGenerateCertificates(InputStream inStream)
647                 throws CertificateException {
648             throw new UnsupportedOperationException("not yet.");
649         }
650 
651         /**
652          * Not supported yet.
653          * @throws UnsupportedOperationException
654          */
engineGenerateCRL(InputStream inStream)655         public CRL engineGenerateCRL(InputStream inStream) throws CRLException {
656             throw new UnsupportedOperationException("not yet.");
657         }
658 
659         /**
660          * Not supported yet.
661          * @throws UnsupportedOperationException
662          */
engineGenerateCRLs(InputStream inStream)663         public Collection engineGenerateCRLs(InputStream inStream)
664                 throws CRLException {
665             throw new UnsupportedOperationException("not yet.");
666         }
667 
668         /**
669          * Returns an instance of TestCertPath.<br>
670          * @throws CertificateException if
671          * a) any of Certificates passed is not an instance of X509Certificate
672          * b) any of Certificates passed is an instance of TestInvalidX509Certificate
673          */
engineGenerateCertPath(List certs)674         public CertPath engineGenerateCertPath(List certs)
675                 throws CertificateException {
676             ArrayList validCerts = new ArrayList();
677             for (Iterator i = certs.iterator(); i.hasNext();) {
678                 Certificate c = (Certificate) i.next();
679                 if (!(c instanceof X509Certificate)) {
680                     throw new CertificateException("Not X509: " + c);
681                 }
682                 if (c instanceof TestInvalidX509Certificate) {
683                     throw new CertificateException("Invalid (test) X509: " + c);
684                 }
685                 validCerts.add(c);
686             }
687             Certificate[] acerts = new Certificate[validCerts.size()];
688             validCerts.toArray(acerts);
689             return new TestCertPath(acerts);
690         }
691     }
692 
693     /**
694      * Utility class used to generate some amount of uniq names.
695      */
696     public static class UniGen {
697         public static final String rootName = "CN=Alex Astapchuk, OU=SSG, O=Intel ZAO, C=RU";
698 
699         private static final String datasNames[] = { "CN", "OU", "O", "C" };
700 
701         private static final String datas[][] = {
702         // Names database
703                 { "Alex Astapchuk", null, null, null },
704                 { "John Doe", null, null, null },
705                 // 'organisation unit'-s
706                 { null, "SSG", null, null }, { null, "SSG/DRL", null, null },
707                 // organizations
708                 { null, null, "Intel ZAO", null },
709                 { null, null, "Intel Inc", null },
710                 // countries
711                 { null, null, null, "RU" }, { null, null, null, "US" },
712                 { null, null, null, "GB" }, { null, null, null, "JA" },
713                 { null, null, null, "KO" }, { null, null, null, "TW" }, };
714 
715         //
716         // Returns a string from <code>data</code> from a given column and
717         // position. The positions are looked for first non-null entry. If there
718         // are no non empty items left, then it scans column starting from the
719         // beginning.
720         //
721         // @param col
722         // @param startRow
723         // @return
724         //
getData(int col, int startRow)725         private static String getData(int col, int startRow) {
726             startRow = startRow % datas.length;
727             for (int i = startRow; i < datas.length; i++) {
728                 if (datas[i][col] != null) {
729                     return datas[i][col];
730                 }
731             }
732             // no non-null entries left, check from the beginning
733             for (int i = 0; i < datas.length; i++) {
734                 if (datas[i][col] != null) {
735                     return datas[i][col];
736                 }
737             }
738             // can't be
739             throw new Error();
740         }
741 
742         //
743         // Increments a num.<br>
744         // <code>num</code> is interpreted as a number with a base of
745         // <code>base</code> and each digit of this number is stored as a
746         // separate num's element.
747         //
748         // @param num
749         // @param base
750         // @return <b>true</b> if overflow happened
751         //
inc(int[] num, int base)752         private static boolean inc(int[] num, int base) {
753             for (int i = 0; i < num.length; i++) {
754                 if ((++num[i]) >= base) {
755                     num[i] = 0;
756                 } else {
757                     return false;
758                 }
759             }
760             return true;
761         }
762 
763         /**
764          * Generates some amount of uniq names, none of which is equals to
765          * {@link #rootName}.
766          * @param howMany
767          * @return
768          */
genNames(int howMany)769         public static String[] genNames(int howMany) {
770             int counts[] = new int[datasNames.length];
771             ArrayList al = new ArrayList();
772 
773             // not really the thrifty algorithm...
774             for (int i = 0; i < howMany;) {
775 
776                 //                System.out.print("#"+i+": ");
777                 //                for( int j=0; j<counts.length; j++) {
778                 //                    System.out.print(""+counts[j]+"|");
779                 //                }
780                 //                System.out.println();
781 
782                 StringBuffer buf = new StringBuffer();
783                 int j = 0;
784                 for (; j < datasNames.length - 1; j++) {
785                     String name = datasNames[j];
786                     String val = getData(j, counts[j]);
787                     buf.append(name).append('=').append(val).append(",");
788                 }
789                 String name = datasNames[j];
790                 String val = getData(j, counts[j]);
791                 buf.append(name).append('=').append(val);
792 
793                 name = buf.toString();
794 
795                 if (!(rootName.equals(name) || al.contains(name))) {
796                     ++i;
797                     al.add(name);
798                     //                    System.out.println("generated: "+name);
799                 } else {
800                     //                    System.out.println("rejected: "+name);
801                 }
802 
803                 if (inc(counts, datas.length)) {
804                     // if this happened, then just add some data into 'datas'
805                     throw new Error(
806                             "cant generate so many uniq names. sorry. add some more data.");
807                 }
808             }
809             return (String[]) al.toArray(new String[al.size()]);
810         }
811 
812         /**
813          * Generates some amount of uniq X500Principals, none of which is equals
814          * has a string equals to {@link #rootName}.
815          * @param howMany
816          * @return
817          */
genX500s(int howMany)818         public static X500Principal[] genX500s(int howMany) {
819             String names[] = genNames(howMany);
820             X500Principal[] ps = new X500Principal[howMany];
821             for (int i = 0; i < howMany; i++) {
822                 ps[i] = new X500Principal(names[i]);
823             }
824             return ps;
825         }
826 
827     }
828 
829 }
830 
831