1717import com .sap .cloud .security .config .ClientCredentials ;
1818import java .io .IOException ;
1919import java .io .UnsupportedEncodingException ;
20+ import java .util .ArrayList ;
21+ import java .util .List ;
2022import org .apache .http .client .HttpClient ;
2123import org .apache .http .client .methods .CloseableHttpResponse ;
2224import org .apache .http .client .methods .HttpDelete ;
@@ -35,50 +37,147 @@ public class SDMAdminServiceImpl implements SDMAdminService {
3537 @ java .lang .Override
3638 public String onboardRepository (Repository repository )
3739 throws JsonProcessingException , UnsupportedEncodingException {
38- SDMCredentials sdmCredentials = tokenHandler .getSDMCredentials ();
39- var httpClient =
40- tokenHandler .getHttpClient (
41- null , null , repository .getSubdomain (), "TECHNICAL_CREDENTIALS_FLOW" );
40+ if (repository == null ) {
41+ logger .error ("Repository object is null. Cannot proceed with onboarding." );
42+ throw new IllegalArgumentException ("Repository object cannot be null." );
43+ }
44+
45+ SDMCredentials sdmCredentials ;
46+ try {
47+ sdmCredentials = tokenHandler .getSDMCredentials ();
48+ if (sdmCredentials == null || sdmCredentials .getUrl () == null ) {
49+ logger .error ("SDM credentials are missing or invalid." );
50+ throw new ServiceException ("SDM credentials are missing or invalid." );
51+ }
52+ } catch (Exception e ) {
53+ logger .error ("Failed to retrieve SDM credentials: " + e .getMessage ());
54+ throw new ServiceException ("Failed to retrieve SDM credentials." , e );
55+ }
56+
57+ HttpClient httpClient = null ;
58+ try {
59+ httpClient =
60+ tokenHandler .getHttpClient (
61+ null , null , repository .getSubdomain (), "TECHNICAL_CREDENTIALS_FLOW" );
62+ if (httpClient == null ) {
63+ logger .error ("Failed to create HTTP client." );
64+ throw new ServiceException ("Failed to create HTTP client." );
65+ }
66+ } catch (Exception e ) {
67+ logger .error ("Error while creating HTTP client: " + e .getMessage ());
68+ throw new ServiceException ("Error while creating HTTP client." , e );
69+ }
70+
4271 String sdmUrl = sdmCredentials .getUrl () + SDMConstants .REST_V2_REPOSITORIES ;
4372 HttpPost onboardingReq = new HttpPost (sdmUrl );
4473 ObjectMapper objectMapper = new ObjectMapper ();
4574 RepositoryBody onboardRepository = new RepositoryBody ();
46- repository .setExternalId (REPOSITORY_ID );
47- onboardRepository .setRepository (repository );
48- String json = objectMapper .writeValueAsString (onboardRepository );
49- StringEntity entity = new StringEntity (json );
75+
76+ try {
77+ repository .setExternalId (REPOSITORY_ID );
78+ onboardRepository .setRepository (repository );
79+ } catch (Exception e ) {
80+ logger .error ("Failed to set repository details: " + e .getMessage ());
81+ throw new ServiceException ("Failed to set repository details." , e );
82+ }
83+
84+ String json ;
85+ try {
86+ json = objectMapper .writeValueAsString (onboardRepository );
87+ } catch (JsonProcessingException e ) {
88+ logger .error ("Failed to serialize repository object to JSON: " + e .getMessage ());
89+ throw new ServiceException ("Failed to serialize repository object to JSON." , e );
90+ }
91+
92+ StringEntity entity ;
93+ try {
94+ entity = new StringEntity (json );
95+ } catch (UnsupportedEncodingException e ) {
96+ logger .error ("Failed to create StringEntity: " + e .getMessage ());
97+ throw new ServiceException ("Failed to create StringEntity." , e );
98+ }
99+
50100 onboardingReq .setEntity (entity );
51- // Set the content type of the request
52101 onboardingReq .setHeader ("Content-Type" , "application/json" );
102+
53103 try (var response = (CloseableHttpResponse ) httpClient .execute (onboardingReq )) {
54104 String responseString = EntityUtils .toString (response .getEntity ());
105+
55106 if ((responseString .contains (REPOSITORY_ID + " already exists" ))
56107 && response .getStatusLine ().getStatusCode () == 409 ) {
57108 return String .format (
58109 SDMConstants .REPOSITORY_ALREADY_EXIST , repository .getDisplayName (), REPOSITORY_ID );
59110 }
60- JsonObject jsonObject = JsonParser .parseString (responseString ).getAsJsonObject ();
61- String repositoryId = jsonObject .get ("id" ).getAsString ();
111+
112+ JsonObject jsonObject ;
113+ jsonObject = JsonParser .parseString (responseString ).getAsJsonObject ();
114+
115+ String repositoryId ;
116+ if (jsonObject .has ("id" ) && !jsonObject .get ("id" ).isJsonNull ()) {
117+ repositoryId = jsonObject .get ("id" ).getAsString ();
118+ } else {
119+ logger .error (
120+ String .format (SDMConstants .ONBOARD_REPO_ERROR_MESSAGE , repository .getDisplayName ())
121+ + " : "
122+ + responseString );
123+ throw new ServiceException (
124+ String .format (SDMConstants .ONBOARD_REPO_ERROR_MESSAGE , repository .getDisplayName ()),
125+ responseString );
126+ }
127+
62128 return String .format (
63129 SDMConstants .ONBOARD_REPO_MESSAGE , repository .getDisplayName (), repositoryId );
64- } catch (IOException e ) {
130+ } catch (Exception e ) {
131+ logger .error (
132+ String .format (SDMConstants .ONBOARD_REPO_ERROR_MESSAGE , repository .getDisplayName ())
133+ + " : "
134+ + e .getMessage ());
65135 throw new ServiceException (
66- String .format (SDMConstants .ONBOARD_REPO_ERROR_MESSAGE , repository .getDisplayName ()),
67- e .getMessage ());
136+ String .format (SDMConstants .ONBOARD_REPO_ERROR_MESSAGE , repository .getDisplayName ()), e );
68137 }
69138 }
70139
71140 @ java .lang .Override
72141 public String offboardRepository (String subdomain ) {
73- SDMCredentials sdmCredentials = tokenHandler .getSDMCredentials ();
74- ClientCredentials clientCredentials =
75- new ClientCredentials (sdmCredentials .getClientId (), sdmCredentials .getClientSecret ());
142+ SDMCredentials sdmCredentials ;
143+ try {
144+ sdmCredentials = tokenHandler .getSDMCredentials ();
145+ if (sdmCredentials == null
146+ || sdmCredentials .getUrl () == null
147+ || sdmCredentials .getBaseTokenUrl () == null ) {
148+ logger .error ("SDM credentials are missing or invalid." );
149+ throw new ServiceException ("SDM credentials are missing or invalid." );
150+ }
151+ } catch (Exception e ) {
152+ logger .error ("Failed to retrieve SDM credentials: " + e .getMessage ());
153+ throw new ServiceException ("Failed to retrieve SDM credentials." , e );
154+ }
155+
156+ ClientCredentials clientCredentials ;
157+ try {
158+ clientCredentials =
159+ new ClientCredentials (sdmCredentials .getClientId (), sdmCredentials .getClientSecret ());
160+ if (clientCredentials .getId () == null || clientCredentials .getSecret () == null ) {
161+ logger .error ("Client credentials are missing or invalid." );
162+ throw new ServiceException ("Client credentials are missing or invalid." );
163+ }
164+ } catch (Exception e ) {
165+ logger .error ("Failed to create client credentials: " + e .getMessage ());
166+ throw new ServiceException ("Failed to create client credentials." , e );
167+ }
168+
76169 String baseTokenUrl = sdmCredentials .getBaseTokenUrl ();
77- if (subdomain != null && !subdomain .equals ("" )) {
78- String providersubdomain =
79- baseTokenUrl .substring (baseTokenUrl .indexOf ("/" ) + 2 , baseTokenUrl .indexOf ("." ));
80- baseTokenUrl = baseTokenUrl .replace (providersubdomain , subdomain );
170+ if (subdomain != null && !subdomain .isEmpty ()) {
171+ try {
172+ String providersubdomain =
173+ baseTokenUrl .substring (baseTokenUrl .indexOf ("/" ) + 2 , baseTokenUrl .indexOf ("." ));
174+ baseTokenUrl = baseTokenUrl .replace (providersubdomain , subdomain );
175+ } catch (Exception e ) {
176+ logger .error ("Failed to replace subdomain in base token URL: " + e .getMessage ());
177+ throw new ServiceException ("Failed to replace subdomain in base token URL." , e );
178+ }
81179 }
180+
82181 var destination =
83182 OAuth2DestinationBuilder .forTargetUrl (sdmCredentials .getUrl ())
84183 .withTokenEndpoint (baseTokenUrl )
@@ -92,44 +191,84 @@ public String offboardRepository(String subdomain) {
92191 builder .maxConnectionsPerRoute (SDMConstants .MAX_CONNECTIONS_PER_ROUTE );
93192 builder .maxConnectionsTotal (SDMConstants .MAX_CONNECTIONS_TOTAL );
94193 DefaultHttpClientFactory factory = builder .build ();
95- HttpClient httpClient = factory .createHttpClient (destination );
194+ HttpClient httpClient ;
195+ try {
196+ httpClient = factory .createHttpClient (destination );
197+ if (httpClient == null ) {
198+ logger .error ("Failed to create HTTP client." );
199+ throw new ServiceException ("Failed to create HTTP client." );
200+ }
201+ } catch (Exception e ) {
202+ logger .error ("Error while creating HTTP client: " + e .getMessage ());
203+ throw new ServiceException ("Error while creating HTTP client." , e );
204+ }
205+
96206 String sdmUrl = sdmCredentials .getUrl () + SDMConstants .REST_V2_REPOSITORIES + "/" ;
97207 HttpGet getRepos = new HttpGet (sdmUrl );
98208 String repoId = "" ;
99209 try (var response = (CloseableHttpResponse ) httpClient .execute (getRepos )) {
100- repoId = getRepositoryId (EntityUtils .toString (response .getEntity ()));
210+ String responseString = EntityUtils .toString (response .getEntity ());
211+ repoId = getRepositoryId (responseString );
212+ if (repoId == null || repoId .isEmpty ()) {
213+ logger .error ("Repository ID not found" );
214+ return "Repository with ID " + SDMConstants .REPOSITORY_ID + " not found." ;
215+ }
101216 } catch (IOException e ) {
102- logger .error ("Error in offboarding repository : " + e .getMessage ());
103- throw new ServiceException ("Error in offboarding " , e .getMessage ());
217+ logger .error ("Error while fetching repository ID: " + e .getMessage ());
218+ throw new ServiceException ("Error while fetching repository ID." , e );
219+ } catch (Exception e ) {
220+ logger .error ("Unexpected error while fetching repository ID: " + e .getMessage ());
221+ throw new ServiceException ("Unexpected error while fetching repository ID." , e );
104222 }
223+
105224 sdmUrl = sdmCredentials .getUrl () + SDMConstants .REST_V2_REPOSITORIES + "/" + repoId ;
106225 HttpDelete offboardingReq = new HttpDelete (sdmUrl );
107- // Set the content type of the request
108226 offboardingReq .setHeader ("Content-Type" , "application/json" );
109227 try (var response = (CloseableHttpResponse ) httpClient .execute (offboardingReq )) {
110- logger .info ("Repository <" + REPOSITORY_ID + "> Offboarded" );
111- return "Repository <" + REPOSITORY_ID + "> Offboarded" ;
228+ int statusCode = response .getStatusLine ().getStatusCode ();
229+ String responseString = EntityUtils .toString (response .getEntity ());
230+
231+ if (statusCode != 200 ) { // Failed to offboard
232+ if (statusCode == 404 ) { // Exception isn't thrown in case of missing repository
233+ logger .warn ("Repository with ID " + SDMConstants .REPOSITORY_ID + " not found." );
234+ return "Repository with ID " + SDMConstants .REPOSITORY_ID + " not found." ;
235+ }
236+ logger .error ("Failed to offboard repository : " + responseString );
237+ throw new ServiceException ("Failed to offboard repository." , responseString );
238+ }
239+
240+ logger .info ("Repository " + repoId + " Offboarded" );
241+ return "Repository " + repoId + " Offboarded" ;
112242 } catch (IOException e ) {
113- logger .error ("Error in offboarding repository : " + e .getMessage ());
114- throw new ServiceException ("Error in offboarding " , e .getMessage ());
243+ logger .error ("Error while offboarding repository: " + e .getMessage ());
244+ throw new ServiceException ("Error while offboarding repository." , e );
245+ } catch (Exception e ) {
246+ logger .error ("Unexpected error while offboarding repository: " + e .getMessage ());
247+ throw new ServiceException ("Unexpected error while offboarding repository." , e );
115248 }
116249 }
117250
118251 private String getRepositoryId (String jsonString ) {
119252 ObjectMapper objectMapper = new ObjectMapper ();
120253 try {
121254 JsonNode rootNode = objectMapper .readTree (jsonString );
122- JsonNode repoInfos = rootNode .path ("repoAndConnectionInfos" );
255+ JsonNode repoInfosNode = rootNode .path ("repoAndConnectionInfos" );
256+
257+ List <JsonNode > repoInfos = new ArrayList <>();
258+ if (repoInfosNode .isArray ()) {
259+ repoInfosNode .forEach (repoInfos ::add );
260+ } else if (!repoInfosNode .isMissingNode () && !repoInfosNode .isNull ()) {
261+ repoInfos .add (repoInfosNode ); // wrap single object in a list
262+ }
123263
124- // Iterate through the array to find the correct externalId and retrieve the id
125264 for (JsonNode repoInfo : repoInfos ) {
126265 JsonNode repository = repoInfo .path ("repository" );
127266 if (repository .path ("externalId" ).asText ().equals (SDMConstants .REPOSITORY_ID )) {
128267 return repository .path ("id" ).asText ();
129268 }
130269 }
131270 } catch (Exception e ) {
132- throw new ServiceException (String . format ( e . getMessage ()) );
271+ throw new ServiceException ("Failed to parse repository response" , e );
133272 }
134273 return null ;
135274 }
0 commit comments