b5531008165978fb5e6f375b85cadbc92d00d122
[so.git] / asdc-controller / src / main / java / org / openecomp / mso / asdc / client / ASDCController.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * OPENECOMP - MSO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.mso.asdc.client;
22
23
24 import java.io.IOException;
25 import java.io.UnsupportedEncodingException;
26 import org.openecomp.sdc.api.IDistributionClient;
27 import org.openecomp.sdc.api.consumer.IDistributionStatusMessage;
28 import org.openecomp.sdc.api.consumer.INotificationCallback;
29 import org.openecomp.sdc.api.notification.IArtifactInfo;
30 import org.openecomp.sdc.api.notification.INotificationData;
31 import org.openecomp.sdc.api.notification.IResourceInstance;
32 import org.openecomp.sdc.api.results.IDistributionClientDownloadResult;
33 import org.openecomp.sdc.api.results.IDistributionClientResult;
34 import org.openecomp.sdc.impl.DistributionClientFactory;
35 import org.openecomp.sdc.utils.DistributionActionResultEnum;
36 import org.openecomp.sdc.utils.DistributionStatusEnum;
37 import org.openecomp.mso.asdc.client.exceptions.ASDCControllerException;
38 import org.openecomp.mso.asdc.client.exceptions.ASDCDownloadException;
39 import org.openecomp.mso.asdc.client.exceptions.ASDCParametersException;
40 import org.openecomp.mso.asdc.client.exceptions.ArtifactInstallerException;
41 import org.openecomp.mso.asdc.installer.IVfResourceInstaller;
42 import org.openecomp.mso.asdc.installer.VfResourceStructure;
43 import org.openecomp.mso.asdc.installer.heat.VfResourceInstaller;
44 import org.openecomp.mso.asdc.util.ASDCNotificationLogging;
45 import org.openecomp.mso.logger.MessageEnum;
46 import org.openecomp.mso.logger.MsoAlarmLogger;
47 import org.openecomp.mso.logger.MsoLogger;
48 import org.openecomp.mso.utils.UUIDChecker;
49
50 public class ASDCController {
51
52     protected static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.ASDC);
53
54     protected static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
55
56     protected boolean isAsdcClientAutoManaged = false;
57
58     protected String controllerName;
59
60     /**
61      * Inner class for Notification callback
62      *
63      *
64      */
65     private final class ASDCNotificationCallBack implements INotificationCallback {
66
67         private ASDCController asdcController;
68
69         ASDCNotificationCallBack (ASDCController controller) {
70             asdcController = controller;
71         }
72
73         /**
74          * This method can be called multiple times at the same moment.
75          * The controller must be thread safe !
76          */
77         @Override
78         public void activateCallback (INotificationData iNotif) {
79             long startTime = System.currentTimeMillis ();
80             UUIDChecker.generateUUID (LOGGER);
81             MsoLogger.setServiceName ("NotificationHandler");
82             MsoLogger.setLogContext (iNotif.getDistributionID (), iNotif.getServiceUUID ());
83             String event = "Receive a callback notification in ASDC, nb of resources: " + iNotif.getResources ().size ();
84             LOGGER.debug(event);
85             asdcController.treatNotification (iNotif);
86             LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Completed the treatment of the notification");
87         }
88     }
89
90     // ***** Controller STATUS code
91
92     protected int nbOfNotificationsOngoing = 0;
93
94     public int getNbOfNotificationsOngoing () {
95         return nbOfNotificationsOngoing;
96     }
97
98     private ASDCControllerStatus controllerStatus = ASDCControllerStatus.STOPPED;
99
100     protected synchronized final void changeControllerStatus (ASDCControllerStatus newControllerStatus) {
101         switch (newControllerStatus) {
102
103             case BUSY:
104                 ++this.nbOfNotificationsOngoing;
105                 this.controllerStatus = newControllerStatus;
106                 break;
107
108             case IDLE:
109                 if (this.nbOfNotificationsOngoing > 1) {
110                     --this.nbOfNotificationsOngoing;
111                 } else {
112                     this.nbOfNotificationsOngoing = 0;
113                     this.controllerStatus = newControllerStatus;
114                 }
115
116                 break;
117             default:
118                 this.controllerStatus = newControllerStatus;
119                 break;
120
121         }
122     }
123
124     public synchronized final ASDCControllerStatus getControllerStatus () {
125         return this.controllerStatus;
126     }
127
128     // ***** END of Controller STATUS code
129
130     protected ASDCConfiguration asdcConfig;
131     private IDistributionClient distributionClient;
132     private IVfResourceInstaller resourceInstaller;
133
134     public ASDCController (String controllerConfigName) {
135         isAsdcClientAutoManaged = true;
136         this.controllerName = controllerConfigName;
137         this.resourceInstaller = new VfResourceInstaller();
138     }
139
140     public ASDCController (String controllerConfigName, IDistributionClient asdcClient, IVfResourceInstaller resourceinstaller) {
141
142         distributionClient = asdcClient;
143         this.resourceInstaller = resourceinstaller;
144         this.controllerName = controllerConfigName;
145     }
146
147     public ASDCController (String controllerConfigName,IDistributionClient asdcClient) {
148         distributionClient = asdcClient;
149         this.controllerName = controllerConfigName;
150         this.resourceInstaller = new VfResourceInstaller();
151     }
152
153     /**
154      * This method refresh the ASDC Controller config and restart the client.
155      *
156      * @return true if config has been reloaded, false otherwise
157      * @throws ASDCControllerException If case of issue with the init or close called during the config reload
158      * @throws ASDCParametersException If there is an issue with the parameters
159      * @throws IOException In case of the key file could not be loaded properly
160      */
161     public boolean updateConfigIfNeeded () throws ASDCParametersException, ASDCControllerException, IOException {
162         LOGGER.debug ("Checking whether ASDC config must be reloaded");
163
164         try {
165             if (this.asdcConfig != null && this.asdcConfig.hasASDCConfigChanged ()) {
166                 LOGGER.debug ("ASDC Config must be reloaded");
167                 this.closeASDC ();
168                 this.asdcConfig.refreshASDCConfig ();
169                 this.initASDC ();
170                 return true;
171             } else {
172                 LOGGER.debug ("ASDC Config must NOT be reloaded");
173                 return false;
174             }
175         } catch (ASDCParametersException ep) {
176             // Try to close it at least to make it consistent with the file specified
177             // We cannot let it run with a different config file, even if it's bad.
178             // This call could potentially throw a ASDCController exception if the controller is currently BUSY.
179             this.closeASDC ();
180
181             throw ep;
182         }
183     }
184
185     /**
186      * This method initializes the ASDC Controller and the ASDC Client.
187      *
188      * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be instantiated or if an init
189      *         attempt is done when already initialized
190      * @throws ASDCParametersException If there is an issue with the parameters provided
191      * @throws IOException In case of issues when trying to load the key file
192      */
193     public void initASDC () throws ASDCControllerException, ASDCParametersException, IOException {
194         String event = "Initialize the ASDC Controller";
195         MsoLogger.setServiceName ("InitASDC");
196         LOGGER.debug (event);
197         if (this.getControllerStatus () != ASDCControllerStatus.STOPPED) {
198             String endEvent = "The controller is already initialized, call the closeASDC method first";
199             throw new ASDCControllerException (endEvent);
200         }
201
202         if (asdcConfig == null) {
203             asdcConfig = new ASDCConfiguration (this.controllerName);
204
205         }
206         // attempt to refresh during init as MsoProperties is may be pointing to an old file
207         // Be careful this is static in MsoProperties
208         asdcConfig.refreshASDCConfig ();
209
210         if (this.distributionClient == null) {
211             distributionClient = DistributionClientFactory.createDistributionClient ();
212         }
213         long initStartTime = System.currentTimeMillis ();
214         IDistributionClientResult result = this.distributionClient.init (asdcConfig,
215                                                                          new ASDCNotificationCallBack (this));
216         if (!result.getDistributionActionResult ().equals (DistributionActionResultEnum.SUCCESS)) {
217             String endEvent = "ASDC distribution client init failed with reason:"
218                               + result.getDistributionMessageResult ();
219             LOGGER.recordMetricEvent (initStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, "Initialization of the ASDC Controller failed with reason:" + result.getDistributionMessageResult (), "ASDC", "init", null);
220             LOGGER.debug (endEvent);
221             asdcConfig = null;
222
223             this.changeControllerStatus (ASDCControllerStatus.STOPPED);
224             throw new ASDCControllerException ("Initialization of the ASDC Controller failed with reason: "
225                                                + result.getDistributionMessageResult ());
226         }
227         LOGGER.recordMetricEvent (initStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully initialize ASDC Controller", "ASDC", "init", null);
228
229         long clientstartStartTime = System.currentTimeMillis ();
230         result = this.distributionClient.start ();
231         if (!result.getDistributionActionResult ().equals (DistributionActionResultEnum.SUCCESS)) {
232             String endEvent = "ASDC distribution client start failed with reason:"
233                               + result.getDistributionMessageResult ();
234             LOGGER.recordMetricEvent (clientstartStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, endEvent, "ASDC", "start", null);
235             LOGGER.debug (endEvent);
236             asdcConfig = null;
237             this.changeControllerStatus (ASDCControllerStatus.STOPPED);
238             throw new ASDCControllerException ("Startup of the ASDC Controller failed with reason: "
239                                                + result.getDistributionMessageResult ());
240         }
241         LOGGER.recordMetricEvent (clientstartStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully start ASDC distribution client", "ASDC", "start", null);
242
243
244         this.changeControllerStatus (ASDCControllerStatus.IDLE);
245         LOGGER.info (MessageEnum.ASDC_INIT_ASDC_CLIENT_SUC, "ASDC", "changeControllerStatus");
246     }
247
248     /**
249      * This method closes the ASDC Controller and the ASDC Client.
250      *
251      * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be closed because
252      *         it's currently BUSY in processing notifications.
253      */
254     public void closeASDC () throws ASDCControllerException {
255
256         MsoLogger.setServiceName ("CloseController");
257         if (this.getControllerStatus () == ASDCControllerStatus.BUSY) {
258             throw new ASDCControllerException ("Cannot close the ASDC controller as it's currently in BUSY state");
259         }
260         if (this.distributionClient != null) {
261             this.distributionClient.stop ();
262             // If auto managed we can set it to Null, ASDCController controls it.
263             // In the other case the client of this class has specified it, so we can't reset it
264             if (isAsdcClientAutoManaged) {
265                 // Next init will initialize it with a new ASDC Client
266                 this.distributionClient = null;
267             }
268
269         }
270         this.changeControllerStatus (ASDCControllerStatus.STOPPED);
271     }
272
273     private boolean checkResourceAlreadyDeployed (VfResourceStructure vfResource) throws ArtifactInstallerException {
274
275         if (this.resourceInstaller.isResourceAlreadyDeployed (vfResource)) {
276             LOGGER.info (MessageEnum.ASDC_ARTIFACT_ALREADY_EXIST,
277                                 vfResource.getResourceInstance().getResourceInstanceName(),
278                                 vfResource.getResourceInstance().getResourceUUID(),
279                                 vfResource.getResourceInstance().getResourceName(), "", "");
280             
281             this.sendDeployNotificationsForResource(vfResource,DistributionStatusEnum.ALREADY_DOWNLOADED,null);
282             this.sendDeployNotificationsForResource(vfResource,DistributionStatusEnum.ALREADY_DEPLOYED,null);
283            
284             return true;
285         } else {
286             return false;
287         }
288
289     }
290
291     private final static String UUID_PARAM = "(UUID:";
292     
293     private IDistributionClientDownloadResult downloadTheArtifact (IArtifactInfo artifact,
294                                                                    String distributionId) throws ASDCDownloadException {
295
296         LOGGER.debug ("Trying to download the artifact : " + artifact.getArtifactURL ()
297                       + UUID_PARAM
298                       + artifact.getArtifactUUID ()
299                       + ")");
300         IDistributionClientDownloadResult downloadResult;
301
302        
303         try {
304             downloadResult = distributionClient.download (artifact);
305             if (null == downloadResult) {
306                 LOGGER.info (MessageEnum.ASDC_ARTIFACT_NULL, artifact.getArtifactUUID (), "", "");
307                 return downloadResult;
308             }
309         } catch (RuntimeException e) {
310             LOGGER.debug ("Not able to download the artifact due to an exception: " + artifact.getArtifactURL ());
311             this.sendASDCNotification (NotificationType.DOWNLOAD,
312                                        artifact.getArtifactURL (),
313                                        asdcConfig.getConsumerID (),
314                                        distributionId,
315                                        DistributionStatusEnum.DOWNLOAD_ERROR,
316                                        e.getMessage (),
317                                        System.currentTimeMillis ());
318
319             throw new ASDCDownloadException ("Exception caught when downloading the artifact", e);
320         }
321
322         if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult ())) {
323
324             LOGGER.info (MessageEnum.ASDC_ARTIFACT_DOWNLOAD_SUC,
325                          artifact.getArtifactURL (),
326                          artifact.getArtifactUUID (),
327                          String.valueOf (downloadResult.getArtifactPayload ().length), "", "");
328
329         } else {
330
331             LOGGER.error (MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL,
332                           artifact.getArtifactName (),
333                           artifact.getArtifactURL (),
334                           artifact.getArtifactUUID (),
335                           downloadResult.getDistributionMessageResult (), "", "", MsoLogger.ErrorCode.DataError, "ASDC artifact download fail");
336
337             this.sendASDCNotification (NotificationType.DOWNLOAD,
338                                        artifact.getArtifactURL (),
339                                        asdcConfig.getConsumerID (),
340                                        distributionId,
341                                        DistributionStatusEnum.DOWNLOAD_ERROR,
342                                        downloadResult.getDistributionMessageResult (),
343                                        System.currentTimeMillis ());
344
345             throw new ASDCDownloadException ("Artifact " + artifact.getArtifactName ()
346                                              + " could not be downloaded from ASDC URL "
347                                              + artifact.getArtifactURL ()
348                                              + UUID_PARAM
349                                              + artifact.getArtifactUUID ()
350                                              + ")"
351                                              + System.lineSeparator ()
352                                              + "Error message is "
353                                              + downloadResult.getDistributionMessageResult ()
354                                              + System.lineSeparator ());
355
356         }
357
358         this.sendASDCNotification (NotificationType.DOWNLOAD,
359                                    artifact.getArtifactURL (),
360                                    asdcConfig.getConsumerID (),
361                                    distributionId,
362                                    DistributionStatusEnum.DOWNLOAD_OK,
363                                    null,
364                                    System.currentTimeMillis ());
365         return downloadResult;
366
367     }
368
369    
370     private void sendDeployNotificationsForResource(VfResourceStructure vfResourceStructure,DistributionStatusEnum distribStatus, String errorReason) {
371     
372         for (IArtifactInfo artifactInfo : vfResourceStructure.getResourceInstance().getArtifacts()) {
373         
374                 if (DistributionStatusEnum.DEPLOY_OK.equals(distribStatus) 
375                                 // This could be NULL if the artifact is a VF module artifact, this won't be present in the MAP
376                                 && vfResourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()) != null 
377                                 && vfResourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()).getDeployedInDb() == 0) {
378                         this.sendASDCNotification (NotificationType.DEPLOY,
379                                         artifactInfo.getArtifactURL (),
380                           asdcConfig.getConsumerID (),
381                           vfResourceStructure.getNotification().getDistributionID(),
382                           DistributionStatusEnum.DEPLOY_ERROR,
383                           "The artifact has not been used by the modules defined in the resource",
384                           System.currentTimeMillis ());
385                 } else {
386                         this.sendASDCNotification (NotificationType.DEPLOY,
387                                         artifactInfo.getArtifactURL (),
388                           asdcConfig.getConsumerID (),
389                           vfResourceStructure.getNotification().getDistributionID(),
390                           distribStatus,
391                           errorReason,
392                           System.currentTimeMillis ());
393                 }
394         }
395     }
396     
397     private void deployResourceStructure (VfResourceStructure vfResourceStructure) throws ArtifactInstallerException {
398
399         LOGGER.info (MessageEnum.ASDC_START_DEPLOY_ARTIFACT, vfResourceStructure.getResourceInstance().getResourceInstanceName(), vfResourceStructure.getResourceInstance().getResourceUUID(), "ASDC", "deployResourceStructure");
400         try {
401                 vfResourceStructure.createVfModuleStructures();
402                 resourceInstaller.installTheResource (vfResourceStructure);
403                 
404         } catch (ArtifactInstallerException e) {
405                 
406                 sendDeployNotificationsForResource(vfResourceStructure,DistributionStatusEnum.DEPLOY_ERROR,e.getMessage());
407                 throw e;
408         }
409
410         if (vfResourceStructure.isDeployedSuccessfully()) {
411                 LOGGER.info (MessageEnum.ASDC_ARTIFACT_DEPLOY_SUC,
412                                 vfResourceStructure.getResourceInstance().getResourceName(),
413                                 vfResourceStructure.getResourceInstance().getResourceUUID(),
414                         String.valueOf (vfResourceStructure.getVfModuleStructure().size()), "ASDC", "deployResourceStructure");
415                 sendDeployNotificationsForResource(vfResourceStructure,DistributionStatusEnum.DEPLOY_OK ,null);
416         }
417
418     }
419
420     private enum NotificationType {
421         DOWNLOAD, DEPLOY
422     }
423
424     private void sendASDCNotification (NotificationType notificationType,
425                                        String artifactURL,
426                                        String consumerID,
427                                        String distributionID,
428                                        DistributionStatusEnum status,
429                                        String errorReason,
430                                        long timestamp) {
431         
432         String event = "Sending " + notificationType.name ()
433                        + "("
434                        + status.name ()
435                        + ")"
436                        + " notification to ASDC for artifact:"
437                        + artifactURL;
438         
439         if (errorReason != null) {
440                 event=event+"("+errorReason+")";
441         }
442         LOGGER.info (MessageEnum.ASDC_SEND_NOTIF_ASDC, notificationType.name (), status.name (), artifactURL, "ASDC", "sendASDCNotification");
443         LOGGER.debug (event);
444
445         long subStarttime = System.currentTimeMillis ();
446         String action = "";
447         try {
448             IDistributionStatusMessage message = new DistributionStatusMessage (artifactURL,
449                                                                                 consumerID,
450                                                                                 distributionID,
451                                                                                 status,
452                                                                                 timestamp);
453
454             switch (notificationType) {
455                 case DOWNLOAD:
456                     if (errorReason != null) {
457                         this.distributionClient.sendDownloadStatus (message, errorReason);
458                     } else {
459                         this.distributionClient.sendDownloadStatus (message);
460                     }
461                     action = "sendDownloadStatus";
462                     break;
463                 case DEPLOY:
464                     if (errorReason != null) {
465                         this.distributionClient.sendDeploymentStatus (message, errorReason);
466                     } else {
467                         this.distributionClient.sendDeploymentStatus (message);
468                     }
469                     action = "sendDeploymentdStatus";
470                     break;
471                 default:
472                         break;
473             }
474         } catch (RuntimeException e) {
475             // TODO: May be a list containing the unsent notification should be
476             // kept
477             LOGGER.warn (MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC, "ASDC", "sendASDCNotification", MsoLogger.ErrorCode.SchemaError, "RuntimeException - sendASDCNotification", e);
478         }
479         LOGGER.recordMetricEvent (subStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully sent notification to ASDC", "ASDC", action, null);
480     }
481
482     public void treatNotification (INotificationData iNotif) {
483         
484         int noOfArtifacts = 0;
485         for (IResourceInstance resource : iNotif.getResources ()) {
486                 noOfArtifacts += resource.getArtifacts ().size ();
487         }
488         LOGGER.info (MessageEnum.ASDC_RECEIVE_CALLBACK_NOTIF,
489                      String.valueOf (noOfArtifacts),
490                      iNotif.getServiceUUID (), "ASDC", "treatNotification");
491         
492         try {
493                 LOGGER.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
494                         LOGGER.info(MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF, iNotif.getServiceUUID(), "ASDC", "treatNotification");
495                         this.changeControllerStatus(ASDCControllerStatus.BUSY);
496                         // Process only the Resource artifacts in MSO
497                         for (IResourceInstance resource : iNotif.getResources()) {
498
499                                 // We process only VNF resource on MSO Side
500                                 if ("VF".equals(resource.getResourceType())) {
501                                         this.processResourceNotification(iNotif,resource);              
502                                 }
503                         }
504                                         
505                                         
506                                 
507         } catch (RuntimeException e) {
508             LOGGER.error (MessageEnum.ASDC_GENERAL_EXCEPTION_ARG,
509                           "Unexpected exception caught during the notification processing", "ASDC", "treatNotification", MsoLogger.ErrorCode.SchemaError, "RuntimeException in treatNotification",
510                           e);
511         } finally {
512             this.changeControllerStatus (ASDCControllerStatus.IDLE);
513         }
514     }
515
516         
517     private void processResourceNotification (INotificationData iNotif,IResourceInstance resource) {
518                 // For each artifact, create a structure describing the VFModule in a ordered flat level
519                 VfResourceStructure vfResourceStructure = new VfResourceStructure(iNotif,resource);
520                 try {
521                         
522                         if (!this.checkResourceAlreadyDeployed(vfResourceStructure)) {
523                                 for (IArtifactInfo artifact : resource.getArtifacts()) {
524                                         
525                                                 IDistributionClientDownloadResult resultArtifact = this.downloadTheArtifact(artifact, 
526                                                                 iNotif.getDistributionID());
527
528                                                 if (resultArtifact != null) {
529                                                         if (ASDCConfiguration.VF_MODULES_METADATA.equals(artifact.getArtifactType())) {
530                                                                 LOGGER.debug("VF_MODULE_ARTIFACT: "+new String(resultArtifact.getArtifactPayload(),"UTF-8"));
531                                                                 LOGGER.debug(ASDCNotificationLogging.dumpVfModuleMetaDataList(distributionClient.decodeVfModuleArtifact(resultArtifact.getArtifactPayload())));
532                                                         }
533                                                         vfResourceStructure.addArtifactToStructure(distributionClient,artifact, resultArtifact);
534                                 
535                                                 } 
536
537                                 }
538                                 
539                                 this.deployResourceStructure(vfResourceStructure);
540                                 
541                         } 
542                 } catch (ArtifactInstallerException | ASDCDownloadException | UnsupportedEncodingException e) {
543                         LOGGER.error(MessageEnum.ASDC_GENERAL_EXCEPTION_ARG,
544                                         "Exception caught during Installation of artifact", "ASDC", "processResourceNotification", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in processResourceNotification", e);
545                 }
546     }
547     
548     private static final String UNKNOWN="Unknown";
549     
550     /**
551      * @return the address of the ASDC we are connected to.
552      */
553     public String getAddress () {
554         if (asdcConfig != null) {
555             return asdcConfig.getAsdcAddress ();
556         }
557         return UNKNOWN;
558     }
559
560     /**
561      * @return the environment name of the ASDC we are connected to.
562      */
563     public String getEnvironment () {
564         if (asdcConfig != null) {
565             return asdcConfig.getEnvironmentName ();
566         }
567         return UNKNOWN;
568     }
569
570 }