001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2016, Connect2id Ltd.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.jose;
019
020
021import com.nimbusds.jose.util.Base64URL;
022import net.jcip.annotations.ThreadSafe;
023
024import java.text.ParseException;
025
026
027/**
028 * Unsecured (plain / {@code alg=none}) JOSE object with
029 * <a href="https://datatracker.ietf.org/doc/html/rfc7515#section-7.1">compact
030 * serialisation</a>.
031 *
032 * <p>This class is thread-safe.
033 *
034 * @author Vladimir Dzhuvinov
035 * @version 2014-04-08
036 */
037@ThreadSafe
038public class PlainObject extends JOSEObject {
039
040
041        private static final long serialVersionUID = 1L;
042
043
044        /**
045         * The header.
046         */
047        private final PlainHeader header;
048
049
050        /**
051         * Creates a new unsecured JOSE object with a default {@link
052         * PlainHeader} and the specified payload.
053         *
054         * @param payload The payload. Must not be {@code null}.
055         */
056        public PlainObject(final Payload payload) {
057
058                if (payload == null) {
059                        throw new IllegalArgumentException("The payload must not be null");
060                }
061
062                setPayload(payload);
063
064                header = new PlainHeader();
065        }
066
067
068        /**
069         * Creates a new unsecured JOSE object with the specified header and
070         * payload.
071         *
072         * @param header  The unsecured header. Must not be {@code null}.
073         * @param payload The payload. Must not be {@code null}.
074         */
075        public PlainObject(final PlainHeader header, final Payload payload) {
076
077                if (header == null) {
078
079                        throw new IllegalArgumentException("The unsecured header must not be null");
080                }
081
082                this.header = header;
083
084                if (payload == null) {
085
086                        throw new IllegalArgumentException("The payload must not be null");
087                }
088
089                setPayload(payload);
090        }
091
092
093        /**
094         * Creates a new unsecured JOSE object with the specified
095         * Base64URL-encoded parts.
096         *
097         * @param firstPart  The first part, corresponding to the unsecured
098         *                   header. Must not be {@code null}.
099         * @param secondPart The second part, corresponding to the payload. 
100         *                   Must not be {@code null}.
101         *
102         * @throws ParseException If parsing of the serialised parts failed.
103         */
104        public PlainObject(final Base64URL firstPart, final Base64URL secondPart)
105                throws ParseException {
106
107                if (firstPart == null) {
108
109                        throw new IllegalArgumentException("The first part must not be null");
110                }
111
112                try {
113                        header = PlainHeader.parse(firstPart);
114
115                } catch (ParseException e) {
116
117                        throw new ParseException("Invalid unsecured header: " + e.getMessage(), 0);
118                }
119
120                if (secondPart == null) {
121
122                        throw new IllegalArgumentException("The second part must not be null");
123                }
124
125                setPayload(new Payload(secondPart));
126
127                setParsedParts(firstPart, secondPart, null);
128        }
129
130
131        @Override
132        public PlainHeader getHeader() {
133
134                return header;
135        }
136
137
138        /**
139         * Serialises this unsecured JOSE object to its compact format
140         * consisting of Base64URL-encoded parts delimited by period ('.') 
141         * characters.
142         *
143         * <pre>
144         * [header-base64url].[payload-base64url].[]
145         * </pre>
146         *
147         * @return The serialised unsecured JOSE object.
148         */
149        @Override
150        public String serialize() {
151
152                return header.toBase64URL().toString() + '.' + getPayload().toBase64URL().toString() + '.';
153        }
154
155
156        /**
157         * Parses an unsecured JOSE object from the specified string in compact
158         * format.
159         *
160         * @param s The string to parse. Must not be {@code null}.
161         *
162         * @return The unsecured JOSE object.
163         *
164         * @throws ParseException If the string couldn't be parsed to a valid 
165         *                        unsecured JOSE object.
166         */
167        public static PlainObject parse(final String s)
168                throws ParseException {
169
170                Base64URL[] parts = JOSEObject.split(s);
171
172                if (! parts[2].toString().isEmpty()) {
173                        
174                        throw new ParseException("Unexpected third Base64URL part", 0);
175                }
176
177                return new PlainObject(parts[0], parts[1]);
178        }
179}