001package org.apache.commons.ssl.org.bouncycastle.asn1.dvcs; 002 003import java.math.BigInteger; 004 005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Encodable; 006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector; 007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer; 008import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence; 009import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject; 010import org.apache.commons.ssl.org.bouncycastle.asn1.x509.Extensions; 011import org.apache.commons.ssl.org.bouncycastle.asn1.x509.GeneralName; 012import org.apache.commons.ssl.org.bouncycastle.asn1.x509.GeneralNames; 013import org.apache.commons.ssl.org.bouncycastle.asn1.x509.PolicyInformation; 014import org.bouncycastle.util.BigIntegers; 015 016/** 017 * <pre> 018 * DVCSRequestInformation ::= SEQUENCE { 019 * version INTEGER DEFAULT 1 , 020 * service ServiceType, 021 * nonce Nonce OPTIONAL, 022 * requestTime DVCSTime OPTIONAL, 023 * requester [0] GeneralNames OPTIONAL, 024 * requestPolicy [1] PolicyInformation OPTIONAL, 025 * dvcs [2] GeneralNames OPTIONAL, 026 * dataLocations [3] GeneralNames OPTIONAL, 027 * extensions [4] IMPLICIT Extensions OPTIONAL 028 * } 029 * </pre> 030 */ 031public class DVCSRequestInformationBuilder 032{ 033 private int version = DEFAULT_VERSION; 034 035 private final ServiceType service; 036 private DVCSRequestInformation initialInfo; 037 038 private BigInteger nonce; 039 private DVCSTime requestTime; 040 private GeneralNames requester; 041 private PolicyInformation requestPolicy; 042 private GeneralNames dvcs; 043 private GeneralNames dataLocations; 044 private Extensions extensions; 045 046 private static final int DEFAULT_VERSION = 1; 047 private static final int TAG_REQUESTER = 0; 048 private static final int TAG_REQUEST_POLICY = 1; 049 private static final int TAG_DVCS = 2; 050 private static final int TAG_DATA_LOCATIONS = 3; 051 private static final int TAG_EXTENSIONS = 4; 052 053 public DVCSRequestInformationBuilder(ServiceType service) 054 { 055 this.service = service; 056 } 057 058 public DVCSRequestInformationBuilder(DVCSRequestInformation initialInfo) 059 { 060 this.initialInfo = initialInfo; 061 this.service = initialInfo.getService(); 062 this.version = initialInfo.getVersion(); 063 this.nonce = initialInfo.getNonce(); 064 this.requestTime = initialInfo.getRequestTime(); 065 this.requestPolicy = initialInfo.getRequestPolicy(); 066 this.dvcs = initialInfo.getDVCS(); 067 this.dataLocations = initialInfo.getDataLocations(); 068 } 069 070 public DVCSRequestInformation build() 071 { 072 ASN1EncodableVector v = new ASN1EncodableVector(); 073 074 if (version != DEFAULT_VERSION) 075 { 076 v.add(new ASN1Integer(version)); 077 } 078 v.add(service); 079 if (nonce != null) 080 { 081 v.add(new ASN1Integer(nonce)); 082 } 083 if (requestTime != null) 084 { 085 v.add(requestTime); 086 } 087 088 int[] tags = new int[]{ 089 TAG_REQUESTER, 090 TAG_REQUEST_POLICY, 091 TAG_DVCS, 092 TAG_DATA_LOCATIONS, 093 TAG_EXTENSIONS 094 }; 095 ASN1Encodable[] taggedObjects = new ASN1Encodable[]{ 096 requester, 097 requestPolicy, 098 dvcs, 099 dataLocations, 100 extensions 101 }; 102 for (int i = 0; i < tags.length; i++) 103 { 104 int tag = tags[i]; 105 ASN1Encodable taggedObject = taggedObjects[i]; 106 if (taggedObject != null) 107 { 108 v.add(new DERTaggedObject(false, tag, taggedObject)); 109 } 110 } 111 112 return DVCSRequestInformation.getInstance(new DERSequence(v)); 113 } 114 115 public void setVersion(int version) 116 { 117 if (initialInfo != null) 118 { 119 throw new IllegalStateException("cannot change version in existing DVCSRequestInformation"); 120 } 121 122 this.version = version; 123 } 124 125 public void setNonce(BigInteger nonce) 126 { 127 // RFC 3029, 9.1: The DVCS MAY modify the fields 128 // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure 129 130 // RFC 3029, 9.1: The only modification 131 // allowed to a 'nonce' is the inclusion of a new field if it was not 132 // present, or to concatenate other data to the end (right) of an 133 // existing value. 134 if (initialInfo != null) 135 { 136 if (initialInfo.getNonce() == null) 137 { 138 this.nonce = nonce; 139 } 140 else 141 { 142 byte[] initialBytes = initialInfo.getNonce().toByteArray(); 143 byte[] newBytes = BigIntegers.asUnsignedByteArray(nonce); 144 byte[] nonceBytes = new byte[initialBytes.length + newBytes.length]; 145 146 System.arraycopy(initialBytes, 0, nonceBytes, 0, initialBytes.length); 147 System.arraycopy(newBytes, 0, nonceBytes, initialBytes.length, newBytes.length); 148 149 this.nonce = new BigInteger(nonceBytes); 150 } 151 } 152 153 this.nonce = nonce; 154 } 155 156 public void setRequestTime(DVCSTime requestTime) 157 { 158 if (initialInfo != null) 159 { 160 throw new IllegalStateException("cannot change request time in existing DVCSRequestInformation"); 161 } 162 163 this.requestTime = requestTime; 164 } 165 166 public void setRequester(GeneralName requester) 167 { 168 this.setRequester(new GeneralNames(requester)); 169 } 170 171 public void setRequester(GeneralNames requester) 172 { 173 // RFC 3029, 9.1: The DVCS MAY modify the fields 174 // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure 175 176 this.requester = requester; 177 } 178 179 public void setRequestPolicy(PolicyInformation requestPolicy) 180 { 181 if (initialInfo != null) 182 { 183 throw new IllegalStateException("cannot change request policy in existing DVCSRequestInformation"); 184 } 185 186 this.requestPolicy = requestPolicy; 187 } 188 189 public void setDVCS(GeneralName dvcs) 190 { 191 this.setDVCS(new GeneralNames(dvcs)); 192 } 193 194 public void setDVCS(GeneralNames dvcs) 195 { 196 // RFC 3029, 9.1: The DVCS MAY modify the fields 197 // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure 198 199 this.dvcs = dvcs; 200 } 201 202 public void setDataLocations(GeneralName dataLocation) 203 { 204 this.setDataLocations(new GeneralNames(dataLocation)); 205 } 206 207 public void setDataLocations(GeneralNames dataLocations) 208 { 209 // RFC 3029, 9.1: The DVCS MAY modify the fields 210 // 'dvcs', 'requester', 'dataLocations', and 'nonce' of the ReqInfo structure 211 212 this.dataLocations = dataLocations; 213 } 214 215 public void setExtensions(Extensions extensions) 216 { 217 if (initialInfo != null) 218 { 219 throw new IllegalStateException("cannot change extensions in existing DVCSRequestInformation"); 220 } 221 222 this.extensions = extensions; 223 } 224}