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}