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