--- /dev/null
+// $Id$
+
+#include <NGObjWeb/SoComponent.h>
+
+@class EOAdaptorChannel;
+
+@interface DDatabase : SoComponent
+{
+ EOAdaptorChannel *channel;
+ NSArray *tableNames;
+ id item;
+}
+
+@end
+
+#include "DSoDatabase.h"
+#include "common.h"
+
+@implementation DDatabase
+
+- (void)dealloc {
+ if ([self->channel isOpen])
+ [self->channel closeChannel];
+ [self->channel release];
+
+ [self->tableNames release];
+ [self->item release];
+ [super dealloc];
+}
+
+/* notifications */
+
+- (void)sleep {
+ if ([self->channel isOpen])
+ [self->channel closeChannel];
+
+ [super sleep];
+}
+
+/* DB things */
+
+- (EOAdaptor *)adaptor {
+ return [(DSoDatabase *)[self clientObject] adaptorInContext:[self context]];
+}
+
+- (EOAdaptorChannel *)channel {
+ EOAdaptorContext *ctx;
+
+ if (self->channel)
+ return self->channel;
+
+ ctx = [[self adaptor] createAdaptorContext];
+ self->channel = [[ctx createAdaptorChannel] retain];
+ if (![self->channel openChannel]) {
+ [self->channel release];
+ self->channel = nil;
+ }
+
+ return self->channel;
+}
+
+/* accessors */
+
+- (void)setItem:(id)_item {
+ ASSIGN(self->item, _item);
+}
+- (id)item {
+ return self->item;
+}
+
+- (NSArray *)tableNames {
+ if (self->tableNames == nil)
+ self->tableNames = [[[self channel] describeTableNames] copy];
+ return self->tableNames;
+}
+
+- (NSString *)tabLink {
+ // this suxx, a) we need to write code, b) we need to attach the / manually
+ return [[self item] stringByAppendingString:@"/"];
+}
+
+@end /* DDatabase */
--- /dev/null
+<?xml version='1.0' standalone='yes'?>
+<var:component className="Frame"
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:var="http://www.skyrix.com/od/binding"
+ xmlns:const="http://www.skyrix.com/od/constant"
+>
+
+Host: <a href=".."><var:string value="clientObject.hostName"/></a><br />
+Port: <var:string value="clientObject.port"/><br />
+DB: <var:string value="clientObject.databaseName"/><br />
+
+<h4>Tables</h4>
+<var:foreach list="tableNames" item="item">
+ <li><a var:href="tabLink"><var:string value="item" /></a></li>
+</var:foreach>
+
+</var:component>
--- /dev/null
+// $Id$
+
+#include <NGObjWeb/SoComponent.h>
+
+@class EOAdaptorChannel;
+
+@interface DDatabaseManager : SoComponent
+{
+ EOAdaptorChannel *channel;
+ NSArray *databaseNames;
+ id item;
+}
+
+@end
+
+#include "DSoHost.h"
+#include "DSoDatabaseManager.h"
+#include "common.h"
+
+@interface EOAdaptorChannel(ModelFetching)
+- (NSArray *)describeDatabaseNames;
+@end
+
+@implementation DDatabaseManager
+
+- (void)dealloc {
+ if ([self->channel isOpen])
+ [self->channel closeChannel];
+ [self->channel release];
+
+ [self->databaseNames release];
+ [self->item release];
+ [super dealloc];
+}
+
+/* notifications */
+
+- (void)sleep {
+ if ([self->channel isOpen])
+ [self->channel closeChannel];
+
+ [super sleep];
+}
+
+/* DB things */
+
+- (EOAdaptor *)adaptor {
+ return [[(DSoDatabaseManager *)[self clientObject]
+ host] adaptorInContext:[self context]];
+}
+
+- (EOAdaptorChannel *)channel {
+ EOAdaptorContext *ctx;
+
+ if (self->channel)
+ return self->channel;
+
+ ctx = [[self adaptor] createAdaptorContext];
+ self->channel = [[ctx createAdaptorChannel] retain];
+ if (![self->channel openChannel]) {
+ [self->channel release];
+ self->channel = nil;
+ }
+
+ return self->channel;
+}
+
+/* accessors */
+
+- (void)setItem:(id)_item {
+ ASSIGN(self->item, _item);
+}
+- (id)item {
+ return self->item;
+}
+
+- (NSArray *)databaseNames {
+ if (self->databaseNames == nil)
+ self->databaseNames = [[[self channel] describeDatabaseNames] copy];
+ return self->databaseNames;
+}
+
+- (NSString *)dbLink {
+ // this suxx, a) we need to write code, b) we need to attach the / manually
+ return [[self item] stringByAppendingString:@"/"];
+}
+
+@end /* DDatabaseManager */
--- /dev/null
+<?xml version='1.0' standalone='yes'?>
+<var:component className="Frame"
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:var="http://www.skyrix.com/od/binding"
+ xmlns:const="http://www.skyrix.com/od/constant"
+>
+
+Host: <var:string value="clientObject.host.hostName"/><br />
+Port: <var:string value="clientObject.host.port"/><br />
+
+<h4>Databases</h4>
+<var:foreach list="databaseNames" item="item">
+ <li><a var:href="dbLink"><var:string value="item" /></a></li>
+</var:foreach>
+
+<hr />
+<a href="../Users/">Users</a>
+
+</var:component>
// Note: it suxx that we need to write code for that ...
- (NSString *)dbLink {
- return [@"Databases/" stringByAppendingString:[self item]];
+ return [[@"Databases/" stringByAppendingString:[self item]]
+ stringByAppendingString:@"/"];
}
- (NSString *)userLink {
- return [@"Users/" stringByAppendingString:[self item]];
+ return [[@"Users/" stringByAppendingString:[self item]]
+ stringByAppendingString:@"/"];
}
@end /* DHostView */
- (id)initWithHostName:(NSString *)_hostname port:(int)_port
databaseName:(NSString *)_dbname;
+/* support */
+
+- (EOAdaptor *)adaptorInContext:(WOContext *)_ctx;
+
@end
#endif /* __dbd_DSoDatabase_H__ */
// $Id$
#include "DSoDatabase.h"
+#include "DSoTable.h"
#include "DSoAuthenticator.h"
#include "common.h"
+// TODO: PG databases do have an owner!
+// TODO: PG databases have an ACL
+
@implementation DSoDatabase
- (id)initWithHostName:(NSString *)_hostname port:(int)_port
return self->databaseName;
}
+/* support */
+
+- (EOAdaptor *)adaptorInContext:(WOContext *)_ctx {
+ return [self adaptorForHostName:[self hostName] port:[self port]
+ databaseName:[self databaseName] inContext:_ctx];
+}
+
/* authentication */
- (id)authenticatorInContext:(id)_ctx {
port:[self port] databaseName:[self databaseName]];
}
+/* name lookup */
+
+- (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag {
+ id obj;
+
+ /*
+ Note: acquire:NO - otherwise acquired stuff will override the stuff
+ below!
+ */
+ if ((obj = [super lookupName:_key inContext:_ctx acquire:NO]))
+ return obj;
+
+ obj = [[DSoTable alloc] initWithName:_key inContainer:self];
+ return [obj autorelease];
+}
+
@end /* DSoDatabase */
- (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag {
id obj;
+ /*
+ Note: acquire:NO - otherwise acquired stuff will override the stuff
+ below!
+ */
if ((obj = [super lookupName:_key inContext:_ctx acquire:NO]))
return obj;
- // TODO: create DSoDatabase object
obj = [[DSoDatabase alloc] initWithHostName:[self->host hostName]
port:[self->host port]
databaseName:_key];
}
#endif
+/* OSX hack */
+
+- (id)valueForUndefinedKey:(NSString *)_key {
+ [self debugWithFormat:@"queried undefined key: '%@'", _key];
+ return nil;
+}
+
+- (BOOL)isCollection {
+ return YES;
+}
+
@end /* DSoObject */
#include "DSoObject.h"
+@class NSString;
+@class DSoDatabase;
+
@interface DSoTable : DSoObject
{
+ DSoDatabase *database;
+ NSString *tableName;
}
+- (id)initWithName:(NSString *)_name inContainer:(id)_container;
+
@end
#endif /* __dbd_DSoTable_H__ */
// $Id$
#include "DSoTable.h"
+#include "DSoDatabase.h"
#include "common.h"
@implementation DSoTable
+- (id)initWithName:(NSString *)_name inContainer:(id)_container {
+ if ((self = [super init])) {
+ self->tableName = [_name copy];
+ self->database = [_container retain];
+ }
+ return self;
+}
+
- (void)dealloc {
+ [self->database release];
+ [self->tableName release];
[super dealloc];
}
+/* support */
+
+- (EOAdaptor *)adaptorInContext:(WOContext *)_ctx {
+ return [self->database adaptorInContext:_ctx];
+}
+
@end /* DSoTable */
\
DHostView.m \
DDatabaseManager.m \
+ DDatabase.m \
dbd_RESOURCE_FILES += \
Version \
\
DHostView.wox \
DDatabaseManager.wox \
+ DDatabase.wox \
dbd_WEBSERVER_RESOURCE_FILES +=
Tricks used
===========
+- *always* remember that SOPE objects which are looked up in the traversal
+ process are conceptually *UI* objects, not datamodel objects (though this
+ might be done for simplistic applications)
+ - the idea is: the URL is UI
+
- small hack in MainPage.m to make a redirect to a "valid" WO URL if the
request-handler-key is missing
- should be made by SOPE itself?
- in theory SOPE should make a redirect to the default method, not sure why
this isn't happening
- ZideStore always makes such a redirect?
+ - maybe any folderish object when being at the end of a traversal stack
+ should check that?
- acquisition
- if you override -lookupName:inContext:acquire:, you should probably
- note that acquisition is also done on the traversal path! if the lookup
returns nil on an URL path being traversed, URL acquisition will occure
(except on non-acquisition protocols like WebDAV)
+
+- baseURL
+ - calculation of base URL requires you to either override -baseURLInContext:
+ or implement -container and -nameInContainer
+
+- enabling WebDAV
+ - implemented -isCollection in DSoObject
+ - per default the baseURL is broken - you need to ensure that it returns
+ a proper value, see above
+ - if the baseURL doesn't match the requested WebDAV URL, we run into
+ problems, maybe need to fix something in the SOPE WebDAV layer here
DSoDatabase = {
superclass = "DSoObject";
methods = {
+ "index" = {
+ protectedBy = "View";
+ pageName = "DDatabase";
+ };
};
};
DSoDatabaseManager = {