Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive/sources/HeuristicLab.Hive.New/HeuristicLab.Clients.Hive/3.3/ServiceClients/ServiceClientFactory.cs @ 4649

Last change on this file since 4649 was 4649, checked in by cneumuel, 13 years ago
  • moved db-context into datalayer
  • businesslayer only defines the transaction-scope
  • removed contextfactory
  • implemented convert-methods
  • made naming in db and domainobjects more consistent
  • changed wcf-service to be http-only (for now)

(#1233)

File size: 6.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.ServiceModel;
24using HeuristicLab.Common;
25using HeuristicLab.Tracing;
26using HeuristicLab.Services.Hive.Common;
27using System.ServiceModel.Description;
28
29namespace HeuristicLab.Clients.Hive {
30  public class ServiceClientFactory<T> {
31    private static object locker = new object();
32
33    private string endpointName;
34
35    private string username;
36    public string Username {
37      get { return username; }
38      set {
39        if(username != value) {
40          username = value;
41          this.factory = null;
42        }
43      }
44    }
45
46    private string password;
47    public string Password {
48      set {
49        if (password != value) {
50          password = value;
51          this.factory = null;
52        }
53      }
54    }
55
56    private ChannelFactory<T> factory = null;
57    private Disposable<T> disposableService = null;
58    private int requestCount = 0;
59
60    public ServiceClientFactory(string username, string password, string endpointName) {
61      this.username = username;
62      this.password = password;
63      this.endpointName = endpointName;
64    }
65
66    private T CreateFacade(string endpointName) {
67      lock (locker) {
68        try {
69          return CreateChannel(endpointName);
70        }
71        catch (EndpointNotFoundException ex) {
72          OnExceptionOccured(ex);
73        }
74        return default(T);
75      }
76    }
77
78    protected virtual T CreateChannel(string endpointName) {
79      if (factory == null) {
80        factory = new ChannelFactory<T>(endpointName);
81        factory.Credentials.UserName.UserName = username;
82        factory.Credentials.UserName.Password = password;
83        factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
84      }
85     
86      return factory.CreateChannel();
87    }
88
89    public Disposable<T> GetService() {
90      lock (locker) {
91        requestCount++;
92        Logger.Debug("Request for ServiceProxy (count: " + requestCount + ")");
93        if (disposableService != null) {
94          if (GetServiceState() == CommunicationState.Faulted) {
95            DisposeService();
96          }
97        }
98        if (disposableService == null) {
99          disposableService = new Disposable<T>(CreateFacade(this.endpointName));
100          RegisterServiceEvents();
101        }       
102        return disposableService;
103      }
104    }
105
106    private void RegisterServiceEvents() {
107      disposableService.Disposing += disposableService_Disposing;
108      ((ICommunicationObject)disposableService.Obj).Faulted += new EventHandler(WcfServicePool_Faulted);
109    }
110
111    private void DeregisterServiceEvents() {
112      disposableService.Disposing -= disposableService_Disposing;
113      ((ICommunicationObject)disposableService.Obj).Faulted -= new EventHandler(WcfServicePool_Faulted);
114    }
115
116    private CommunicationState GetServiceState() {
117      return ((ICommunicationObject)disposableService.Obj).State;
118    }
119
120    void WcfServicePool_Faulted(object sender, EventArgs e) {
121      OnExceptionOccured(new CommunicationException(e.ToString()));
122    }
123
124    private void disposableService_Disposing(object sender, EventArgs<T> e) {
125      DisposeService();
126    }
127
128    public void DisposeService() {
129      lock (locker) {
130        requestCount--;
131        Logger.Debug("Disposing ServiceProxy (count: " + requestCount + ")");
132        if (requestCount == 0) {
133          try {
134            DeregisterServiceEvents();
135            ServiceUtil.DisposeWcfClient((ICommunicationObject)disposableService.Obj);
136          }
137          catch (Exception e) {
138            OnExceptionOccured(e);
139          }
140          finally {
141            disposableService = null;
142          }
143        } else if (requestCount < 0) {
144          throw new ServiceClientFactoryException("requestCount cannot be less than 0.");
145        }
146      }
147    }
148
149    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
150    private void OnExceptionOccured(Exception e) {
151      lock (locker) {
152        var handler = ExceptionOccured;
153        if (handler != null) handler(this, new EventArgs<Exception>(e));
154      }
155    }
156  }
157
158  public static class ServiceUtil {
159    /// <summary>
160    /// This method changes the endpoint-address while preserving the identity-certificate defined in the config file
161    /// </summary>
162    public static void ReplaceEndpointAddress(ServiceEndpoint endpoint, string hostAddress) {
163      EndpointAddressBuilder builder = new EndpointAddressBuilder(endpoint.Address);
164      UriBuilder uriBuilder = new UriBuilder(builder.Uri);
165      uriBuilder.Host = hostAddress;
166      builder.Uri = uriBuilder.Uri;
167      endpoint.Address = builder.ToEndpointAddress();
168    }
169
170    /// <summary>
171    /// Safely disposes a WCF client proxy object
172    /// </summary>
173    /// <param name="obj"></param>
174    public static void DisposeWcfClient(ICommunicationObject obj) {
175      if (obj != null) {
176        if (obj.State != CommunicationState.Faulted &&
177            obj.State != CommunicationState.Closed) {
178          try { obj.Close(); }
179          catch (CommunicationObjectFaultedException) { obj.Abort(); }
180          catch (TimeoutException) { obj.Abort(); }
181          catch (Exception e) {
182            obj.Abort();
183            Logger.Error(e);
184          }
185        } else
186          obj.Abort();
187      }
188    }
189  }
190}
Note: See TracBrowser for help on using the repository browser.