001/*
002 * Copyright (c) 2004-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.ecoinformatics.seek.ecogrid;
031
032import java.io.File;
033import java.io.FileInputStream;
034import java.io.FileNotFoundException;
035import java.io.FileOutputStream;
036import java.io.IOException;
037import java.io.InputStream;
038import java.io.ObjectInput;
039import java.io.ObjectInputStream;
040import java.io.ObjectOutputStream;
041import java.io.OutputStream;
042import java.util.List;
043import java.util.Vector;
044
045import org.apache.commons.logging.Log;
046import org.apache.commons.logging.LogFactory;
047import org.apache.xpath.XPathAPI;
048import org.ecoinformatics.ecogrid.registry.stub.RegistryEntryType;
049import org.ecoinformatics.ecogrid.registry.stub.RegistryEntryTypeDocumentType;
050import org.ecoinformatics.seek.ecogrid.exception.InvalidEcoGridServiceException;
051import org.kepler.authentication.AuthenticationException;
052import org.kepler.authentication.AuthenticationManager;
053import org.kepler.authentication.Domain;
054import org.kepler.authentication.DomainList;
055import org.kepler.authentication.ProxyEntity;
056import org.kepler.configuration.ConfigurationManager;
057import org.kepler.configuration.ConfigurationProperty;
058import org.kepler.util.DotKeplerManager;
059import org.w3c.dom.Node;
060import org.w3c.dom.NodeList;
061
062import ptolemy.util.MessageHandler;
063
064/**
065 * This class will control the current service user want to search: user can
066 * add, remove and update the service list
067 * 
068 * @author leinfelder (modified from jing tao's version)
069 * 
070 */
071
072public class EcoGridServicesController {
073
074        protected static Log log;
075        protected static boolean isDebugging;
076        protected static final String TRUE = "true";
077        protected static final String FALSE = "false";
078
079        private String _saveFileName;
080        
081        public static final String AUTHENTICATEDQUERYSERVICETYPE = "http://ecoinformatics.org/authenticatedqueryservice-1.0.0";
082        public static final String QUERYSERVICETYPE = "http://ecoinformatics.org/queryservice-1.0.0";
083        public static final String AUTHSERVICETYPE = "http://ecoinformatics.org/authenticationservice-1.0.0";
084        public static final String PUTSERVICETYPE = "http://ecoinformatics.org/putservice-1.0.0";
085        public static final String IDENTIFIERSERVICETYPE = "http://ecoinformatics.org/identifierservice-1.0.0";
086
087        static {
088                log = LogFactory.getLog(EcoGridServicesController.class);
089                isDebugging = log.isDebugEnabled();
090        }
091
092        // list user selected
093        private Vector selectedSearchingServicesList = new Vector();
094
095        // the list in configure file
096        private Vector<EcoGridService> currentServicesList = new Vector();
097
098        // the types to include in the listing
099        private Vector serviceTypes = new Vector();
100
101        // maximum number of times we retry authentication
102        private int maxLoginAttempt = 3;
103
104        private static EcoGridServicesController controller = null;
105
106        // restrict the use of this class to singleton
107        private EcoGridServicesController() {
108                // Set up file name for storing default local save directory
109                File modDir = DotKeplerManager.getInstance()
110                                .getTransientModuleDirectory("ecogrid");
111                if (modDir != null) {
112                        _saveFileName = modDir.toString();
113                } else {
114                        _saveFileName = System.getProperty("KEPLER");
115                }
116                if (!_saveFileName.endsWith(File.separator)) {
117                        _saveFileName += File.separator;
118                }
119                _saveFileName += "EcoGridServices";
120        }
121
122        /**
123         * Method to get an object from this singleton class
124         * 
125         */
126        public static EcoGridServicesController getInstance() {
127                if (controller == null) {
128                        controller = new EcoGridServicesController();
129                        controller.init();
130                }
131                return controller;
132        }
133
134        private static String lookupAuthenticationDomainMapping(String serviceType) {
135                // the get the key=value map for type=class
136                String parentXPath = "//" + MetadataSpecificationInterface.ECOGRIDPATH
137                                + "/" + MetadataSpecificationInterface.AUTHENTICATION_MAPPING;
138                
139    
140    ConfigurationProperty ecogridProperty = ConfigurationManager.getInstance()
141      .getProperty(ConfigurationManager.getModule("ecogrid"));
142    ConfigurationProperty authMapping = ecogridProperty.findProperties("serviceType", serviceType, true).get(0);
143    return authMapping.getProperty("serviceClass").getValue();
144        }
145
146        protected void init() {
147                // include all service types for the generic controller
148                serviceTypes.add(QUERYSERVICETYPE);
149                serviceTypes.add(AUTHENTICATEDQUERYSERVICETYPE);
150                serviceTypes.add(AUTHSERVICETYPE);
151                serviceTypes.add(PUTSERVICETYPE);
152                serviceTypes.add(IDENTIFIERSERVICETYPE);
153                //readServicesFromConfig();
154                readServices();
155        }
156
157        /**
158         * Remove a given service from current query service list. The key for
159         * removing is endpoint. If endpoint is same, we think they are same service
160         * 
161         * @param service
162         *            EcoGridService
163         */
164        public void removeService(EcoGridService service) {
165                if (service == null) {
166                        // if service is null, we don't need do anything
167                        return;
168                }// if
169                else {
170                        String endPoint = service.getEndPoint();
171                        if (endPoint == null || endPoint.trim().equals("")) {
172                                return;
173                        }// if
174                        else {
175                                // go through the current query service list and find a servcie
176                                // which has same endpoint to the given servcie. The remove it.
177                                int size = currentServicesList.size();
178                                for (int i = 0; i < size; i++) {
179                                        EcoGridService currentService = (EcoGridService) currentServicesList
180                                                        .elementAt(i);
181                                        if (currentService != null) {
182                                                String currentEndPoint = currentService.getEndPoint();
183                                                if (currentEndPoint != null
184                                                                && currentEndPoint.equals(endPoint)) {
185                                                        currentServicesList.remove(i);
186                                                        if (isDebugging) {
187                                                                log.debug("Delete service "
188                                                                                + service.getServiceName()
189                                                                                + " from list");
190                                                        }
191                                                        return;
192                                                }// if
193                                        }// if
194                                }// for
195                        }// else
196                }// else
197        }// removeService
198
199        /**
200         * Add a service to service list. If new service has same endpoints to
201         * service already in current. Then we will compare document type array and
202         * add new document type into service If the serviceType is not a in our
203         * list, it will throw an exception
204         * 
205         * @param service
206         *            EcoGridService
207         * @throws InvalidEcoGridServiceException
208         */
209        public void addService(EcoGridService service)
210                        throws InvalidEcoGridServiceException {
211                String serviceType = service.getServiceType();
212                if (serviceType == null || !serviceTypes.contains(serviceType)) {
213                        throw new InvalidEcoGridServiceException(
214                                        "The service type is invalid or null: " + serviceType
215                                                        + ".  Couldn't be added to list");
216                }// if
217
218                // isDuplicateService
219                int index = isDuplicateService(service, currentServicesList);
220                if (index == -1) {
221                        // it is new end point
222                        if (isDebugging) {
223                                log.debug("Add service " + service.getServiceName()
224                                                + " into list");
225                        }
226                        currentServicesList.add(service);
227                } else {
228                        // compare document type list if new service has same endpoint
229                        EcoGridService currentService = (EcoGridService) currentServicesList
230                                        .elementAt(index);
231                        DocumentType[] currentDocTypeList = currentService
232                                        .getDocumentTypeList();
233                        DocumentType[] newDocTypeList = service.getDocumentTypeList();
234                        if (currentDocTypeList == null || currentDocTypeList.length == 0) {
235                                // if current service doesn't have any document type, just set
236                                // the new one
237                                currentService.setDocumentTypeList(newDocTypeList);
238                        } else if (newDocTypeList != null) {
239                                int sizeOfnew = newDocTypeList.length;
240                                int sizeofCurrent = currentDocTypeList.length;
241                                Vector newDocTypeVector = new Vector();
242                                // go through new document type
243                                for (int j = 0; j < sizeOfnew; j++) {
244                                        boolean existed = false;
245                                        DocumentType newType = newDocTypeList[j];
246                                        if (newType == null) {
247                                                continue;
248                                        }
249                                        String newNamespace = newType.getNamespace();
250                                        if (newNamespace == null || newNamespace.trim().equals("")) {
251                                                continue;
252                                        }
253                                        for (int i = 0; i < sizeofCurrent; i++) {
254                                                DocumentType currentType = currentDocTypeList[i];
255                                                if (currentType == null) {
256                                                        continue;
257                                                } else {
258                                                        String currentNamespace = currentType
259                                                                        .getNamespace();
260                                                        if (currentNamespace == null
261                                                                        || currentNamespace.trim().equals("")) {
262                                                                continue;
263                                                        } else if (currentNamespace.equals(newNamespace)) {
264                                                                existed = true;
265                                                        }//
266                                                }// else
267
268                                        }// for
269                                        // if the namespace is a new space, add this document type
270                                        // into the array
271                                        if (!existed) {
272                                                newDocTypeVector.add(newType);
273                                        }
274                                }// for
275                                // if we do get some new document type(newDocTypeVector is not
276                                // empty)
277                                // we should a new doctype into list
278                                if (!newDocTypeVector.isEmpty()) {
279                                        DocumentType[] updatedDocTypeList = addNewDocType(
280                                                        currentDocTypeList, newDocTypeVector);
281                                        currentService.setDocumentTypeList(updatedDocTypeList);
282                                }// if
283
284                        }// else if
285                }// else
286        }// addService
287
288        public void clearServicesList() {
289                this.currentServicesList = new Vector();
290                this.selectedSearchingServicesList = new Vector();
291        }
292
293        /*
294         * Method to add a vector document type to array
295         */
296        protected DocumentType[] addNewDocType(DocumentType[] currentArray,
297                        Vector newTypeVector) {
298                int arraySize = currentArray.length;
299                int vectorSize = newTypeVector.size();
300                int newSize = arraySize + vectorSize;
301                DocumentType[] newArray = new DocumentType[newSize];
302                // copy the array
303                for (int i = 0; i < arraySize; i++) {
304                        newArray[i] = currentArray[i];
305                }// for
306                // copy the vector
307                for (int j = 0; j < vectorSize; j++) {
308                        newArray[arraySize + j] = (DocumentType) newTypeVector.elementAt(j);
309                }// for
310                return newArray;
311        }// addNewDocType
312
313        /**
314         * Method to update a existed EcoGridService
315         * 
316         * @param service
317         *            EcoGridService
318         * @throws InvalidEcoGridServiceException
319         */
320        public void updateService(EcoGridService service)
321                        throws InvalidEcoGridServiceException {
322                if (service == null) {
323                        throw new InvalidEcoGridServiceException(
324                                        "Couldn't use a null service" + " to update a list");
325                }
326                // make sure the service is a valid type
327                String serviceType = service.getServiceType();
328                String endPoint = service.getEndPoint();
329                if (serviceType == null || !serviceTypes.contains(serviceType)) {
330                        throw new InvalidEcoGridServiceException(
331                                        "The service type is invalid or null "
332                                                        + "and couldn't be updated into list");
333                }// if
334                if (endPoint == null || endPoint.trim().equals("")) {
335                        throw new InvalidEcoGridServiceException(
336                                        "End point cannot be null in "
337                                                        + "the new service which will update the list");
338                }
339                boolean success = false;
340                // go through the vector
341                int size = currentServicesList.size();
342                for (int i = 0; i < size; i++) {
343                        EcoGridService currentService = (EcoGridService) currentServicesList
344                                        .elementAt(i);
345                        String currentEndPoint = currentService.getEndPoint();
346                        if (currentEndPoint != null && currentEndPoint.equals(endPoint)) {
347                                // replace the old one, but respect the selection status
348                                Object oldService = currentServicesList.remove(i);
349                                if (oldService instanceof SelectableEcoGridService) {
350                                        if (service instanceof SelectableEcoGridService) {
351                                                // set the selection status for the overall service
352                                                ((SelectableEcoGridService) service)
353                                                                .getSelectableServiceName().setIsSelected(
354                                                                                ((SelectableEcoGridService) oldService)
355                                                                                                .getSelectableServiceName()
356                                                                                                .getIsSelected());
357                                                SelectableDocumentType[] documentTypeList = ((SelectableEcoGridService) service)
358                                                                .getSelectableDocumentTypeList();
359                                                SelectableDocumentType[] oldDocumentTypeList = ((SelectableEcoGridService) oldService)
360                                                                .getSelectableDocumentTypeList();
361                                                if (documentTypeList != null) {
362                                                        // go through the new documents and set the
363                                                        // selection status on each of them
364                                                        for (int j = 0; j < documentTypeList.length; j++) {
365                                                                // avoid arrayindexoutofbounds exceptions
366                                                                if (oldDocumentTypeList != null
367                                                                                && j >= oldDocumentTypeList.length) {
368                                                                        break;
369                                                                }
370                                                                // set the selection status
371                                                                if (oldDocumentTypeList[j].getNamespace()
372                                                                                .equals(
373                                                                                                documentTypeList[j]
374                                                                                                                .getNamespace())) {
375                                                                        documentTypeList[j]
376                                                                                        .setIsSelected(oldDocumentTypeList[j]
377                                                                                                        .getIsSelected());
378                                                                }
379                                                        }
380                                                }
381                                        }
382                                }
383                                currentServicesList.add(i, service);
384                                if (isDebugging) {
385                                        log.debug("Update the service " + service.getServiceName());
386                                }
387                                success = true;
388                        }
389                }// for
390                // couldn't find a service to update and will throw a exception
391                if (!success) {
392                        throw new InvalidEcoGridServiceException(
393                                        "Couldn't find a target service " + "to update in the list");
394                }
395        }// updateService
396
397        /**
398         * Method to get the full service list vector
399         * 
400         * @return Vector all services in the controller
401         */
402        public Vector getServicesList() {
403                return this.currentServicesList;
404        }
405
406        public void setServicesList(Vector serviceList) {
407                this.currentServicesList = serviceList;
408        }
409
410        /**
411         * Rather than completely overwriting the existing services, this method
412         * allows new services to be merged with the existing ones. Services with
413         * overlapping endpoints are updated to use the other attributes of the new
414         * service. If a service (endpoint) is not found in the current list, the
415         * new service is added
416         * 
417         * @param newServices
418         *            list of new EcoGridServices to merge with the existing
419         *            services
420         * @throws InvalidEcoGridServiceException
421         *             cascades up from the add() and update() methods used by this
422         *             method
423         */
424        public void mergeServicesList(Vector newServices) {
425                for (int i = 0; i < newServices.size(); i++) {
426                        // get a new service
427                        EcoGridService newService = (EcoGridService) newServices.get(i);
428                        // look it up in the list
429                        EcoGridService existingService = this.getService(newService
430                                        .getEndPoint());
431                        if (existingService != null) {
432                                try {
433                                        this.updateService(newService);
434                                } catch (InvalidEcoGridServiceException e) {
435                                        // warn, but continue processing the list
436                                        log.info("could not update service:" + e.getMessage());
437                                        // e.printStackTrace();
438                                }
439                        } else {
440                                try {
441                                        this.addService(newService);
442                                } catch (InvalidEcoGridServiceException e) {
443                                        // warn, but continue processing the list
444                                        log.info("could not add service:" + e.getMessage());
445                                        // e.printStackTrace();
446                                }
447                        }
448                }
449        }
450
451        /**
452         * Provides an authentication credential for the given service object (if
453         * possible) Note that there may not be adequate information in the
454         * EcoGridServicesController to support authentication for every service.
455         * Additionally, authentication is not applicable for all EcoGridService
456         * types
457         * 
458         * @param service
459         *            an any given EcoGridService that might need authentication
460         *            credentials to use This service must be part of a service
461         *            group that has registered a valid authentication service that
462         *            will provide the credential for use by other service types
463         * @return an authentication credential (string) to be used by the service
464         *         given in parameter
465         */
466        public synchronized String authenticateForService(EcoGridService service) {
467                // authenticate for any given service
468                String sessionId = "bogus!";
469                String domainName = null;
470                try {
471                        if (service != null) {
472                                // get the authentication domain for the service
473                                Domain domain = EcoGridServicesController.getInstance()
474                                                .getServiceDomain(service);
475                                if (domain != null) {
476                                        domainName = domain.getDomain();
477                                        log.debug("domainName=" + domainName);
478                                }
479                        }
480                        if (domainName != null) {
481                                for (int i = 0; i < maxLoginAttempt; i++) {
482                                        try {
483                                                ProxyEntity proxy = AuthenticationManager.getManager()
484                                                                .getProxy(domainName);
485                                                sessionId = proxy.getCredential();
486                                                log.debug("authentication credential=" + sessionId);
487                                                break;
488                                        } catch (AuthenticationException ae) {
489                                                if (ae.getType() == AuthenticationException.USER_CANCEL) {
490                                                        log.info("user cancelled the authentication");
491                                                        break;
492                                                } else {
493                                                        MessageHandler.error("Error authenticating", ae);
494                                                        log.error("The authentication exception is ", ae);
495                                                        ae.printStackTrace();
496                                                        // continue to prompt until we've done it enough
497                                                }
498                                        }
499                                }
500                        }
501                } catch (Exception e) {
502                        log.error("There was a non-authentication exception: ", e);
503                        e.printStackTrace();
504                }
505                return sessionId;
506        }
507
508        /**
509         * 
510         * @param service
511         *       */
512        public Domain getServiceDomain(EcoGridService service) {
513                Domain domain = null;
514
515                try {
516                        // first check if we have the Domain for this service group already
517                        domain = DomainList.getInstance().searchDomainList(
518                                        service.getServiceGroup());
519                        if (domain != null) {
520                                return domain;
521                        }
522                } catch (Exception e) {
523                        // suppose there is no pre-existing domain for this service
524                }
525
526                // look up authentication information, if it exists
527                EcoGridService authService = this.getService(service.getServiceGroup(),
528                                AUTHSERVICETYPE);
529                if (authService != null) {
530                        domain = new Domain();
531                        domain.setDomain(authService.getServiceGroup());
532                        domain.setServiceURL(authService.getEndPoint());
533                        // map the serviceType to the serviceClass for domain
534                        domain
535                                        .setServiceClass(lookupAuthenticationDomainMapping(authService
536                                                        .getServiceType()));
537                        
538                        // look up default user for new/unknown services
539                        ConfigurationProperty ecogridProperty = 
540                                ConfigurationManager.getInstance().getProperty(ConfigurationManager.getModule("ecogrid"));
541                    ConfigurationProperty defaultUser = ecogridProperty.getProperty("defaultUser");
542                    
543                        String username = defaultUser.getProperty("username").getValue();
544                        String password = defaultUser.getProperty("password").getValue();
545                        domain.setUsername(username);
546                        domain.setPassword(password);
547
548                        // add the new domain to the list for future reference
549                        try {
550                                DomainList.getInstance().addDomain(domain);
551                        } catch (Exception e) {
552                                log.error("problem adding new Domain to DomainList: "
553                                                + domain.getDomain());
554                                e.printStackTrace();
555                        }
556
557                }
558
559                return domain;
560        }
561
562        /**
563         * Used for tying together related services Finds the EcoGridService for a
564         * given endpoint
565         * 
566         * @param endPoint
567         *            the URL of the service
568         * @return service object (EcoGridService) that shares the same endPoint
569         */
570        public EcoGridService getService(String endPoint) {
571                EcoGridService service = null;
572                for (int i = 0; i < currentServicesList.size(); i++) {
573                        service = (EcoGridService) currentServicesList.get(i);
574                        if (service.getEndPoint().equals(endPoint)) {
575                                return service;
576                        }
577                }
578                return null;
579        }
580
581        /**
582         * Finds the EcoGridService for a given serviceGroup/serviceType pairing
583         * 
584         * @param serviceGroup
585         *            the name of the group of services to search within
586         * @param serviceType
587         *            the type of service to locate
588         * @return service that meets the input parameters
589         */
590        public EcoGridService getService(String serviceGroup, String serviceType) {
591                EcoGridService service = null;
592                for (int i = 0; i < currentServicesList.size(); i++) {
593                        service = (EcoGridService) currentServicesList.get(i);
594                        if (service.getServiceGroup().equals(serviceGroup)) {
595                                if (service.getServiceType().equals(serviceType)) {
596                                        return service;
597                                }
598                        }
599                }
600                return null;
601        }
602
603        /**
604         * Finds a list of services for a given serviceGroup name
605         * 
606         * @param serviceGroup
607         *            the name of the group of services to search within
608         * @return list of EcoGridService objects for the given serviceGroup
609         */
610        public Vector getServiceGroupList(String serviceGroup) {
611                Vector retList = new Vector();
612                for (int i = 0; i < currentServicesList.size(); i++) {
613                        EcoGridService service = (EcoGridService) currentServicesList
614                                        .get(i);
615                        if (service.getServiceGroup().equals(serviceGroup)) {
616                                retList.add(service);
617                        }
618                }
619                return retList;
620        }
621
622        /**
623         * Finds a list of services for a given serviceType name this is a
624         * convenience method for the more general form that takes a full list of
625         * types
626         * 
627         * @param serviceType
628         *            the name of the serviceType of services to search within
629         * @return list of EcoGridService objects for the given serviceType
630         */
631        public Vector getServicesList(String serviceType) {
632                Vector types = new Vector();
633                types.add(serviceType);
634                return getServicesList(types);
635        }
636
637        /**
638         * Finds a list of services with serviceTypes in the given type list
639         * 
640         * @param serviceTypeList
641         *            list of serviceTypes to match on
642         * @return list of EcoGridService objects for the given serviceTypes
643         */
644        public Vector getServicesList(Vector serviceTypeList) {
645                Vector retList = new Vector();
646                for (int i = 0; i < currentServicesList.size(); i++) {
647                        EcoGridService service = (EcoGridService) currentServicesList
648                                        .get(i);
649                        if (serviceTypeList.contains(service.getServiceType())) {
650                                retList.add(service);
651                        }
652                }
653                return retList;
654        }
655
656        /**
657         * Finds a list of query services this is a convenience method for the more
658         * general form that takes a full list of types
659         * 
660         * @return list of EcoGridService objects for querying
661         */
662        public Vector getQueryServicesList() {
663                Vector types = new Vector();
664                types.add(AUTHENTICATEDQUERYSERVICETYPE);
665                types.add(QUERYSERVICETYPE);
666                return getServicesList(types);
667        }
668
669        /*
670         * Given a service node in configure file, this method will transfer it to
671         * [Selectable]EcoGridService java object
672         */
673        private SelectableEcoGridService generateServiceFromServiceNode(
674                        ConfigurationProperty cp) {
675                SelectableEcoGridService service = null;
676                if (cp != null) {
677                        /*String serviceName = getKidNodeValue(serviceNode,
678                                        MetadataSpecificationInterface.SERVICENAME);
679                        String serviceType = getKidNodeValue(serviceNode,
680                                        MetadataSpecificationInterface.SERVICETYPE);
681                        String endPoint = getKidNodeValue(serviceNode,
682                                        MetadataSpecificationInterface.ENDPOINT);
683                        String selection = getKidNodeValue(serviceNode,
684                                        MetadataSpecificationInterface.SELECTION);
685      String serviceGroup = getKidNodeValue(serviceNode,
686                                        MetadataSpecificationInterface.SERVICEGROUP);
687      */
688      String serviceName = cp.getProperty("serviceName").getValue();
689      String serviceType = cp.getProperty("serviceType").getValue();
690      String endPoint = cp.getProperty("endPoint").getValue();
691      String selection = "false";
692      if(cp.getProperty("selected") != null)
693      {
694        selection = cp.getProperty("selected").getValue();
695      }
696      String serviceGroup = cp.getProperty("serviceGroup").getValue();
697                        
698                        // String serviceClassification = getKidNodeValue(serviceNode,
699                        // MetadataSpecificationInterface.SERVICECLASSIFICATION);
700                        // String description = getKidNodeValue(serviceNode,
701                        // MetadataSpecificationInterface.DESCRIPTION);
702
703                        // System.out.println("the selection for service is "+selection);
704                        boolean selected = false;
705                        if (selection != null && selection.equals(TRUE)) {
706                                selected = true;
707                        }
708                        SelectableDocumentType[] documentTypeList = getDocumentList(cp);
709
710                        // generate a service java object
711                        try {
712                                service = new SelectableEcoGridService();
713                                SelectableServiceName name = new SelectableServiceName();
714                                name.setServiceName(serviceName);
715                                name.setIsSelected(selected);
716                                service.setSelectableServiceName(name);
717                                service.setServiceName(serviceName);
718                                service.setServiceType(serviceType);
719                                service.setEndPoint(endPoint);
720                                service.setSelectableDocumentTypeList(documentTypeList);
721                                service.setDocumentTypeList(documentTypeList);
722                                service.setServiceGroup(serviceGroup);
723                                // service.setServiceClassification(serviceClassification);
724                                // service.setDescription(description);
725
726                        }// try
727                        catch (Exception e) {
728                                service = null;
729                                log.debug("couldn't get a service from configure file ", e);
730                        }// catch
731                }// if
732                return service;
733        }// handleSericeNode
734
735        /*
736         * Give a parentnode and kid node name, it will return the kid node value
737         */
738        private String getKidNodeValue(Node parentNode, String kidName) {
739                String nodeValue = null;
740                try {
741                        NodeList nodeList = XPathAPI.selectNodeList(parentNode, kidName);
742                        if (nodeList != null && nodeList.getLength() > 0) {
743                                Node node = nodeList.item(0);
744                                if (node != null && node.getFirstChild() != null) {
745                                        nodeValue = node.getFirstChild().getNodeValue();
746                                }// if
747                        }// if
748                }// try
749                catch (Exception e) {
750                        if (isDebugging) {
751                                log.debug("Couldn't find " + kidName, e);
752                        }
753                } // catch
754                if (isDebugging) {
755                        log.debug("The value of " + kidName + " is " + nodeValue);
756                }
757                return nodeValue;
758        }// getKideNodeValue
759
760        /*
761         * Given a service node and return a documentType list array
762         */
763        private SelectableDocumentType[] getDocumentList(ConfigurationProperty cp) 
764  {
765                SelectableDocumentType[] documentList = null;
766                Vector documentVector = new Vector();
767                //NodeList documentTypeNodeList = null;
768    List documentTypeList = cp.getProperties("documentType");
769                //try {
770                        // get documenttype node list
771                        //documentTypeNodeList = XPathAPI.selectNodeList(serviceNode,
772                        //              MetadataSpecificationInterface.DOCUMENTTYPE);
773      
774                //} catch (Exception e) {
775                //      log.debug("Couldn't find document list in config", e);
776                //      return documentList;
777                //}// catch
778    if(documentTypeList == null || documentTypeList.size() == 0)
779    {
780      return documentList;
781    }
782
783                if (documentTypeList != null && documentTypeList.size() > 0) 
784    {
785                        int size = documentTypeList.size();
786                        for (int i = 0; i < size; i++) 
787      {
788                                boolean selected = true;
789                                /*Node documentTypeNode = documentTypeNodeList.item(i);
790                                String namespace = getKidNodeValue(documentTypeNode,
791                                                MetadataSpecificationInterface.NAMESPACE);
792                                String label = getKidNodeValue(documentTypeNode,
793                                                MetadataSpecificationInterface.LABEL);
794                                String selectedStr = getKidNodeValue(documentTypeNode,
795                                                MetadataSpecificationInterface.SELECTION);
796        */
797        ConfigurationProperty documentTypeProp = (ConfigurationProperty)documentTypeList.get(i);
798        String namespace = documentTypeProp.getProperty("namespace").getValue();
799        String label = documentTypeProp.getProperty("label").getValue();
800        String selectedStr = documentTypeProp.getProperty("selected").getValue();
801        
802                                // System.out.println("the selection string for namespace
803                                // "+namespace+" is "+selectedStr);
804                                if (selectedStr != null && selectedStr.equals(FALSE)) {
805                                        selected = false;
806                                }
807
808                                SelectableDocumentType type = null;
809                                try {
810                                        type = new SelectableDocumentType(namespace, label,
811                                                        selected);
812                                } catch (Exception e) {
813                                        log.debug("Couldn't generate a document type", e);
814                                        continue;
815                                }
816                                // the vector will stored the document type
817                                documentVector.add(type);
818                        } // for
819                        // transfer a vector to array.
820                        int length = documentVector.size();
821                        documentList = new SelectableDocumentType[length];
822                        for (int i = 0; i < length; i++) 
823      {
824                                documentList[i] = (SelectableDocumentType) documentVector
825                                                .elementAt(i);
826                        } // for
827
828                } // if
829
830                return documentList;
831        }// getDocumentList
832
833        /*
834         * Judge if a given service already existed in a service list. The key is
835         * endpoint. If it is duplicate service, index in vector will be returned
836         * Otherwise, -1 will be returned.
837         */
838        private static int isDuplicateService(EcoGridService service,
839                        Vector serviceList) throws InvalidEcoGridServiceException {
840                int duplicateIndex = -1;
841                if (service == null || serviceList == null) {
842                        throw new InvalidEcoGridServiceException(
843                                        "The service or service list is"
844                                                        + " null and couldn't judge if the given service is duplicate in list");
845                }
846                String givenEndPoint = service.getEndPoint();
847                if (givenEndPoint == null || givenEndPoint.trim().equals("")) {
848                        throw new InvalidEcoGridServiceException(
849                                        "The given service doesn't have "
850                                                        + "endpoint and couldn't judge if the given service is duplicate in list");
851                }
852                int size = serviceList.size();
853                for (int i = 0; i < size; i++) {
854                        EcoGridService currentService = (EcoGridService) serviceList
855                                        .elementAt(i);
856                        String currentEndPoint = currentService.getEndPoint();
857                        if (currentEndPoint != null
858                                        && currentEndPoint.equals(givenEndPoint)) {
859                                duplicateIndex = i;
860                                break;
861                        }// if
862                }// for
863                return duplicateIndex;
864        }// isDuplicateService
865
866        /**
867         * Method to get selected service with selected document types from service
868         * list vector. If a service selected, but without any selected documents,
869         * this service couldn't be in this vector
870         */
871        public Vector getSelectedServicesList() {
872                selectedSearchingServicesList = new Vector();
873                for (int i = 0; i < currentServicesList.size(); i++) {
874                        EcoGridService service = (EcoGridService) currentServicesList
875                                        .elementAt(i);
876                        if (service != null) {
877                                SelectableEcoGridService selectableService = (SelectableEcoGridService) service;
878                                if (selectableService.getSelectableServiceName()
879                                                .getIsSelected() == true) {
880                                        SelectableDocumentType[] docList = selectableService
881                                                        .getSelectedDocumentTypeList();
882                                        if (docList != null && docList.length != 0) {
883                                                // System.out.println("Add service !!!!!!!!!!!!!!!!! " +
884                                                // selectableService.getEndPoint() +"into selected
885                                                // service list");
886                                                selectedSearchingServicesList.add(selectableService);
887                                        }
888                                }
889                        }
890                }
891                return this.selectedSearchingServicesList;
892        }
893        
894        public void readServices() {
895
896                File saveFile = new File(_saveFileName);
897
898                if (saveFile.exists()) {
899                        try {
900                                InputStream is = new FileInputStream(saveFile);
901                                ObjectInput oi = new ObjectInputStream(is);
902                                Object newObj = oi.readObject();
903                                oi.close();
904
905                                Vector<EcoGridService> servs = (Vector<EcoGridService>) newObj;
906                                for (EcoGridService egs : servs) {
907                                        addService(egs);
908                                }
909
910                                return;
911                        } catch (Exception e1) {
912                                // problem reading file, try to delete it
913                                log.warn("Exception while reading EcoGridServices file: "
914                                                + e1.getMessage());
915                                try {
916                                        saveFile.delete();
917                                } catch (Exception e2) {
918                                        log.warn("Unable to delete EcoGridServices file: "
919                                                        + e2.getMessage());
920                                }
921                        }
922                } else {
923                        // initialize default services from the Config.xml file
924                        readServicesFromConfig();
925                }
926        }
927
928        /*
929         * Read query service from configure file and put the service into a vector
930         * 
931         * If any updates are done on Config, be sure to call this method again to
932         * refresh with the newest values
933         */
934        private void readServicesFromConfig() {
935                // reset the vector
936                currentServicesList = new Vector();
937
938    ConfigurationProperty ecogridProperty = ConfigurationManager.getInstance()
939      .getProperty(ConfigurationManager.getModule("ecogrid"));
940    List servicesList = ecogridProperty.getProperties("servicesList.service");
941    
942                // find service type is ecogrid query
943                if (servicesList != null && servicesList.size() > 0) 
944    {
945                        int length = servicesList.size();
946                        for (int i = 0; i < length; i++) 
947      {
948        ConfigurationProperty cp = (ConfigurationProperty)servicesList.get(i);
949                                //Node serviceTypeNode = typeList.item(i);
950                                //if (serviceTypeNode != null
951                                //              && serviceTypeNode.getFirstChild() != null) {
952                                //      String serviceTypeString = serviceTypeNode.getFirstChild()
953                                //                      .getNodeValue();
954        String serviceTypeString = cp.getProperty("serviceType").getValue();
955                                        if (isDebugging) {
956                                                log.debug("The service type from configure file is "
957                                                                + serviceTypeString);
958                                        }
959                                        // if this a valid service type, transfer the service
960                                        // node(servicetype's parent
961                                        // node) into java object and put it into service list
962                                        if (serviceTypeString != null
963                                                        && serviceTypes.contains(serviceTypeString)) 
964          {
965                                                //Node queryServiceNode = serviceTypeNode.getParentNode();
966                                                //SelectableEcoGridService service = generateServiceFromServiceNode(queryServiceNode);
967            SelectableEcoGridService service = generateServiceFromServiceNode(cp);
968                                                if (service != null) 
969            {
970                                                        // check duplicate
971                                                        int duplicateIndex = -2;
972                                                        try {
973                                                                duplicateIndex = isDuplicateService(service,
974                                                                                currentServicesList);
975                                                        } catch (InvalidEcoGridServiceException e) {
976                                                                log
977                                                                                .debug(
978                                                                                                "The error for checking duplicate ecogrid service in readQueryServiceFromConfig is ",
979                                                                                                e);
980                                                        }
981                                                        // if it is not duplicate, the index should be -1
982                                                        if (duplicateIndex == -1) 
983              {
984                                                                if (isDebugging) 
985                {
986                                                                        log.debug("read service "
987                                                                                        + service.getServiceName()
988                                                                                        + " from config file to vector");
989                                                                }
990                                                                currentServicesList.add(service);
991                                                        }
992                                                }
993                                        }// if
994                                }// if
995                        }// for
996  }     
997  
998        public void deleteServicesFile() {
999                File saveFile = new File(_saveFileName);
1000                if (saveFile.exists()) {
1001                        if (isDebugging)
1002                                log.debug("delete " + saveFile);
1003                        saveFile.delete();
1004                }
1005        }
1006        
1007        public void writeServices() throws Exception {
1008                File saveFile = new File(_saveFileName);
1009                if (saveFile.exists()) {
1010                        if (isDebugging)
1011                                log.debug("delete " + saveFile);
1012                        saveFile.delete();
1013                }
1014                try {
1015                        OutputStream os = new FileOutputStream(saveFile);
1016                        ObjectOutputStream oos = new ObjectOutputStream(os);
1017                        oos.writeObject(currentServicesList);
1018                        oos.flush();
1019                        if (isDebugging) {
1020                                log.debug("wrote " + saveFile);
1021                        }
1022                } catch (FileNotFoundException e) {
1023                        e.printStackTrace();
1024                } catch (IOException e) {
1025                        e.printStackTrace();
1026                }
1027        }
1028
1029        /**
1030         * Print out every service in the list
1031         */
1032        public void print() {
1033                if (currentServicesList != null) {
1034                        int size = currentServicesList.size();
1035                        for (int i = 0; i < size; i++) {
1036                                EcoGridService service = (EcoGridService) currentServicesList
1037                                                .elementAt(i);
1038                                service.print();
1039                                log.debug("----------------");
1040                        }// for
1041                }// if
1042        }// print
1043
1044        /**
1045         * Filters out the non-query services given a list of EcoGridServices
1046         * 
1047         * @param list
1048         *            of many different kinds of services
1049         * @return list of EcoGridService objects for querying
1050         */
1051        public static Vector filterQueryServicesList(Vector inputServices) {
1052                Vector types = new Vector();
1053                types.add(AUTHENTICATEDQUERYSERVICETYPE);
1054                types.add(QUERYSERVICETYPE);
1055
1056                Vector retList = new Vector();
1057                for (int i = 0; i < inputServices.size(); i++) {
1058                        EcoGridService service = (EcoGridService) inputServices.get(i);
1059                        if (types.contains(service.getServiceType())) {
1060                                retList.add(service);
1061                        }
1062                }
1063                return retList;
1064        }
1065
1066        public static Vector registryEntries2EcogridServices(
1067                        RegistryEntryType[] list, boolean selectable) {
1068                Vector serviceVector = new Vector();
1069                if (list == null) {
1070                        log.debug("The registry entry  list is null");
1071                        return serviceVector;
1072                }
1073                int length = list.length;
1074                for (int i = 0; i < length; i++) {
1075                        RegistryEntryType registryType = list[i];
1076                        String serviceName = registryType.getServiceName();
1077                        log.debug("The service name from registry is " + serviceName);
1078                        String serviceType = registryType.getServiceType();
1079                        log.debug("The service type from registry is " + serviceType);
1080                        String endpoint = registryType.getEndPoint();
1081                        log.debug("Find the service " + endpoint + " in registry");
1082                        String serviceGroup = registryType.getServiceGroup();
1083                        log.debug("the service group is " + serviceGroup + " in registry");
1084                        RegistryEntryTypeDocumentType[] typeList = registryType
1085                                        .getDocumentType();
1086
1087                        DocumentType[] docTypeList = null;
1088                        EcoGridService service = new EcoGridService();
1089                        try {
1090                                service.setServiceName(serviceName);
1091                                service.setServiceType(serviceType);
1092                                service.setEndPoint(endpoint);
1093                                service.setServiceGroup(serviceGroup);
1094                                docTypeList = transferRegDocTypeArray(typeList);
1095                                service.setDocumentTypeList(docTypeList);
1096                                if (docTypeList == null || docTypeList.length == 0) {
1097                                        log.debug("Document type list is null or empty");
1098                                        // continue;
1099                                }
1100                        } catch (Exception e) {
1101                                log.debug("Could not set service  " + e.getMessage());
1102                                continue;
1103                        }
1104                        log.debug("Adding service " + endpoint + " into the vector");
1105                        if (selectable) {
1106                                // make it selectable
1107                                service = new SelectableEcoGridService(service);
1108                        }
1109                        serviceVector.add(service);
1110                }//
1111                return serviceVector;
1112        }// transferRegEntriesArrayToVector
1113
1114        private static DocumentType[] transferRegDocTypeArray(
1115                        RegistryEntryTypeDocumentType[] regTypeList) throws Exception {
1116                DocumentType[] docTypeList = null;
1117                if (regTypeList == null) {
1118                        return docTypeList;
1119                }// if
1120                int length = regTypeList.length;
1121                Vector tmp = new Vector();
1122                for (int i = 0; i < length; i++) {
1123                        RegistryEntryTypeDocumentType regDocType = regTypeList[i];
1124                        String namespace = regDocType.getNamespace();
1125                        String label = regDocType.getLabel();
1126                        try {
1127                                DocumentType type = new DocumentType(namespace, label);
1128                                tmp.add(type);
1129                        } catch (Exception e) {
1130                                log.debug("Could not create document type ", e);
1131                                throw e;
1132                        }
1133                }// for
1134                // transfer the tmp vector to an array
1135                int size = tmp.size();
1136                docTypeList = new DocumentType[size];
1137                for (int i = 0; i < size; i++) {
1138                        docTypeList[i] = (DocumentType) tmp.elementAt(i);
1139                }// for
1140                return docTypeList;
1141        }// transferRegDocTypeArray
1142
1143}// EcoGridServiceController