001    package com.nimbusds.jose;
002    
003    
004    import java.text.ParseException;
005    
006    import javax.mail.internet.ContentType;
007    import javax.mail.internet.ParameterList;
008    
009    import net.jcip.annotations.ThreadSafe;
010    
011    import com.nimbusds.jose.util.Base64URL;
012    
013    
014    /**
015     * Plaintext (unsecured) JOSE object. This class is thread-safe.
016     *
017     * @author Vladimir Dzhuvinov
018     * @version $version$ (2013-05-04)
019     */
020    @ThreadSafe
021    public class PlainObject extends JOSEObject {
022    
023    
024            /**
025             * The MIME type of plain JOSE objects serialised to a compact form:
026             * {@code application/jws; charset=UTF-8}
027             */
028            public static final ContentType MIME_TYPE_COMPACT;
029    
030    
031            /**
032             * The MIME type of plain JOSE objects serialised to a JSON object 
033             * form: {@code application/jws-js; charset=UTF-8}
034             */
035            public static final ContentType MIME_TYPE_JS;
036    
037    
038            static {
039    
040                    final ParameterList params = new ParameterList();
041                    params.set("charset", "UTF-8");
042    
043                    MIME_TYPE_COMPACT = new ContentType("application", "jws", params);
044    
045                    MIME_TYPE_JS = new ContentType("application", "jws-js", params);
046            }
047    
048    
049            /**
050             * The header.
051             */
052            private final PlainHeader header;
053    
054    
055            /**
056             * Creates a new plaintext JOSE object with a default 
057             * {@link PlainHeader} and the specified payload.
058             *
059             * @param payload The payload. Must not be {@code null}.
060             */
061            public PlainObject(final Payload payload) {
062    
063                    if (payload == null) {
064    
065                            throw new IllegalArgumentException("The payload must not be null");
066                    }
067    
068                    setPayload(payload);
069    
070                    header = new PlainHeader();
071            }
072    
073    
074            /**
075             * Creates a new plaintext JOSE object with the specified header and 
076             * payload.
077             *
078             * @param header  The plaintext header. Must not be {@code null}.
079             * @param payload The payload. Must not be {@code null}.
080             */
081            public PlainObject(final PlainHeader header, final Payload payload) {
082    
083                    if (header == null) {
084    
085                            throw new IllegalArgumentException("The plain header must not be null");
086                    }
087    
088                    this.header = header;
089    
090                    if (payload == null) {
091    
092                            throw new IllegalArgumentException("The payload must not be null");
093                    }
094    
095                    setPayload(payload);
096            }
097    
098    
099            /**
100             * Creates a new plaintext JOSE object with the specified 
101             * Base64URL-encoded parts.
102             *
103             * @param firstPart  The first part, corresponding to the plaintext 
104             *                   header. Must not be {@code null}.
105             * @param secondPart The second part, corresponding to the payload. 
106             *                   Must not be {@code null}.
107             *
108             * @throws ParseException If parsing of the serialised parts failed.
109             */
110            public PlainObject(final Base64URL firstPart, final Base64URL secondPart)
111                            throws ParseException {
112    
113                    if (firstPart == null) {
114    
115                            throw new IllegalArgumentException("The first part must not be null");
116                    }
117    
118                    try {
119                            header = PlainHeader.parse(firstPart);
120    
121                    } catch (ParseException e) {
122    
123                            throw new ParseException("Invalid plain header: " + e.getMessage(), 0);
124                    }
125    
126                    if (secondPart == null) {
127    
128                            throw new IllegalArgumentException("The second part must not be null");
129                    }
130    
131                    setPayload(new Payload(secondPart));
132    
133                    setParsedParts(firstPart, secondPart, null);
134            }
135    
136    
137            @Override
138            public ReadOnlyPlainHeader getHeader() {
139    
140                    return header;
141            }
142    
143    
144            /**
145             * Serialises this plaintext JOSE object to its compact format 
146             * consisting of Base64URL-encoded parts delimited by period ('.') 
147             * characters.
148             *
149             * <pre>
150             * [header-base64url].[payload-base64url].[]
151             * </pre>
152             *
153             * @return The serialised plaintext JOSE object.
154             */
155            @Override
156            public String serialize() {
157    
158                    StringBuilder sb = new StringBuilder(header.toBase64URL().toString());
159                    sb.append('.');
160                    sb.append(getPayload().toBase64URL().toString());
161                    sb.append('.');
162                    return sb.toString();
163            }
164    
165    
166            /**
167             * Parses a plaintext JOSE object from the specified string in compact 
168             * format.
169             *
170             * @param s The string to parse. Must not be {@code null}.
171             *
172             * @return The plain JOSE object.
173             *
174             * @throws ParseException If the string couldn't be parsed to a valid 
175             *                        plaintext JOSE object.
176             */
177            public static PlainObject parse(final String s)
178                            throws ParseException {
179    
180                    Base64URL[] parts = JOSEObject.split(s);
181    
182                    if (! parts[2].toString().isEmpty()) {
183                            
184                            throw new ParseException("Unexpected third Base64URL part", 0);
185                    }
186    
187                    return new PlainObject(parts[0], parts[1]);
188            }
189    }