// $Id$
#include "OCSChannelManager.h"
+#include "NSURL+OCS.h"
+#include <GDLAccess/EOAdaptor.h>
+#include <GDLAccess/EOAdaptorContext.h>
+#include <GDLAccess/EOAdaptorChannel.h>
#include "common.h"
@implementation OCSChannelManager
+static BOOL debugOn = YES;
+
++ (NSString *)adaptorNameForURLScheme:(NSString *)_scheme {
+ // TODO: map scheme to adaptors (eg 'postgresql://' to PostgreSQL72
+ return @"PostgreSQL72";
+}
+
++ (id)defaultChannelManager {
+ static OCSChannelManager *cm = nil;
+ if (cm == nil)
+ cm = [[self alloc] init];
+ return cm;
+}
+
+- (id)init {
+ if ((self = [super init])) {
+ self->urlToAdaptor = [[NSMutableDictionary alloc] initWithCapacity:4];
+ }
+ return self;
+}
+
- (void)dealloc {
+ [self->urlToAdaptor release];
[super dealloc];
}
+/* DB key */
+
+- (NSString *)databaseKeyForURL:(NSURL *)_url {
+ /*
+ We need to build a proper key that omits passwords and URL path components
+ which are not required.
+ */
+ NSString *key;
+
+ key = [NSString stringWithFormat:@"%@\n%@\n%@\n%@",
+ [_url host], [_url port],
+ [_url user], [_url ocsDatabaseName]];
+ return key;
+}
+
+/* adaptors */
+
+- (NSDictionary *)connectionDictionaryForURL:(NSURL *)_url {
+ [self debugWithFormat:@"build connection dictionary for URL: %@", _url];
+ return nil;
+}
+
+- (EOAdaptor *)adaptorForURL:(NSURL *)_url {
+ EOAdaptor *adaptor;
+ NSString *adaptorName;
+ NSString *key;
+ NSDictionary *condict;
+
+ if (_url == nil)
+ return nil;
+ if ((key = [self databaseKeyForURL:_url]) == nil)
+ return nil;
+ if ((adaptor = [self->urlToAdaptor objectForKey:key]) != nil) {
+ [self debugWithFormat:@"using cached adaptor: %@", adaptor];
+ return adaptor; /* cached :-) */
+ }
+
+ [self debugWithFormat:@"creating new adaptor for URL: %@", _url];
+
+ adaptorName = [[self class] adaptorNameForURLScheme:[_url scheme]];
+ if ([adaptorName length] == 0) {
+ [self logWithFormat:@"ERROR: cannot handle URL: %@", _url];
+ return nil;
+ }
+
+ condict = [self connectionDictionaryForURL:_url];
+
+ if ((adaptor = [EOAdaptor adaptorWithName:adaptorName]) == nil) {
+ [self logWithFormat:@"ERROR: did not find adaptor '%@' for URL: %@",
+ adaptorName, _url];
+ return nil;
+ }
+
+ [adaptor setConnectionDictionary:condict];
+ [self->urlToAdaptor setObject:adaptor forKey:key];
+ return adaptor;
+}
+
+/* channels */
+
+- (EOAdaptorChannel *)_createChannelForURL:(NSURL *)_url {
+ EOAdaptor *adaptor;
+ EOAdaptorContext *adContext;
+ EOAdaptorChannel *adChannel;
+
+ if ((adaptor = [self adaptorForURL:_url]) == nil)
+ return nil;
+
+ if ((adContext = [adaptor createAdaptorContext]) == nil) {
+ [self logWithFormat:@"ERROR: could not create adaptor context!"];
+ return nil;
+ }
+ if ((adChannel = [adContext createAdaptorChannel]) == nil) {
+ [self logWithFormat:@"ERROR: could not create adaptor channel!"];
+ return nil;
+ }
+ return adChannel;
+}
+
+- (EOAdaptorChannel *)acquireOpenChannelForURL:(NSURL *)_url {
+ // TODO: naive implementation, add pooling!
+ EOAdaptorChannel *channel;
+
+ if ((channel = [self _createChannelForURL:_url]) == nil)
+ return channel;
+
+ if ([channel isOpen])
+ return [channel retain];
+
+ if (![channel openChannel]) {
+ [self logWithFormat:@"could not open channel %@ for URL: %@",
+ channel, _url];
+ return nil;
+ }
+
+ return [channel retain];
+}
+- (void)releaseChannel:(EOAdaptorChannel *)_channel {
+ // TODO: naive implementation, add pooling!
+ if ([_channel isOpen])
+ [_channel closeChannel];
+
+ [_channel release];
+}
+
+/* debugging */
+
+- (BOOL)isDebuggingEnabled {
+ return debugOn;
+}
+
+/* description */
+
+- (NSString *)description {
+ NSMutableString *ms;
+
+ ms = [NSMutableString stringWithCapacity:256];
+ [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+
+ [ms appendFormat:@" #adaptors=%d", [self->urlToAdaptor count]];
+
+ [ms appendString:@">"];
+ return ms;
+}
+
@end /* OCSChannelManager */