001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2020, Connect2id Ltd and contributors.
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.openid.connect.sdk.federation.api;
019
020
021import java.net.URI;
022import java.util.Collections;
023import java.util.LinkedHashMap;
024import java.util.List;
025import java.util.Map;
026
027import net.jcip.annotations.Immutable;
028
029import com.nimbusds.oauth2.sdk.ParseException;
030import com.nimbusds.oauth2.sdk.http.HTTPRequest;
031import com.nimbusds.oauth2.sdk.id.Issuer;
032import com.nimbusds.oauth2.sdk.util.MultivaluedMapUtils;
033import com.nimbusds.oauth2.sdk.util.StringUtils;
034
035
036/**
037 * Entity listing request.
038 *
039 * <p>Related specifications:
040 *
041 * <ul>
042 *     <li>OpenID Connect Federation 1.0, section 6.3.1.
043 * </ul>
044 */
045@Immutable
046public class EntityListingRequest extends FederationAPIRequest {
047        
048        
049        /**
050         * The issuer.
051         */
052        private final Issuer issuer;
053        
054        
055        private final EntityListingSpec listingSpec;
056        
057        
058        /**
059         * Creates a new entity listing request.
060         *
061         * @param endpoint    The federation API endpoint. Must not be
062         *                    {@code null}.
063         * @param issuer      The issuer entity identifier. Must not be
064         *                    {@code null}.
065         * @param listingSpec The entity listing spec. Must not be
066         *                    {@code null}.
067         */
068        public EntityListingRequest(final URI endpoint, final Issuer issuer, final EntityListingSpec listingSpec) {
069                super(endpoint, OperationType.LISTING);
070                if (issuer == null) {
071                        throw new IllegalArgumentException("The issuer must not be null");
072                }
073                this.issuer = issuer;
074                if (listingSpec == null) {
075                        throw new IllegalArgumentException("The listing spec must not be null");
076                }
077                this.listingSpec = listingSpec;
078        }
079        
080        
081        /**
082         * Returns the issuer.
083         *
084         * @return The issuer.
085         */
086        public Issuer getIssuer() {
087                return issuer;
088        }
089        
090        
091        /**
092         * Returns the federation entity listing spec.
093         *
094         * @return The listing spec.
095         */
096        public EntityListingSpec getListingSpec() {
097                return listingSpec;
098        }
099        
100        
101        @Override
102        public Map<String, List<String>> toParameters() {
103                Map<String, List<String>> params = new LinkedHashMap<>();
104                params.put("operation", Collections.singletonList(getOperationType().getValue()));
105                params.put("iss", Collections.singletonList(getIssuer().getValue()));
106                switch (getListingSpec()) {
107                        case LEAF_ENTITIES_ONLY:
108                                params.put("is_leaf", Collections.singletonList("true"));
109                                break;
110                        case INTERMEDIATES_ONLY:
111                                params.put("is_leaf", Collections.singletonList("false"));
112                                break;
113                        case ALL:
114                                // no output
115                }
116                return params;
117        }
118        
119        
120        /**
121         * Parses an entity listing request from the specified query string
122         * parameters.
123         *
124         * @param params The query string parameters. Must not be {@code null}.
125         *
126         * @return The entity listing request.
127         *
128         * @throws ParseException If parsing failed.
129         */
130        public static EntityListingRequest parse(final Map<String, List<String>> params)
131                throws ParseException {
132                
133                String value = MultivaluedMapUtils.getFirstValue(params, "operation");
134                if (StringUtils.isBlank(value)) {
135                        throw new ParseException("Missing operation type");
136                }
137                if (! OperationType.LISTING.getValue().equals(value)) {
138                        throw new ParseException("The operation type must be listing");
139                }
140                
141                value = MultivaluedMapUtils.getFirstValue(params, "iss");
142                if (value == null) {
143                        throw new ParseException("Missing iss (issuer) parameter");
144                }
145                Issuer issuer = new Issuer(value);
146                
147                value = MultivaluedMapUtils.getFirstValue(params, "is_leaf");
148                EntityListingSpec listingSpec = EntityListingSpec.ALL;
149                if ("true".equals(value)) {
150                        listingSpec = EntityListingSpec.LEAF_ENTITIES_ONLY;
151                } else if ("false".equals(value)) {
152                        listingSpec = EntityListingSpec.INTERMEDIATES_ONLY;
153                }
154                
155                return new EntityListingRequest(null, issuer, listingSpec);
156        }
157        
158        
159        /**
160         * Parses an entity listing request from the specified HTTP request.
161         *
162         * @param httpRequest The HTTP request. Must not be {@code null}.
163         *
164         * @return The entity listing request.
165         *
166         * @throws ParseException If parsing failed.
167         */
168        public static EntityListingRequest parse(final HTTPRequest httpRequest)
169                throws ParseException {
170                
171                httpRequest.ensureMethod(HTTPRequest.Method.GET);
172                EntityListingRequest request = parse(httpRequest.getQueryParameters());
173                return new EntityListingRequest(httpRequest.getURI(), request.getIssuer(), request.getListingSpec());
174        }
175}