1/*
2   EOAdaptorChannel.m
3
4   Copyright (C) 1996 Free Software Foundation, Inc.
5
6   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
7   Date: October 1996
8
9   This file is part of the GNUstep Database Library.
10
11   This library is free software; you can redistribute it and/or
12   modify it under the terms of the GNU Library General Public
13   License as published by the Free Software Foundation; either
14   version 2 of the License, or (at your option) any later version.
15
16   This library is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19   Library General Public License for more details.
20
21   You should have received a copy of the GNU Library General Public
22   License along with this library; see the file COPYING.LIB.
23   If not, write to the Free Software Foundation,
24   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25*/
26// $Id: EOFaultHandler.m 1 2004-08-20 10:38:46Z znek $
27
28#include "EOFaultHandler.h"
29#include "EOFault.h"
30#include "common.h"
31
32#if (defined(__GNU_LIBOBJC__) && (__GNU_LIBOBJC__ >= 20100911)) || defined(APPLE_RUNTIME) || defined(__GNUSTEP_RUNTIME__)
33#  define METHOD_NULL NULL
34#  define class_get_super_class class_getSuperclass
35#  define object_is_instance(object) (object!=nil?YES:NO)
36#  define class_get_instance_method  class_getInstanceMethod
37typedef struct objc_method      *Method_t;
38#endif
39
40#if NeXT_RUNTIME
41#  if !defined(METHOD_NULL)
42#    define METHOD_NULL NULL
43#  endif
44#endif
45
46#if defined (__GNUSTEP_RUNTIME__)
47#  define class_get_instance_method class_getInstanceMethod
48#endif
49
50#if !(__GNU_LIBOBJC__ >= 20100911)
51#  define sel_getTypeEncoding(selector) ((selector)->sel_types)
52#endif
53
54@implementation EOFaultHandler
55
56- (void)setTargetClass:(Class)_class extraData:(void *)_extraData {
57  self->targetClass = _class;
58  self->extraData   = _extraData;
59}
60
61- (Class)targetClass; {
62  return self->targetClass;
63}
64- (void *)extraData {
65  return self->extraData;
66}
67
68/* firing */
69
70- (BOOL)shouldPerformInvocation:(NSInvocation *)_invocation {
71  return YES;
72}
73
74- (void)faultWillFire:(EOFault *)_fault {
75}
76
77- (void)completeInitializationOfObject:(id)_object {
78  [self doesNotRecognizeSelector:_cmd];
79}
80
81/* fault reflection */
82
83- (Class)classForFault:(EOFault *)_fault {
84
85#if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__)
86
87  return (object_is_instance(_fault))
88    ? [self targetClass]
89    : (*(Class *)_fault);
90#else
91#  warning TODO: add complete implementation for Apple/NeXT runtime!
92  return [self targetClass];
93#endif
94}
95
96- (BOOL)respondsToSelector:(SEL)_selector forFault:(EOFault *)_fault {
97  Class class;
98
99  /* first check whether fault itself responds to selector */
100#if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__)
101  if (class_get_instance_method(*(Class *)_fault, _selector) != METHOD_NULL)
102    return YES;
103#else
104#  warning TODO: add implementation for NeXT/Apple runtime!
105#endif
106
107  /* then check whether the target class does */
108  class = [self targetClass];
109#if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__)
110  return (class_get_instance_method(class, _selector) != NULL) ? YES : NO;
111#else
112#  warning TODO: use NeXT/Apple runtime function
113  return [(NSObject *)class methodForSelector:_selector] ? YES : NO;
114#endif
115}
116
117- (BOOL)conformsToProtocol:(Protocol *)_protocol forFault:(EOFault *)_fault {
118  Class class, sClass;
119
120#if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__) && !(__GNU_LIBOBJC__ >= 20100911)
121  struct objc_protocol_list* protos;
122  int i;
123
124  class = object_is_instance(_fault) ? [self targetClass] : (Class)_fault;
125  for (protos = class->protocols; protos; protos = protos->next) {
126    for (i = 0; i < protos->count; i++) {
127      if ([protos->list[i] conformsToProtocol:_protocol])
128        return YES;
129    }
130  }
131#else
132#  warning TODO: implement on NeXT/Apple runtime!
133  class = [self targetClass];
134#endif
135
136  return ((sClass = [class superclass]))
137    ? [sClass conformsToProtocol:_protocol]
138    : NO;
139}
140
141- (BOOL)isKindOfClass:(Class)_class forFault:(EOFault *)_fault {
142  Class class;
143
144#if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__)
145  class = object_is_instance(_fault) ? [self targetClass] : (Class)_fault;
146  for (; class != Nil; class = class_get_super_class(class)) {
147    if (class == _class)
148      return YES;
149  }
150#else
151#  warning TODO: add implementation for NeXT/Apple runtime!
152  class = [self targetClass];
153#endif
154  return NO;
155}
156
157- (BOOL)isMemberOfClass:(Class)_class forFault:(EOFault *)_fault {
158  Class class;
159#if GNU_RUNTIME && !defined(__GNUSTEP_RUNTIME__)
160  class = object_is_instance(_fault) ? [self targetClass] : (Class)_fault;
161#else
162#  warning TODO: add implementation for NeXT/Apple runtime!
163  class = [self targetClass];
164#endif
165  return class == _class ? YES : NO;
166}
167
168- (NSMethodSignature *)methodSignatureForSelector:(SEL)_selector
169  forFault:(EOFault *)_fault
170{
171#if NeXT_Foundation_LIBRARY || defined(__GNUSTEP_RUNTIME__)
172  // probably incorrect
173  return [_fault methodSignatureForSelector:_selector];
174#else
175  register const char *types = NULL;
176
177  if (_selector == NULL) // invalid selector
178    return nil;
179
180#if GNU_RUNTIME && 0
181  // GNU runtime selectors may be typed, a lookup may not be necessary
182  types = aSelector->sel_types;
183#endif
184
185  /* first check for EOFault's own methods */
186
187#if !(__GNU_LIBOBJC__ >= 20100911)
188  if (types == NULL) {
189    // lookup method for selector
190    struct objc_method *mth;
191    mth = class_get_instance_method(*(Class *)_fault, _selector);
192    if (mth) types = mth->method_types;
193  }
194
195  /* then check in target class methods */
196
197  if (types == NULL) {
198    // lookup method for selector
199    struct objc_method *mth;
200    mth = class_get_instance_method([self targetClass], _selector);
201    if (mth) types = mth->method_types;
202  }
203#endif
204
205#if GNU_RUNTIME
206  // GNU runtime selectors may be typed, a lookup may not be necessary
207  if (types == NULL)
208    types = sel_getTypeEncoding(_selector);
209#endif
210  if (types == NULL)
211    return nil;
212
213  return [NSMethodSignature signatureWithObjCTypes:types];
214#endif
215}
216
217/* description */
218
219- (NSString *)descriptionForObject:(id)_fault {
220  return [NSString stringWithFormat:@"<%@[0x%p]: on=%@>",
221                     NSStringFromClass(*(Class *)_fault),
222                     _fault,
223                     NSStringFromClass([self targetClass])];
224}
225
226@end /* EOFaultHandler */
227