1%{
2/*
3 * Macros to find the Java DbEnv object for methods in various classes.
4 * Note that "arg1" is from the code SWIG generates for the "this"/"self".
5 */
6#define	JDBENV (arg1 ? (jobject)DB_ENV_INTERNAL(arg1) : NULL)
7#define	DB2JDBENV ((jobject)DB_ENV_INTERNAL(arg1->dbenv))
8#define	DBC2JDBENV ((jobject)DB_ENV_INTERNAL(arg1->dbp->dbenv))
9#define	TXN2JDBENV ((jobject)DB_ENV_INTERNAL(arg1->mgrp->env->dbenv))
10%}
11
12/* Common case exception handling */
13%typemap(check) SWIGTYPE *self %{
14	if ($input == 0) {
15		__dbj_throw(jenv, EINVAL, "call on closed handle", NULL, NULL);
16		return $null;
17	}%}
18
19%define JAVA_EXCEPT_NONE
20%exception %{ $action %}
21%enddef
22
23/* Most methods return an error code. */
24%define JAVA_EXCEPT(_retcheck, _jdbenv)
25%exception %{
26	$action
27	if (!_retcheck(result)) {
28		__dbj_throw(jenv, result, NULL, NULL, _jdbenv);
29	}
30%}
31%enddef
32
33/* For everything else, errno is set in db.i. */
34%define JAVA_EXCEPT_ERRNO(_retcheck, _jdbenv)
35%exception %{
36	errno = 0;
37	$action
38	if (!_retcheck(errno)) {
39		__dbj_throw(jenv, errno, NULL, NULL, _jdbenv);
40	}
41%}
42%enddef
43
44/* And then there are these (extra) special cases. */
45%exception __db_env::lock_get %{
46	errno = 0;
47	$action
48	if (errno == DB_LOCK_NOTGRANTED) {
49                (*jenv)->Throw(jenv,
50                    (*jenv)->NewObject(jenv, lockex_class, lockex_construct,
51                    (*jenv)->NewStringUTF(jenv, "DbEnv.lock_get not granted"),
52                        DB_LOCK_GET, arg5, jarg4, NULL, -1, JDBENV));
53	} else if (!DB_RETOK_STD(errno)) {
54		__dbj_throw(jenv, errno, NULL, NULL, JDBENV);
55	}
56%}
57
58%{
59static jthrowable __dbj_get_except(JNIEnv *jenv,
60    int err, const char *msg, jobject obj, jobject jdbenv) {
61	jobject jmsg;
62
63	if (msg == NULL)
64		msg = db_strerror(err);
65
66	jmsg = (*jenv)->NewStringUTF(jenv, msg);
67
68	/* Retrieve error message logged by DB */
69	if (jdbenv != NULL) {
70		jmsg = (jstring) (*jenv)->CallNonvirtualObjectMethod(jenv,
71		    jdbenv, dbenv_class, get_err_msg_method, jmsg);
72	}
73
74	switch (err) {
75	case EINVAL:
76		return (jthrowable)(*jenv)->NewObject(jenv,
77		    illegalargex_class, illegalargex_construct, jmsg);
78
79	case ENOENT:
80		return (jthrowable)(*jenv)->NewObject(jenv,
81		    filenotfoundex_class, filenotfoundex_construct, jmsg);
82
83	case ENOMEM:
84		return (jthrowable)(*jenv)->NewObject(jenv,
85		    outofmemerr_class, outofmemerr_construct, jmsg);
86
87	case DB_BUFFER_SMALL:
88		return (jthrowable)(*jenv)->NewObject(jenv, memex_class,
89		    memex_construct, jmsg, obj, err, jdbenv);
90
91	case DB_REP_DUPMASTER:
92		return (jthrowable)(*jenv)->NewObject(jenv,
93		    repdupmasterex_class, repdupmasterex_construct,
94		    jmsg, err, jdbenv);
95
96	case DB_REP_HANDLE_DEAD:
97		return (jthrowable)(*jenv)->NewObject(jenv,
98		    rephandledeadex_class, rephandledeadex_construct,
99		    jmsg, err, jdbenv);
100
101	case DB_REP_HOLDELECTION:
102		return (jthrowable)(*jenv)->NewObject(jenv,
103		    repholdelectionex_class, repholdelectionex_construct,
104		    jmsg, err, jdbenv);
105
106	case DB_REP_JOIN_FAILURE:
107		return (jthrowable)(*jenv)->NewObject(jenv,
108		    repjoinfailex_class, repjoinfailex_construct,
109		    jmsg, err, jdbenv);
110
111	case DB_REP_LEASE_EXPIRED:
112		return (jthrowable)(*jenv)->NewObject(jenv,
113		    repleaseexpiredex_class, repleaseexpiredex_construct,
114		    jmsg, err, jdbenv);
115
116	case DB_REP_LEASE_TIMEOUT:
117		return (jthrowable)(*jenv)->NewObject(jenv,
118		    repleasetimeoutex_class, repleasetimeoutex_construct,
119		    jmsg, err, jdbenv);
120
121	case DB_REP_LOCKOUT:
122		return (jthrowable)(*jenv)->NewObject(jenv,
123		    replockoutex_class, replockoutex_construct,
124		    jmsg, err, jdbenv);
125
126	case DB_REP_UNAVAIL:
127		return (jthrowable)(*jenv)->NewObject(jenv,
128		    repunavailex_class, repunavailex_construct,
129		    jmsg, err, jdbenv);
130
131	case DB_RUNRECOVERY:
132		return (jthrowable)(*jenv)->NewObject(jenv, runrecex_class,
133		    runrecex_construct, jmsg, err, jdbenv);
134
135	case DB_LOCK_DEADLOCK:
136		return (jthrowable)(*jenv)->NewObject(jenv, deadex_class,
137		    deadex_construct, jmsg, err, jdbenv);
138
139	case DB_LOCK_NOTGRANTED:
140		return (jthrowable)(*jenv)->NewObject(jenv, lockex_class,
141		    lockex_construct, jmsg, err, 0, NULL, NULL, 0, jdbenv);
142
143	case DB_VERSION_MISMATCH:
144		return (jthrowable)(*jenv)->NewObject(jenv, versionex_class,
145		    versionex_construct, jmsg, err, jdbenv);
146
147	default:
148		return (jthrowable)(*jenv)->NewObject(jenv, dbex_class,
149		    dbex_construct, jmsg, err, jdbenv);
150	}
151}
152
153static int __dbj_throw(JNIEnv *jenv,
154    int err, const char *msg, jobject obj, jobject jdbenv)
155{
156	jthrowable t;
157
158	/* If an exception is pending, ignore requests to throw a new one. */
159	if ((*jenv)->ExceptionOccurred(jenv) == NULL) {
160		t = __dbj_get_except(jenv, err, msg, obj, jdbenv);
161		if (t == NULL) {
162			/*
163			 * This is a problem - something went wrong creating an
164			 * exception.  We have to assume there is an exception
165			 * created by the JVM that is pending as a result
166			 * (e.g., OutOfMemoryError), but we don't want to lose
167			 * this error, so we just call __db_errx here.
168			 */
169			if (msg == NULL)
170				msg = db_strerror(err);
171
172			 __db_errx(NULL, "Couldn't create exception for: '%s'",
173			     msg);
174		} else
175			(*jenv)->Throw(jenv, t);
176	}
177
178	return (err);
179}
180%}
181