View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.client.console.rest;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.util.ArrayList;
24  import java.util.LinkedHashMap;
25  import java.util.List;
26  import java.util.Map;
27  import javax.ws.rs.core.GenericType;
28  import javax.ws.rs.core.HttpHeaders;
29  import javax.ws.rs.core.Response;
30  import org.apache.commons.lang3.StringUtils;
31  import org.apache.cxf.jaxrs.client.Client;
32  import org.apache.cxf.jaxrs.client.WebClient;
33  import org.apache.syncope.client.lib.batch.BatchRequest;
34  import org.apache.syncope.client.ui.commons.status.StatusBean;
35  import org.apache.syncope.client.ui.commons.status.StatusUtils;
36  import org.apache.syncope.common.lib.request.ResourceAR;
37  import org.apache.syncope.common.lib.request.ResourceDR;
38  import org.apache.syncope.common.lib.request.StatusR;
39  import org.apache.syncope.common.lib.to.AnyTO;
40  import org.apache.syncope.common.lib.to.ProvisioningResult;
41  import org.apache.syncope.common.lib.types.ResourceAssociationAction;
42  import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
43  import org.apache.syncope.common.lib.types.StatusRType;
44  import org.apache.syncope.common.rest.api.RESTHeaders;
45  import org.apache.syncope.common.rest.api.batch.BatchPayloadParser;
46  import org.apache.syncope.common.rest.api.batch.BatchRequestItem;
47  import org.apache.syncope.common.rest.api.batch.BatchResponseItem;
48  import org.apache.syncope.common.rest.api.service.AnyService;
49  import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
50  
51  public abstract class AbstractAnyRestClient<TO extends AnyTO> extends BaseRestClient {
52  
53      private static final long serialVersionUID = 1962529678091410544L;
54  
55      protected abstract Class<? extends AnyService<TO>> getAnyServiceClass();
56  
57      public abstract int count(String realm, String fiql, String type);
58  
59      public abstract List<TO> search(String realm, String fiql, int page, int size, SortParam<String> sort, String type);
60  
61      public TO read(final String key) {
62          return getService(getAnyServiceClass()).read(key);
63      }
64  
65      public ProvisioningResult<TO> delete(final String etag, final String key) {
66          ProvisioningResult<TO> result;
67          synchronized (this) {
68              result = getService(etag, getAnyServiceClass()).delete(key).
69                      readEntity(new GenericType<>() {
70                      });
71              resetClient(getAnyServiceClass());
72          }
73          return result;
74      }
75  
76      protected List<BatchResponseItem> parseBatchResponse(final Response response) throws IOException {
77          return BatchPayloadParser.parse(
78                  (InputStream) response.getEntity(), response.getMediaType(), new BatchResponseItem());
79      }
80  
81      public Map<String, String> associate(
82              final ResourceAssociationAction action,
83              final String etag,
84              final String key,
85              final List<StatusBean> statuses) {
86  
87          Map<String, String> result = new LinkedHashMap<>();
88          synchronized (this) {
89              AnyService<?> service = getService(etag, getAnyServiceClass());
90              Client client = WebClient.client(service);
91              List<String> accept = client.getHeaders().get(HttpHeaders.ACCEPT);
92              if (!accept.contains(RESTHeaders.MULTIPART_MIXED)) {
93                  client.accept(RESTHeaders.MULTIPART_MIXED);
94              }
95  
96              StatusR statusR = StatusUtils.statusR(key, StatusRType.ACTIVATE, statuses);
97  
98              ResourceAR resourceAR = new ResourceAR.Builder().key(key).
99                      action(action).
100                     onSyncope(statusR.isOnSyncope()).
101                     resources(statusR.getResources()).build();
102             try {
103                 List<BatchResponseItem> items = parseBatchResponse(service.associate(resourceAR));
104                 for (int i = 0; i < items.size(); i++) {
105                     result.put(
106                             resourceAR.getResources().get(i),
107                             getStatus(items.get(i).getStatus()));
108                 }
109             } catch (IOException e) {
110                 LOG.error("While processing Batch response", e);
111             }
112 
113             resetClient(getAnyServiceClass());
114         }
115         return result;
116     }
117 
118     public Map<String, String> deassociate(
119             final ResourceDeassociationAction action,
120             final String etag,
121             final String key,
122             final List<StatusBean> statuses) {
123 
124         Map<String, String> result = new LinkedHashMap<>();
125         synchronized (this) {
126             AnyService<?> service = getService(etag, getAnyServiceClass());
127             Client client = WebClient.client(service);
128             List<String> accept = client.getHeaders().get(HttpHeaders.ACCEPT);
129             if (!accept.contains(RESTHeaders.MULTIPART_MIXED)) {
130                 client.accept(RESTHeaders.MULTIPART_MIXED);
131             }
132 
133             ResourceDR resourceDR = new ResourceDR.Builder().key(key).
134                     action(action).
135                     resources(StatusUtils.statusR(key, StatusRType.ACTIVATE, statuses).getResources()).build();
136             try {
137                 List<BatchResponseItem> items = parseBatchResponse(service.deassociate(resourceDR));
138                 for (int i = 0; i < items.size(); i++) {
139                     result.put(
140                             resourceDR.getResources().get(i),
141                             getStatus(items.get(i).getStatus()));
142                 }
143             } catch (IOException e) {
144                 LOG.error("While processing Batch response", e);
145             }
146 
147             resetClient(getAnyServiceClass());
148         }
149         return result;
150     }
151 
152     public Map<String, String> batch(final BatchRequest batchRequest) {
153         List<BatchRequestItem> batchRequestItems = new ArrayList<>(batchRequest.getItems());
154 
155         Map<String, String> result = new LinkedHashMap<>();
156         try {
157             List<BatchResponseItem> batchResponseItems = batchRequest.commit().getItems();
158             for (int i = 0; i < batchResponseItems.size(); i++) {
159                 String status = getStatus(batchResponseItems.get(i).getStatus());
160                 if (batchRequestItems.get(i).getRequestURI().endsWith("/status")) {
161                     result.put(StringUtils.substringAfterLast(
162                             StringUtils.substringBefore(batchRequestItems.get(i).getRequestURI(), "/status"), "/"),
163                             status);
164                 } else {
165                     result.put(StringUtils.substringAfterLast(
166                             batchRequestItems.get(i).getRequestURI(), "/"), status);
167                 }
168             }
169         } catch (IOException e) {
170             LOG.error("While processing Batch response", e);
171         }
172 
173         return result;
174     }
175 }