diff options
author | Frederic Peters <fpeters@entrouvert.com> | 2008-04-29 12:07:06 +0000 |
---|---|---|
committer | Frederic Peters <fpeters@entrouvert.com> | 2008-04-29 12:07:06 +0000 |
commit | b2c6027ad1a0e13257906fc5efbf4c5386d3f1cb (patch) | |
tree | e3565e6ba4736e17ed6a3e02f3a8151aed72572e | |
parent | 3d7c20873cfd488c67645457594a27f8026f9d54 (diff) | |
download | lasso-b2c6027ad1a0e13257906fc5efbf4c5386d3f1cb.tar.gz lasso-b2c6027ad1a0e13257906fc5efbf4c5386d3f1cb.tar.xz lasso-b2c6027ad1a0e13257906fc5efbf4c5386d3f1cb.zip |
[project @ fpeters@0d.be-20080222093656-l6a09ccadxdz9qrs]
merging benjamin branch
Original author: Frederic Peters <fpeters@0d.be>
Date: 2008-02-22 10:36:56.421000+01:00
-rw-r--r-- | bindings/bindings.py | 6 | ||||
-rw-r--r-- | bindings/java/GObject.java | 37 | ||||
-rw-r--r-- | bindings/java/Makefile.am | 55 | ||||
-rw-r--r-- | bindings/java/TODO | 3 | ||||
-rw-r--r-- | bindings/java/tests/BindingTests.java | 113 | ||||
-rw-r--r-- | bindings/java/tests/LoginTest.java | 61 | ||||
-rw-r--r-- | bindings/lang_java.py | 366 | ||||
-rw-r--r-- | bindings/lang_java_wrapper_top.c | 998 | ||||
-rw-r--r-- | bindings/overrides.xml | 4 |
9 files changed, 1027 insertions, 616 deletions
diff --git a/bindings/bindings.py b/bindings/bindings.py index 971deafd..e274b7f7 100644 --- a/bindings/bindings.py +++ b/bindings/bindings.py @@ -430,6 +430,12 @@ def main(): java_binding = lang_java.JavaBinding(binding) java_binding.generate(); + elif options.language == 'java-list': + import lang_java + + java_binding = lang_java.JavaBinding(binding) + java_binding.print_list_of_files(); + if __name__ == '__main__': main() diff --git a/bindings/java/GObject.java b/bindings/java/GObject.java index ccb59c22..a7815a72 100644 --- a/bindings/java/GObject.java +++ b/bindings/java/GObject.java @@ -1,4 +1,5 @@ package com.entrouvert.lasso; +import java.util.*; class GObject { private long cptr; @@ -6,4 +7,40 @@ class GObject { protected GObject(long ptr) { cptr = ptr; } + protected Map arrayToMap(Object[] arr) { + Map map = new HashMap(); + if (arr == null) + return map; + if (arr.length % 2 != 0) + throw new IllegalArgumentException("arr must of an even size"); + int i; + for (i=0;i<arr.length;i+=2) { + map.put(arr[i],arr[i+1]); + } + return map; + } + protected void mapToArray(Map map, Object[] arr) { + int s = map.size(); + if (map == null) + return; + Iterator it; + it = map.entrySet().iterator(); + int i = 0; + while (it.hasNext() && i < 2*s) { + Map.Entry e = (Map.Entry)it.next(); + arr[i++] = (Object)e.getKey(); + arr[i++] = (Object)e.getValue(); + } + } + protected void listToArray(List list, Object[] arr) { + Iterator it = list.iterator(); + int s = arr.length; + int i = 0; + while (it.hasNext() && i < s) { + arr[i++] = (Object)it.next(); + } + } + protected void finalize() throws Throwable { + LassoJNI.destroy(cptr); + } } diff --git a/bindings/java/Makefile.am b/bindings/java/Makefile.am index ace56f6e..e045c6b9 100644 --- a/bindings/java/Makefile.am +++ b/bindings/java/Makefile.am @@ -3,39 +3,66 @@ INCLUDES = -I$(top_srcdir) \ -I$(top_builddir) \ $(SASL_CFLAGS) +AM_JAVACFLAGS=-C +CLASSPATH_ENV= CLASSPATH=.:lasso.jar:/usr/share/java/junit.jar + java_extension_LTLIBRARIES = libjnilasso.la -java_extensiondir = ${libdir} +java_extensiondir = ${libdir}/java + +java_lasso_source_files = $(shell python $(top_srcdir)/bindings/bindings.py -l java-list --src-dir=$(top_srcdir)/lasso/) + +lasso_jardir=$(prefix)/share/java +lasso_jar_DATA=lasso.jar +lasso_jar_class_files = $(java_lasso_source_files:.java=.class) + +JAVAH=gcjh + +$(lasso_jar_class_files): %.class: %.java + $(JAVAC) -C -classpath . -d . $< + +all_jar_class_files = $(shell find com/entrouvert/lasso -name '*.class' | sed 's%\$$%\\$$%g') + +lasso.jar: $(all_jar_class_files) + $(JAR) -cf $@ $(all_jar_class_files) -nodist_java_extension_DATA = +# Doc +apidir = $(docbasedir)/lasso/java-api + +doc: + -mkdir .doc + -javadoc -link http://java.sun.com/j2se/1.4.2/docs/api -public -d .doc -sourcepath . -subpackages com.entrouvert.lasso + mv .doc doc + + +com_entrouvert_lasso_LassoJNI.h: $(lasso_jar_class_files) + $(JAVAH) -jni -d . --classpath=. com.entrouvert.lasso.LassoJNI libjnilasso_la_CFLAGS = $(LASSO_CORE_CFLAGS) -I$(top_srcdir) -I$(top_builddir) libjnilasso_la_LDFLAGS = -export-dynamic -prefer-pic -module -avoid-version libjnilasso_la_LIBADD = $(top_builddir)/lasso/liblasso.la $(LASSO_LIBS) -nodist_libjnilasso_la_SOURCES = com_entrouvert_lasso_LassoJNI.c +nodist_libjnilasso_la_SOURCES = com_entrouvert_lasso_LassoJNI.c BUILT_SOURCES = com_entrouvert_lasso_LassoJNI.c com_entrouvert_lasso_LassoJNI.h -%.class: %.java - javac -d . -cp . $< - -com_entrouvert_lasso_LassoJNI.h: com/entrouvert/lasso/LassoJNI.class - javah -d . -jni --classpath=. com.entrouvert.lasso.LassoJNI - -com/entrouvert/lasso/LassoJNI.java com/entrouvert/lasso/LassoConstants.java com_entrouvert_lasso_LassoJNI.c: $(srcdir)/../lang_java_wrapper_top.c $(srcdir)/../lang_java.py +$(java_lasso_source_files) com_entrouvert_lasso_LassoJNI.c: ../lang_java_wrapper_top.c ../lang_java.py $(PYTHON) $(top_srcdir)/bindings/bindings.py -l java --src-dir=$(top_srcdir)/lasso/ cp $(srcdir)/GObject.java com/entrouvert/lasso -doc/index.html: - javadoc -link http://java.sun.com/j2se/1.4.2/docs/api -public -d doc -sourcepath . -subpackages com.entrouvert.lasso +check: JAVAROOT=. -publish: doc/index.html +doc-publish: doc tar czf doc.tgz -C doc . scp doc.tgz bdauvergne@perso.entrouvert.org: ssh bdauvergne@perso.entrouvert.org tar czf -C public_html/java-binding-doc doc.tgz rm doc.tgz clean-local: - -rm -f doc/* com_entrouvert_lasso_LassoJNI.c com/entrouvert/lasso/*.java com/entrouvert/lasso/*.class com_entrouvert_lasso_LassoJNI.h + -rm -f com_entrouvert_lasso_LassoJNI.c com/entrouvert/lasso/*.java com/entrouvert/lasso/*.class com_entrouvert_lasso_LassoJNI.h lasso.jar + -rm -rf doc + -rm tests/*.class + + +check_JAVA = tests/BindingTests.java tests/LoginTest.java endif diff --git a/bindings/java/TODO b/bindings/java/TODO index 9e0c346f..09b4a5c6 100644 --- a/bindings/java/TODO +++ b/bindings/java/TODO @@ -11,4 +11,5 @@ -> recencer par fonction les erreurs émises DONE -> remonter les infos dans le graphe DONE * doc DONE -* renvoyer des listes et des hashmap au lieu de tableaux +* renvoyer des listes et des hashmap au lieu de tableaux DONE +* utiliser les numéros de version de lasso dans la doc/noms de fichiers diff --git a/bindings/java/tests/BindingTests.java b/bindings/java/tests/BindingTests.java index 53a508df..10b08f2b 100644 --- a/bindings/java/tests/BindingTests.java +++ b/bindings/java/tests/BindingTests.java @@ -42,22 +42,9 @@ import java.util.*; public class BindingTests extends TestCase { - String[] toStringArray(Object[] array) { - String[] str = new String[array.length]; - int i; - for (i=0;i<array.length;i++) - str[i] = (String)array[i]; - return str; - } - SamlAssertion[] toSamlAssertionArray(Object[] array) { - SamlAssertion[] str = new SamlAssertion[array.length]; - int i; - for (i=0;i<array.length;i++) - str[i] = (SamlAssertion)array[i]; - return str; - } public static void main(String args[]) { junit.textui.TestRunner.run(suite()); + System.gc(); } public static Test suite() { @@ -120,27 +107,33 @@ public class BindingTests extends TestCase { assertEquals(respondWith.get(0), "first string"); assertEquals(respondWith.get(1), "second string"); assertEquals(respondWith.get(2), "third string"); - authnRequest.setRespondWith(toStringArray(respondWith.toArray())); - assertEquals(authnRequest.getRespondWith()[0], "first string"); - assertEquals(authnRequest.getRespondWith()[1], "second string"); - assertEquals(authnRequest.getRespondWith()[2], "third string"); + authnRequest.setRespondWith(respondWith); + assertEquals(authnRequest.getRespondWith().get(0), "first string"); + assertEquals(authnRequest.getRespondWith().get(1), "second string"); + assertEquals(authnRequest.getRespondWith().get(2), "third string"); assertEquals(respondWith.get(0), "first string"); assertEquals(respondWith.get(1), "second string"); assertEquals(respondWith.get(2), "third string"); respondWith = null; - assertEquals(authnRequest.getRespondWith()[0], "first string"); - assertEquals(authnRequest.getRespondWith()[1], "second string"); - assertEquals(authnRequest.getRespondWith()[2], "third string"); - respondWith = Arrays.asList(authnRequest.getRespondWith()); + assertEquals(authnRequest.getRespondWith().get(0), "first string"); + assertEquals(authnRequest.getRespondWith().get(1), "second string"); + assertEquals(authnRequest.getRespondWith().get(2), "third string"); + respondWith = authnRequest.getRespondWith(); assertEquals(respondWith.get(0), "first string"); assertEquals(respondWith.get(1), "second string"); assertEquals(respondWith.get(2), "third string"); respondWith = null; - assertEquals(authnRequest.getRespondWith()[0], "first string"); - assertEquals(authnRequest.getRespondWith()[1], "second string"); - assertEquals(authnRequest.getRespondWith()[2], "third string"); + assertEquals(authnRequest.getRespondWith().get(0), "first string"); + assertEquals(authnRequest.getRespondWith().get(1), "second string"); + assertEquals(authnRequest.getRespondWith().get(2), "third string"); + authnRequest.removeFromRespondWith("second string"); + assertEquals(authnRequest.getRespondWith().get(0), "first string"); + assertEquals(authnRequest.getRespondWith().get(1), "third string"); + authnRequest.addToRespondWith("second string"); + assertEquals(authnRequest.getRespondWith().get(0), "first string"); + assertEquals(authnRequest.getRespondWith().get(1), "third string"); + assertEquals(authnRequest.getRespondWith().get(2), "second string"); authnRequest.setRespondWith(null); - System.out.println("coin"+authnRequest.getRespondWith()); assertNull(authnRequest.getRespondWith()); authnRequest = null; @@ -174,34 +167,25 @@ public class BindingTests extends TestCase { assertEquals(((SamlAssertion) assertions.get(0)).getAssertionId(), "assertion 1"); assertEquals(((SamlAssertion) assertions.get(1)).getAssertionId(), "assertion 2"); assertEquals(((SamlAssertion) assertions.get(2)).getAssertionId(), "assertion 3"); - response.setAssertion(toSamlAssertionArray(assertions.toArray())); - assertEquals(((SamlAssertion) response.getAssertion()[0]).getAssertionId(), - "assertion 1"); - assertEquals(((SamlAssertion) response.getAssertion()[1]).getAssertionId(), - "assertion 2"); - assertEquals(((SamlAssertion) response.getAssertion()[2]).getAssertionId(), - "assertion 3"); + response.setAssertion(assertions); + assertEquals(((SamlAssertion) response.getAssertion().get(0)).getAssertionId(), "assertion 1"); + assertEquals(((SamlAssertion) response.getAssertion().get(1)).getAssertionId(), "assertion 2"); + assertEquals(((SamlAssertion) response.getAssertion().get(2)).getAssertionId(), "assertion 3"); assertEquals(((SamlAssertion) assertions.get(0)).getAssertionId(), "assertion 1"); assertEquals(((SamlAssertion) assertions.get(1)).getAssertionId(), "assertion 2"); assertEquals(((SamlAssertion) assertions.get(2)).getAssertionId(), "assertion 3"); assertions = null;; - assertEquals(((SamlAssertion) response.getAssertion()[0]).getAssertionId(), - "assertion 1"); - assertEquals(((SamlAssertion) response.getAssertion()[1]).getAssertionId(), - "assertion 2"); - assertEquals(((SamlAssertion) response.getAssertion()[2]).getAssertionId(), - "assertion 3"); - assertions = Arrays.asList(response.getAssertion()); + assertEquals(((SamlAssertion) response.getAssertion().get(0)).getAssertionId(), "assertion 1"); + assertEquals(((SamlAssertion) response.getAssertion().get(1)).getAssertionId(), "assertion 2"); + assertEquals(((SamlAssertion) response.getAssertion().get(2)).getAssertionId(), "assertion 3"); + assertions = response.getAssertion(); assertEquals(((SamlAssertion) assertions.get(0)).getAssertionId(), "assertion 1"); assertEquals(((SamlAssertion) assertions.get(1)).getAssertionId(), "assertion 2"); assertEquals(((SamlAssertion) assertions.get(2)).getAssertionId(), "assertion 3"); assertions = null; - assertEquals(((SamlAssertion) response.getAssertion()[0]).getAssertionId(), - "assertion 1"); - assertEquals(((SamlAssertion) response.getAssertion()[1]).getAssertionId(), - "assertion 2"); - assertEquals(((SamlAssertion) response.getAssertion()[2]).getAssertionId(), - "assertion 3"); + assertEquals(((SamlAssertion) response.getAssertion().get(0)).getAssertionId(), "assertion 1"); + assertEquals(((SamlAssertion) response.getAssertion().get(1)).getAssertionId(), "assertion 2"); + assertEquals(((SamlAssertion) response.getAssertion().get(2)).getAssertionId(), "assertion 3"); response.setAssertion(null); assertNull(response.getAssertion()); @@ -215,15 +199,9 @@ public class BindingTests extends TestCase { assertNull(authnRequest.getExtension()); - String actionString1 = "<lib:Extension xmlns:lib=\"urn:liberty:iff:2003-08\">\n" - + " <action>do 1</action>\n" - + "</lib:Extension>"; - String actionString2 = "<lib:Extension xmlns:lib=\"urn:liberty:iff:2003-08\">\n" - + " <action>do 2</action>\n" - + "</lib:Extension>"; - String actionString3 = "<lib:Extension xmlns:lib=\"urn:liberty:iff:2003-08\">\n" - + " <action>do 3</action>\n" - + "</lib:Extension>"; + String actionString1 = "<lib:Extension xmlns:lib=\"urn:liberty:iff:2003-08\">\n" + " <action>do 1</action>\n" + "</lib:Extension>"; + String actionString2 = "<lib:Extension xmlns:lib=\"urn:liberty:iff:2003-08\">\n" + " <action>do 2</action>\n" + "</lib:Extension>"; + String actionString3 = "<lib:Extension xmlns:lib=\"urn:liberty:iff:2003-08\">\n" + " <action>do 3</action>\n" + "</lib:Extension>"; List extension = new ArrayList(); assertEquals(extension.size(), 0); extension.add(actionString1); @@ -239,25 +217,25 @@ public class BindingTests extends TestCase { assertEquals(extension.get(0), actionString1); assertEquals(extension.get(1), actionString2); assertEquals(extension.get(2), actionString3); - authnRequest.setExtension(toStringArray(extension.toArray())); - assertEquals(authnRequest.getExtension()[0], actionString1); - assertEquals(authnRequest.getExtension()[1], actionString2); - assertEquals(authnRequest.getExtension()[2], actionString3); + authnRequest.setExtension(extension); + assertEquals(authnRequest.getExtension().get(0), actionString1); + assertEquals(authnRequest.getExtension().get(1), actionString2); + assertEquals(authnRequest.getExtension().get(2), actionString3); assertEquals(extension.get(0), actionString1); assertEquals(extension.get(1), actionString2); assertEquals(extension.get(2), actionString3); extension = null; - assertEquals(authnRequest.getExtension()[0], actionString1); - assertEquals(authnRequest.getExtension()[1], actionString2); - assertEquals(authnRequest.getExtension()[2], actionString3); - extension = Arrays.asList(authnRequest.getExtension()); + assertEquals(authnRequest.getExtension().get(0), actionString1); + assertEquals(authnRequest.getExtension().get(1), actionString2); + assertEquals(authnRequest.getExtension().get(2), actionString3); + extension = authnRequest.getExtension(); assertEquals(extension.get(0), actionString1); assertEquals(extension.get(1), actionString2); assertEquals(extension.get(2), actionString3); extension = null; - assertEquals(authnRequest.getExtension()[0], actionString1); - assertEquals(authnRequest.getExtension()[1], actionString2); - assertEquals(authnRequest.getExtension()[2], actionString3); + assertEquals(authnRequest.getExtension().get(0), actionString1); + assertEquals(authnRequest.getExtension().get(1), actionString2); + assertEquals(authnRequest.getExtension().get(2), actionString3); authnRequest.setExtension(null); assertNull(authnRequest.getExtension()); @@ -272,8 +250,7 @@ public class BindingTests extends TestCase { assertNull(login.getRequest()); login.setRequest((SamlpRequestAbstract) new LibAuthnRequest()); ((LibAuthnRequest) login.getRequest()).setConsent(LassoConstants.LASSO_LIB_CONSENT_OBTAINED); - assertEquals(((LibAuthnRequest) login.getRequest()).getConsent(), - LassoConstants.LASSO_LIB_CONSENT_OBTAINED); + assertEquals(((LibAuthnRequest) login.getRequest()).getConsent(), LassoConstants.LASSO_LIB_CONSENT_OBTAINED); login.setRequest(null); assertNull(login.getRequest()); diff --git a/bindings/java/tests/LoginTest.java b/bindings/java/tests/LoginTest.java index 755ffd7b..d3d29d49 100644 --- a/bindings/java/tests/LoginTest.java +++ b/bindings/java/tests/LoginTest.java @@ -42,30 +42,30 @@ import com.entrouvert.lasso.*; public class LoginTest extends TestCase { public String generateIdentityProviderDump() { Server server = new Server( - "../../tests/data/idp1-la/metadata.xml", - "../../tests/data/idp1-la/private-key-raw.pem", + "../../../tests/data/idp1-la/metadata.xml", + "../../../tests/data/idp1-la/private-key-raw.pem", null, - "../../tests/data/idp1-la/certificate.pem"); + "../../../tests/data/idp1-la/certificate.pem"); server.addProvider( - lasso.PROVIDER_ROLE_SP, - "../../tests/data/sp1-la/metadata.xml", - "../../tests/data/sp1-la/public-key.pem", - "../../tests/data/ca1-la/certificate.pem"); + LassoConstants.LASSO_PROVIDER_ROLE_SP, + "../../../tests/data/sp1-la/metadata.xml", + "../../../tests/data/sp1-la/public-key.pem", + "../../../tests/data/ca1-la/certificate.pem"); String serverDump = server.dump(); return serverDump; } public String generateServiceProviderDump() { Server server = new Server( - "../../tests/data/sp1-la/metadata.xml", - "../../tests/data/sp1-la/private-key-raw.pem", + "../../../tests/data/sp1-la/metadata.xml", + "../../../tests/data/sp1-la/private-key-raw.pem", null, - "../../tests/data/sp1-la/certificate.pem"); + "../../../tests/data/sp1-la/certificate.pem"); server.addProvider( - lasso.PROVIDER_ROLE_IDP, - "../../tests/data/idp1-la/metadata.xml", - "../../tests/data/idp1-la/public-key.pem", - "../../tests/data/ca1-la/certificate.pem"); + LassoConstants.LASSO_PROVIDER_ROLE_IDP, + "../../../tests/data/idp1-la/metadata.xml", + "../../../tests/data/idp1-la/public-key.pem", + "../../../tests/data/ca1-la/certificate.pem"); String serverDump = server.dump(); return serverDump; } @@ -97,11 +97,11 @@ public class LoginTest extends TestCase { assertNotNull(spDump); sp = Server.newFromDump(spDump); spLogin = new Login(sp); - spLogin.initAuthnRequest("https://idp1/metadata", lasso.HTTP_METHOD_REDIRECT); + spLogin.initAuthnRequest("https://idp1/metadata", LassoConstants.LASSO_HTTP_METHOD_REDIRECT); authnRequest = (LibAuthnRequest) spLogin.getRequest(); authnRequest.setIsPassive(false); - authnRequest.setNameIdPolicy(lasso.LIB_NAMEID_POLICY_TYPE_FEDERATED); - authnRequest.setConsent(lasso.LIB_CONSENT_OBTAINED); + authnRequest.setNameIdPolicy(LassoConstants.LASSO_LIB_NAMEID_POLICY_TYPE_FEDERATED); + authnRequest.setConsent(LassoConstants.LASSO_LIB_CONSENT_OBTAINED); relayState = "fake"; authnRequest.setRelayState(relayState); spLogin.buildAuthnRequestMsg(); @@ -120,15 +120,15 @@ public class LoginTest extends TestCase { userAuthenticated = true; userConsentObtained = false; idpLogin.validateRequestMsg(userAuthenticated, userConsentObtained); - authenticationMethod = lasso.SAML_AUTHENTICATION_METHOD_PASSWORD; + authenticationMethod = LassoConstants.LASSO_SAML_AUTHENTICATION_METHOD_PASSWORD; idpLogin.buildAssertion( authenticationMethod, null, // authenticationInstant null, // reauthenticateOnOrAfter null, // notBefore null);// notOnOrAfter - assertEquals(lasso.LOGIN_PROTOCOL_PROFILE_BRWS_ART, idpLogin.getProtocolProfile()); - idpLogin.buildArtifactMsg(lasso.HTTP_METHOD_REDIRECT); + assertEquals(LassoConstants.LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_ART, idpLogin.getProtocolProfile()); + idpLogin.buildArtifactMsg(LassoConstants.LASSO_HTTP_METHOD_REDIRECT); idpIdentityDump = idpLogin.getIdentity().dump(); assertNotNull(idpIdentityDump); idpSessionDump = idpLogin.getSession().dump(); @@ -139,12 +139,13 @@ public class LoginTest extends TestCase { nameIdentifier = ((SamlNameIdentifier)idpLogin.getNameIdentifier()).getContent(); artifact = idpLogin.getAssertionArtifact(); assertNotNull(artifact); - method = lasso.HTTP_METHOD_REDIRECT; + method = LassoConstants.LASSO_HTTP_METHOD_REDIRECT; // Service provider assertion consumer. spDump = generateServiceProviderDump(); assertNotNull(spDump); sp = Server.newFromDump(spDump); + soapEndpoint = spLogin.getMsgUrl(); spLogin = new Login(sp); spLogin.initRequest(responseQuery, method); spLogin.buildRequestMsg(); @@ -154,8 +155,8 @@ public class LoginTest extends TestCase { assertNotNull(soapRequestMsg); // Identity provider SOAP endpoint. - requestType = lasso.getRequestTypeFromSoapMsg(soapRequestMsg); - assertEquals(lasso.REQUEST_TYPE_LOGIN, requestType); + requestType = LassoJNI.getRequestTypeFromSoapMsg(soapRequestMsg); + assertEquals(LassoConstants.LASSO_REQUEST_TYPE_LOGIN, requestType); idpDump = generateIdentityProviderDump(); assertNotNull(idpDump); idp = Server.newFromDump(idpDump); @@ -181,9 +182,9 @@ public class LoginTest extends TestCase { assertNotNull(spSession); spSessionDump = spSession.dump(); assertNotNull(spSessionDump); - assertion = (SamlAssertion) spSession.getAssertions("https://idp1/metadata").getItem(0); + assertion = (SamlAssertion) spSession.getAssertions("https://idp1/metadata").get(0); authenticationMethod = assertion.getAuthenticationStatement().getAuthenticationMethod(); - assertEquals(lasso.SAML_AUTHENTICATION_METHOD_PASSWORD, authenticationMethod); + assertEquals(LassoConstants.LASSO_SAML_AUTHENTICATION_METHOD_PASSWORD, authenticationMethod); // Service provider logout. spDump = generateServiceProviderDump(); @@ -195,14 +196,14 @@ public class LoginTest extends TestCase { spLogout.setIdentityFromDump(spIdentityDump); assertNotNull(spSessionDump); spLogout.setSessionFromDump(spSessionDump); - spLogout.initRequest(null, lasso.HTTP_METHOD_ANY); + spLogout.initRequest(null, LassoConstants.LASSO_HTTP_METHOD_ANY); spLogout.buildRequestMsg(); soapEndpoint = spLogout.getMsgUrl(); soapRequestMsg = spLogout.getMsgBody(); // Identity provider SOAP endpoint. - requestType = lasso.getRequestTypeFromSoapMsg(soapRequestMsg); - assertEquals(lasso.REQUEST_TYPE_LOGOUT, requestType); + requestType = LassoJNI.getRequestTypeFromSoapMsg(soapRequestMsg); + assertEquals(LassoConstants.LASSO_REQUEST_TYPE_LOGOUT, requestType); idpDump = generateIdentityProviderDump(); assertNotNull(idpDump); idp = Server.newFromDump(idpDump); @@ -235,10 +236,8 @@ public class LoginTest extends TestCase { } public static void main(String args[]) { - System.out.println(System.mapLibraryName("jlasso")); - lasso.init(); junit.textui.TestRunner.run(suite()); - lasso.shutdown(); + System.gc(); } } diff --git a/bindings/lang_java.py b/bindings/lang_java.py index 21e6f955..026a9e43 100644 --- a/bindings/lang_java.py +++ b/bindings/lang_java.py @@ -29,6 +29,12 @@ import utils lasso_package_name = 'com.entrouvert.lasso' lasso_java_path = 'com/entrouvert/lasso/' +debug = 0 + +def with_return_owner(d): + c = d.copy() + c['return_owner'] = 1 + return c def generate_arg_list(self,args): def arg_to_decl(arg): @@ -88,11 +94,40 @@ def wrapper_decl(name, jnitype, fd): print >> fd, 'JNIEXPORT %s JNICALL %s(JNIEnv *env, jclass clss' % \ (jnitype,jniname), +def is_collection(type): + return type in ('GList*','GHashTable*') + +def is_string_type(type): + return type in ['char*', 'const char*', 'gchar*', 'const gchar*'] + class JavaBinding: def __init__(self, binding_data): self.binding_data = binding_data - def is_pygobject(self, t): + def print_list_of_files(self): + l = ['GObject.java','LassoConstants.java','LassoJNI.java','LassoException.java', 'LassoUndefinedException.java', 'LassoUnimplementedException.java'] + for c in self.binding_data.structs: + class_name = convert_class_name(c.name) + l.append(class_name + '.java') + for c in self.binding_data.constants: + type, orig = c + if 'LASSO_ERROR_' in orig or '_ERROR_' not in orig: + continue + name, super = error_to_exception(orig) + l.append(name + '.java') + if not super + '.java' in l: + l.append(super + '.java') + l = [ lasso_java_path + p for p in l] + for p in l: + print p, + print + print + + def is_int_type(self, type): + return type in ['gboolean','int','gint'] + self.binding_data.enums + + + def is_gobject_type(self, t): return t not in ['char*', 'const char*', 'gchar*', 'const gchar*', 'GList*', 'GHashTable*', 'int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums @@ -162,7 +197,8 @@ public abstract interface LassoConstants { package %s; public final class LassoJNI { -public static native void init2(); +protected static native void init2(); +protected static native void destroy(long cptr); ''' % lasso_package_name def generate_JNI_constants(self, fd): print >>fd, '/* Constants getters */' @@ -252,8 +288,9 @@ public static native void init2(); print >> fd, ' public static native void %s(GObject obj, %s[] value);' % (name,jtype) name = '%s_add' % prefix print >> fd, ' public static native void %s(GObject obj, %s value);' % (name,jtype) - name = '%s_remove' % prefix - print >> fd, ' public static native void %s(GObject obj, %s value);' % (name,jtype) + if not m[2].get('elem_type') in ('xmlNode*',): + name = '%s_remove' % prefix + print >> fd, ' public static native void %s(GObject obj, %s value);' % (name,jtype) elif mtype == 'GHashTable*': name = '%s_get' % prefix print >> fd, ' public static native %s[] %s(GObject obj);' % (jtype,name) @@ -261,10 +298,10 @@ public static native void init2(); print >> fd, ' public static native void %s(GObject obj, %s[] value);' % (name,jtype) name = '%s_add' % prefix print >> fd, ' public static native void %s(GObject obj, String key, %s value);' % (name,jtype) - name = '%s_remove' % prefix - print >> fd, ' public static native void %s(GObject obj, String key);' % (name) - name = '%s_get_by_name' % prefix - print >> fd, ' public static native %s[] %s(GObject obj, String key);' % (jtype,name) +# name = '%s_remove' % prefix +# print >> fd, ' public static native void %s(GObject obj, String key);' % (name) +# name = '%s_get_by_name' % prefix +# print >> fd, ' public static native %s[] %s(GObject obj, String key);' % (jtype,name) else: name = '%s_get' % prefix print >> fd, ' public static native %s %s(GObject obj);' % (jtype,name) @@ -336,61 +373,57 @@ public static native void init2(); print >>fd, '}' print >> fd, '/* End of declaration of constants */' - def jni_return_type(self, vtype): - if vtype == 'gboolean': + def jni_return_type(self, type): + if type == 'gboolean': return 'jboolean' - elif vtype in ['int','gint'] + self.binding_data.enums: + elif type in ['int','gint'] + self.binding_data.enums: return 'jint' - elif vtype in ('char*', 'gchar*', 'const char*', 'const gchar*'): + elif type in ('char*', 'gchar*', 'const char*', 'const gchar*'): return 'jstring' - elif vtype in ('GList*','GHashTable*'): + elif type in ('GList*','GHashTable*'): return 'jobjectArray' - elif vtype == 'xmlNode*': + elif type == 'xmlNode*': return 'jstring' - elif not vtype: + elif not type: return 'void' else: return 'jobject' - def c_to_java_value(self, name, vtype, options): - if vtype == 'gboolean': - return '(jboolean)%s' % name - elif vtype in ['int', 'gint'] + self.binding_data.enums: - return '(jint)%s' % name - elif vtype in ('char*', 'gchar*'): - return 'string_to_jstring(env, %s)' % name - elif vtype in ('const char*', 'const gchar*'): - return 'string_to_jstring(env, %s)' % name - elif vtype in ('GList*',): + def c_to_java_value(self, left, right, type, options): + if type == 'gboolean': + return '%s = (jboolean)%s' % (left,right) + elif type in ['int', 'gint'] + self.binding_data.enums: + return '%s = (jint)%s' % (left, right) + elif is_string_type(type): + return 'string_to_jstring(env, %s, &%s)' % (right, left) + elif type in ('GList*',): elem_type = options.get('elem_type') if elem_type == 'char*': - return 'get_list_of_strings(env, %s)' % name + return 'get_list_of_strings(env, %s, &%s)' % (right, left) elif elem_type == 'xmlNode*': - return 'get_list_of_xml_nodes(env, %s)' % name + return 'get_list_of_xml_nodes(env, %s, &%s)' % (right, left) else: - return 'get_list_of_objects(env, %s)' % name - elif vtype in ('GHashTable*',): + return 'get_list_of_objects(env, %s, &%s)' % (right, left) + elif type in ('GHashTable*',): elem_type = options.get('elem_type') if elem_type == 'char*': - return 'get_hash_of_strings(env, %s)' % name + return 'get_hash_of_strings(env, %s, &%s)' % (right, left) else: - return 'get_hash_of_objects(env, %s)' % name - elif vtype == 'xmlNode*': - return 'xml_node_to_jstring(env, %s)' % name + return 'get_hash_of_objects(env, %s, &%s)' % (right, left) + elif type == 'xmlNode*': + return 'xml_node_to_jstring(env, %s, &%s)' % (right, left) else: - if 'return_owner' in options: - return 'gobject_to_jobject(env, (GObject*)%s);' % name + if options.get('return_owner'): + return 'gobject_to_jobject(env, (GObject*)%s, &%s);' % (right, left) else: - return 'gobject_to_jobject_and_ref(env, (GObject*)%s);' % name - - def java_to_c_value(self, left, right, vtype, options): - if vtype in ['gboolean','int', 'gint'] + self.binding_data.enums: - return '%s = (%s)%s;' % (left,vtype,right) - elif vtype in ('char*', 'gchar*'): - return '%s = (%s) jstring_to_string_dup(env, %s);' % (left,vtype,right) - elif vtype in ('const char*', 'const gchar*'): - return '%s = (%s) jstring_to_string(env, %s);' % (left,vtype,right) - elif vtype in ('GList*',): + return 'gobject_to_jobject_and_ref(env, (GObject*)%s, &%s);' % (right, left) + + def java_to_c_value(self, left, right, type, options): + if type in ['gboolean','int', 'gint'] + self.binding_data.enums: + return '%s = (%s)%s;' % (left,type,right) + elif is_string_type(type): + return 'jstring_to_string(env, %s, (char**)&%s);' % (right,left) + elif type in ('GList*',): elem_type = options.get('elem_type') if elem_type == 'char*': return 'set_list_of_strings(env, &%s,%s);' % (left,right) @@ -398,19 +431,16 @@ public static native void init2(); return 'set_list_of_xml_nodes(env, &%s, %s);' % (left, right) else: return 'set_list_of_objects(env, &%s, %s);' % (left, right) - elif vtype in ('GHashTable*',): + elif type in ('GHashTable*',): elem_type = options.get('elem_type') if elem_type == 'char*': return 'set_hash_of_strings(env, %s, %s);' % (left,right) else: return 'set_hash_of_objects(env, %s, %s);' % (left,right) - elif vtype == 'xmlNode*': - return '%s = jstring_to_xml_node(env, %s);' % (left, right) + elif type == 'xmlNode*': + return 'jstring_to_xml_node(env, %s, &%s);' % (right, left) else: - if 'return_owner' in options: - return '%s = (%s)jobject_to_gobject(env, %s);' % (left,vtype,right) - else: - return '%s = (%s)jobject_to_gobject_and_ref(env, %s);' % (left,vtype,right) + return 'jobject_to_gobject(env, %s, (GObject**)&%s);' % (right, left) def generate_wrapper_function(self, m, fd): print >> fd, '/* Wrapper function for ', @@ -447,12 +477,12 @@ public static native void init2(); print >> fd, ' {' idx = 0 if m.return_type: - print >> fd, '%s ret;' % jtype + print >> fd, ' %s ret;' % jtype # Declare C args for arg in m.args: idx = idx + 1 arg_type, arg_name, arg_options = arg - print >> fd, ' %s %s;' % (arg_type,arg_name) + print >> fd, ' %s %s;' % (arg_type.replace('const ',''),arg_name) # Declare return vars if m.return_type: print >> fd, ' %s return_value;' % m.return_type @@ -461,33 +491,50 @@ public static native void init2(); for arg in m.args: idx = idx + 1 arg_type, arg_name, arg_options = arg - option = arg_options.copy() - option['return_owner'] = 1 - print >> fd, ' %s' % self.java_to_c_value(arg_name, 'jarg%s' % idx, arg_type, option) + print >> fd, ' %s' % self.java_to_c_value(arg_name, 'jarg%s' % idx, arg_type, arg_options) + if debug: + print >> fd, ' printf("%s' % name, + arglist = '' + for arg in m.args: + arg_type, arg_name, arg_options = arg + arglist = arglist + ', %s' % arg_name + if self.is_int_type(arg_type): + print >> fd, '%i', + elif is_string_type(arg_type): + print >> fd, '%s', + else: + print >> fd, '%p', + print >> fd, '\\n"%s);' % arglist # Call function print >> fd, ' ', if m.return_type: print >> fd, 'return_value = (%s)' % m.return_type, print >> fd, '%s(%s);' % (m.name, ', '.join([x[1] for x in m.args])) - options = {} # Free const char * args idx=0 for arg in m.args: idx=idx+1 arg_type, arg_name, arg_options = arg - if arg_type in ('const gchar*', 'const char*'): - print >> fd, ' release_utf_string(env, jarg%s, %s);' % (idx,arg_name) + if is_string_type(arg_type): + print >> fd, ' if (%s)' % arg_name + print >> fd, ' g_free(%s);' % arg_name # Return if m.return_type: if m.name.endswith('_new'): - print >> fd, ' return (jlong) return_value;' + print >> fd, ' ret = (jlong)(int) return_value;' else: + options = {} if m.return_owner: - options['return_owner'] = 1 - print >> fd, ' ret = %s;' % self.c_to_java_value('return_value', m.return_type, options) - if m.return_type == 'GList*' and not m.return_owner: - print >> fd, ' free_glist(return_value, NULL);' + options = with_return_owner({}) + print >> fd, ' %s;' % self.c_to_java_value('ret','return_value', m.return_type, options) + if m.return_owner: + if m.return_type == 'GList*': + print >> fd, ' free_glist(&return_value, NULL);' + elif is_string_type(m.return_type): + print >> fd, ' if (return_value)' + print >> fd, ' g_free(return_value);' + print >> fd, ' return ret;' print >> fd, ' }' def generate_wrapper_getter_setter(self, c, fd): @@ -500,23 +547,42 @@ public static native void init2(); print >> fd,'/* Getter for %s %s.%s */' % (mtype,klassname,m[1]) wrapper_decl("%s_get" % prefix, jtype, fd) print >> fd, ', jobject jobj)\n {' - print >> fd, ' %s *gobj = (%s*)jobject_to_gobject(env, jobj);' % (klassname,klassname) + print >> fd, ' %s *gobj;' % klassname + print >> fd, ' jobject_to_gobject(env, jobj, (GObject**)&gobj);' + if debug: + print >> fd, ' printf("%s_get %%p %%p\\n", gobj, gobj->%s);' % (prefix, m[1]) + print >> fd, ' %s ret = 0;' % jtype print >> fd, ' if (gobj) {' - print >> fd, ' return %s;' % self.c_to_java_value ('gobj->%s' % m[1], mtype, m[2]) + print >> fd, ' %s;' % self.c_to_java_value ('ret','gobj->%s' % m[1], mtype, m[2]) print >> fd, ' } else {' print >> fd, ' (*env)->ThrowNew(env, "java/lang/NullPointerException", "no gobject correspond to the given object");' - print >> fd, ' return 0;' print >> fd, ' }' + print >> fd, ' return ret;' print >> fd, '}' print >> fd, '' # setter print >> fd,'/* Setter for %s %s.%s */' % (mtype,klassname,m[1]) wrapper_decl("%s_set" % prefix, 'void', fd) print >> fd, ', jobject jobj, %s value)\n {' % self.jni_return_type(mtype) - print >> fd, ' %s *gobj = (%s*)jobject_to_gobject(env, jobj);' % (klassname,klassname) - if mtype in ('char*', 'const char*', 'gchar*', 'const gchar*'): - print >> fd, ' g_free(gobj->%s);' % m[1] + print >> fd, ' %s *gobj;' % klassname + if debug: + print >> fd, ' printf("%s_set %%p %%p\\n", gobj, value);' % prefix + print >> fd, ' jobject_to_gobject(env, jobj, (GObject**)&gobj);' + print >> fd, ' if (!gobj) {' + print >> fd, ' (*env)->ThrowNew(env, "java/lang/NullPointerException", "no gobject correspond to the given object");' + print >> fd, ' }' + if not self.is_int_type(mtype) and not is_collection(mtype): + print >> fd, ' if (gobj->%s) {' % m[1] + if is_string_type(mtype): + print >> fd, ' g_free(gobj->%s);' % m[1] + else: + print >> fd, ' g_object_unref(gobj->%s);' % m[1] + print >> fd, ' }' print >> fd, ' %s' % self.java_to_c_value('gobj->%s' % m[1], 'value', mtype, m[2]) + if self.is_gobject_type(mtype): + print >> fd, ' if (gobj->%s) {' % m[1] + print >> fd, ' g_object_ref(gobj->%s);' % m[1] + print >> fd, ' }' print >> fd, '}' # add/remove if mtype in ('GList*', ): @@ -525,8 +591,9 @@ public static native void init2(); elem_type = m[2].get('elem_type') wrapper_decl("%s_add" % prefix, 'void', fd) print >> fd, ', jobject jobj, %s value)\n {' % jni_elem_type(elem_type) - print >> fd, ' %s *gobj = (%s*)jobject_to_gobject(env, jobj);' % (klassname,klassname) - if elem_type in ('char*','gchar*'): + print >> fd, ' %s *gobj;' % klassname + print >> fd, ' jobject_to_gobject(env, jobj, (GObject**)&gobj);' + if is_string_type(elem_type): print >> fd, ' add_to_list_of_strings(env, &gobj->%s,value);' % m[1] elif elem_type in ('xmlNode*',): print >> fd, ' add_to_list_of_xml_nodes(env, &gobj->%s,value);' % m[1] @@ -534,17 +601,17 @@ public static native void init2(); print >> fd, ' add_to_list_of_objects(env, &gobj->%s,value);' % m[1] print >> fd, '}' # remove - print >> fd,'/* Remover for %s %s.%s */' % (mtype,klassname,m[1]) - wrapper_decl("%s_remove" % prefix, 'void', fd) - print >> fd, ', jobject jobj, %s value)\n {' % jni_elem_type(elem_type) - print >> fd, ' %s *gobj = (%s*)jobject_to_gobject(env, jobj);' % (klassname,klassname) - if elem_type in ('char*','gchar*'): - print >> fd, ' remove_from_list_of_strings(env, &gobj->%s,value);' % m[1] - elif elem_type in ('xmlNode*',): - print >> fd, ' remove_from_list_of_xml_nodes(env, &gobj->%s,value);' % m[1] - else: - print >> fd, ' remove_from_list_of_objects(env, &gobj->%s,value);' % m[1] - print >> fd, '}' + if elem_type not in ('xmlNode*',): + print >> fd,'/* Remover for %s %s.%s */' % (mtype,klassname,m[1]) + wrapper_decl("%s_remove" % prefix, 'void', fd) + print >> fd, ', jobject jobj, %s value)\n {' % jni_elem_type(elem_type) + print >> fd, ' %s *gobj;' % klassname + print >> fd, ' jobject_to_gobject(env, jobj, (GObject**)&gobj);' + if elem_type in ('char*','gchar*'): + print >> fd, ' remove_from_list_of_strings(env, &gobj->%s,value);' % m[1] + else: + print >> fd, ' remove_from_list_of_objects(env, &gobj->%s,value);' % m[1] + print >> fd, '}' # add/remove/get_by_name if mtype in ('GHashTable*',): # add @@ -552,32 +619,35 @@ public static native void init2(); elem_type = m[2].get('elem_type') wrapper_decl("%s_add" % prefix, 'void', fd) print >> fd, ', jobject jobj, jstring key, %s value)\n {' % jni_elem_type(elem_type) - print >> fd, ' %s *gobj = (%s*)jobject_to_gobject(env, jobj);' % (klassname,klassname) + print >> fd, ' %s *gobj;' % klassname + print >> fd, ' jobject_to_gobject(env, jobj, (GObject**)&gobj);' if elem_type in ('char*','gchar*'): print >> fd, ' add_to_hash_of_strings(env, gobj->%s,value,key);' % m[1] else: print >> fd, ' add_to_hash_of_objects(env, gobj->%s,value,key);' % m[1] print >> fd, '}' - # remove - print >> fd,'/* Remover for %s %s.%s */' % (mtype,klassname,m[1]) - wrapper_decl("%s_remove" % prefix, 'void', fd) - print >> fd, ', jobject jobj, jstring key)\n {' - print >> fd, ' %s *gobj = (%s*)jobject_to_gobject(env, jobj);' % (klassname,klassname) - if elem_type in ('char*','gchar*'): - print >> fd, ' remove_from_hash_of_strings(env, gobj->%s,key);' % m[1] - else: - print >> fd, ' remove_from_hash_of_objects(env, gobj->%s,key);' % m[1] - print >> fd, '}' - # get by name - print >> fd,'/* Get by name for %s %s.%s */' % (mtype,klassname,m[1]) - wrapper_decl("%s_get_by_name" % prefix, jni_elem_type(elem_type) , fd) - print >> fd, ', jobject jobj, jstring key)\n {' - print >> fd, ' %s *gobj = (%s*)jobject_to_gobject(env, jobj);' % (klassname,klassname) - if elem_type in ('char*','gchar*'): - print >> fd, ' return get_hash_of_strings_by_name(env, gobj->%s,key);' % m[1] - else: - print >> fd, ' return get_hash_of_objects_by_name(env, gobj->%s,key);' % m[1] - print >> fd, '}' +# # remove +# print >> fd,'/* Remover for %s %s.%s */' % (mtype,klassname,m[1]) +# wrapper_decl("%s_remove" % prefix, 'void', fd) +# print >> fd, ', jobject jobj, jstring key)\n {' +# print >> fd, ' %s *gobj;' % klassname +# print >> fd, ' jobject_to_gobject(env, jobj, (GObject**)&gobj);' +# if elem_type in ('char*','gchar*'): +# print >> fd, ' remove_from_hash_of_strings(env, gobj->%s,key);' % m[1] +# else: +# print >> fd, ' remove_from_hash_of_objects(env, gobj->%s,key);' % m[1] +# print >> fd, '}' +# # get by name +# print >> fd,'/* Get by name for %s %s.%s */' % (mtype,klassname,m[1]) +# wrapper_decl("%s_get_by_name" % prefix, jni_elem_type(elem_type) , fd) +# print >> fd, ', jobject jobj, jstring key)\n {' +# print >> fd, ' %s *gobj;' % klassname +# print >> fd, ' jobject_to_gobject(env, jobj, (GObject**)&gobj);' +# if elem_type in ('char*','gchar*'): +# print >> fd, ' return get_hash_of_strings_by_name(env, gobj->%s,key);' % m[1] +# else: +# print >> fd, ' return get_hash_of_objects_by_name(env, gobj->%s,key);' % m[1] +# print >> fd, '}' # def generate_exception_switch_case(self, fd, name, orig): @@ -654,6 +724,7 @@ public static native void init2(); path = lasso_java_path + '%s.java' % class_name fd = open(path,'w') print >> fd, 'package %s;' % lasso_package_name + print >> fd, 'import java.util.*;' print >> fd, '' #print 'class %s extends %s {' % (class_name,parent_name) print >> fd, 'public class %s extends %s {' % (class_name,parent_name) @@ -690,31 +761,46 @@ public static native void init2(); jname = utils.format_as_camelcase('_'+name) jtype = self.JNI_member_type(m) if type == 'GList*': - print >> fd, ' public void set%s(%s[] value) {' % (jname,jtype) - print >> fd, ' LassoJNI.%s_set(this, value);' % prefix + print >> fd, ' public void set%s(List list) {' % jname + print >> fd, ' %s[] arr = null;' % jtype + print >> fd, ' if (list != null) {' + print >> fd, ' arr = new %s[list.size()];' % jtype + print >> fd, ' listToArray(list, arr);' + print >> fd, ' }' + print >> fd, ' LassoJNI.%s_set(this, arr);' % prefix print >> fd, ' }' - print >> fd, ' public %s[] get%s() {' % (jtype,jname) - print >> fd, ' return LassoJNI.%s_get(this);' % prefix + print >> fd, ' public List get%s() {' % jname + print >> fd, ' %s[] arr = LassoJNI.%s_get(this);' % (jtype,prefix) + print >> fd, ' if (arr != null)' + print >> fd, ' return Arrays.asList(arr);' + print >> fd, ' else' + print >> fd, ' return null;' print >> fd, ' }' print >> fd, ' public void addTo%s(%s value) {' % (jname,jtype) print >> fd, ' LassoJNI.%s_add(this, value);' % prefix print >> fd, ' }' - print >> fd, ' public void removeFrom%s(%s value) {' % (jname,jtype) - print >> fd, ' LassoJNI.%s_remove(this, value);' % prefix - print >> fd, ' }' + if m[2].get('elem_type') not in ('xmlNode*',): + print >> fd, ' public void removeFrom%s(%s value) {' % (jname,jtype) + print >> fd, ' LassoJNI.%s_remove(this, value);' % prefix + print >> fd, ' }' elif type == 'GHashTable*': - print >> fd, ' public void set%s(%s[] value) {' % (jname,jtype) - print >> fd, ' LassoJNI.%s_set(this, value);' % prefix + print >> fd, ' public void set%s(Map map) {' % jname + print >> fd, ' %s[] arr = null;' % jtype + print >> fd, ' if (map != null) {' + print >> fd, ' arr = new %s[map.size()*2];' % jtype + print >> fd, ' mapToArray(map,arr);' + print >> fd, ' }' + print >> fd, ' LassoJNI.%s_set(this, arr);' % prefix print >> fd, ' }' - print >> fd, ' public %s[] get%s() {' % (jtype,jname) - print >> fd, ' return LassoJNI.%s_get(this);' % prefix + print >> fd, ' public Map get%s() {' % jname + print >> fd, ' return arrayToMap(LassoJNI.%s_get(this));' % prefix print >> fd, ' }' print >> fd, ' public void addTo%s(String key, %s value) {' % (jname,jtype) print >> fd, ' LassoJNI.%s_add(this, key, value);' % prefix print >> fd, ' }' - print >> fd, ' public void removeFrom%s(String key) {' % (jname) - print >> fd, ' LassoJNI.%s_remove(this, key);' % prefix - print >> fd, ' }' +# print >> fd, ' public void removeFrom%s(String key) {' % (jname) +# print >> fd, ' LassoJNI.%s_remove(this, key);' % prefix +# print >> fd, ' }' #print ' void set%s(%s[] value)' % (jname,jtype) #print ' %s[] get%s()' % (jtype,jname) #print ' void addTo%s(String key, %s value)' % (jname,jtype) @@ -741,7 +827,7 @@ public static native void init2(); wrapper.initial_indent = first wrapper.subsequent_indent = ' * ' str = re.sub(r'\bNULL\b','null', str) - str = re.sub(r'#Lasso(\w+)',r'{@link \1}',str) + str = re.sub(r'#Lasso(\w+)',r'{@@link \1}',str) str = re.sub(r'[^.]*must *be *freed *by[^.]*\.?', '', str) str = re.sub(r'[^.]*internally[^.]*\.?[^.]*freed[^.]*\.?', '', str) @@ -760,20 +846,32 @@ public static native void init2(); err = error_to_exception(err)[0] print >> fd, normalize(err,' * @throws ') print >> fd, ' **/' - print >> fd, ' public %s %s(%s) {' % (return_type,mname,generate_arg_list(self,args[1:])) - print >> fd, ' ', - if m.return_type: - print >> fd, 'return', - arglist = generate_arg_list2(args[1:]) - if arglist: - arglist = ', ' + arglist - if m.errors: - print >> fd, 'LassoException.throwError(', - print >> fd,'LassoJNI.%s(this%s)' % (jni_name,arglist), - if m.errors: - print >> fd, ');' + if m.return_type == 'GList*': + print >> fd, ' public List %s(%s) {' % (mname,generate_arg_list(self,args[1:])) + arglist = generate_arg_list2(args[1:]) + if arglist: + arglist = ', ' + arglist + print >> fd, ' Object[] arr = LassoJNI.%s(this%s);' % (jni_name,arglist) + print >> fd, ' if (arr != null)' + print >> fd, ' return Arrays.asList(arr);' + print >> fd, ' else' + print >> fd, ' return null;' + print >> fd, ' }' else: - print >> fd, ';' - print >> fd, ' }' + print >> fd, ' public %s %s(%s) {' % (return_type,mname,generate_arg_list(self,args[1:])) + print >> fd, ' ', + if m.return_type: + print >> fd, 'return', + arglist = generate_arg_list2(args[1:]) + if arglist: + arglist = ', ' + arglist + if m.errors: + print >> fd, 'LassoException.throwError(', + print >> fd,'LassoJNI.%s(this%s)' % (jni_name,arglist), + if m.errors: + print >> fd, ');' + else: + print >> fd, ';' + print >> fd, ' }' print >> fd, '}' fd.close() diff --git a/bindings/lang_java_wrapper_top.c b/bindings/lang_java_wrapper_top.c index 123bb996..60048e53 100644 --- a/bindings/lang_java_wrapper_top.c +++ b/bindings/lang_java_wrapper_top.c @@ -4,519 +4,781 @@ #include "com_entrouvert_lasso_LassoJNI.h" #include <string.h> -static GQuark lasso_wrapper_key; -typedef jobject (*Converter)(JNIEnv *env, void *); -typedef void *(*OutConverter)(JNIEnv *env, jobject); - -/* String handling */ -static jstring string_to_jstring(JNIEnv *env, const char *str); -static jstring string_to_jstring_and_free(JNIEnv *env, char *str); -static const char* jstring_to_string(JNIEnv *env, jstring str); -static void release_utf_string(JNIEnv *env, jstring str, const char *utfstr); - -/* xmlNode handling */ -static jstring xml_node_to_jstring(JNIEnv *env, xmlNode *xmlnode); -static xmlNode* jstring_to_xml_node(JNIEnv *env, jstring string); - -/* Lasso object handling */ -/* Reference counting: - * - * new jobject make ++refcount - * - */ - -static GObject* jobject_to_gobject(JNIEnv *env, jobject *obj); -static GObject* jobject_to_gobject_and_ref(JNIEnv *env, jobject *obj); -static jobject gobject_to_jobject(JNIEnv *env, GObject *obj); -static jobject gobject_to_jobject_and_ref(JNIEnv *env, GObject *obj); - -/* List handling */ -static void free_glist(GList **list, GFunc free_function) ; -static jobjectArray get_list(JNIEnv *, char *,GList *, Converter); -#define get_list_of_strings(env,list) get_list(env,"java/lang/String",list,(Converter)string_to_jstring) -#define get_list_of_xml_nodes(env,list) get_list(env,"java/lang/String",list,(Converter)xml_node_to_jstring) -#define get_list_of_objects(env,list) get_list(env,"java/lang/Object",list,(Converter)gobject_to_jobject_and_ref) -static void set_list(JNIEnv*,GList **, jobjectArray jarr,GFunc free_function, OutConverter); +#define LASSO_ROOT "com/entrouvert/lasso/" +#define check_exception (*env)->ExceptionCheck(env) +#define g_return_val_if_exception(value) if ((*env)->ExceptionCheck(env)) return (value); +#define g_return_if_exception() if ((*env)->ExceptionCheck(env)) return; +#define convert_jlong_to_gobject(value) ((GObject*)(ptrdiff_t)value) +#define g_error_if_fail(value) { if (!(value)) { g_on_error_query("LassoJNI"); } } +#define PTR_TO_JLONG(x) (jlong)((ptrdiff_t)x) + +static GQuark lasso_wrapper_key = 0; +typedef int (*Converter)(JNIEnv *env, void *from, jobject *to); +typedef int *(*OutConverter)(JNIEnv *env, jobject from, gpointer *to); + +/* Static declarations */ +static int gpointer_equal(gpointer p1, gpointer p2); +static int new_object_with_gobject(JNIEnv *env, GObject *obj, char *clsName, jobject *jobj); +static int jstring_to_local_string(JNIEnv *env, jstring jstr, const char **str); +static void release_local_string(JNIEnv *env, jstring str, const char *utf_str); +static int get_jlong_field(JNIEnv *env, jobject obj, char *field, jlong *dest); +static jclass get_jclass_by_name(JNIEnv *env, char *name); +static int get_array_element(JNIEnv *env, jobjectArray arr, jsize i, jobject *dest); +static int set_array_element(JNIEnv *env, jobjectArray arr, jsize i, jobject value); +static int get_array_size(JNIEnv *env, jobjectArray arr, jsize *dest); +static int create_object_array(JNIEnv *env, char *clsName, jsize size, jobjectArray *jarr); +static jobject get_shadow_object(JNIEnv *env, GObject *obj); +static void set_shadow_object(JNIEnv *env, GObject *obj, jobject shadow_object); +static void exception(JNIEnv *env, char *message); +static int string_to_jstring(JNIEnv *env, const char* str, jstring *jstr); +static int string_to_jstring_and_free(JNIEnv *env, char* str, jstring *jstr); +static int jstring_to_string(JNIEnv *env, jstring jstr, char **str); +static int xml_node_to_jstring(JNIEnv *env, xmlNode *xmlnode, jstring *jstr); +static int jstring_to_xml_node(JNIEnv *env, jstring jstr, xmlNode **xmlnode); +static int gobject_to_jobject_aux(JNIEnv *env, GObject *obj, gboolean doRef, jobject *job); +static int gobject_to_jobject(JNIEnv *env, GObject *obj, jobject *jobj); +static int gobject_to_jobject_and_ref(JNIEnv *env, GObject *obj, jobject *jobj); + +static int jobject_to_gobject(JNIEnv *env, jobject obj, GObject **gobj); +static int jobject_to_gobject_for_list(JNIEnv *env, jobject *obj, GObject **gobj); +static void free_glist(GList **list, GFunc free_function); +static int get_list(JNIEnv *env, char *clsName, GList *list, Converter convert, jobjectArray *jarr); +static int set_list(JNIEnv *env, GList **list, jobjectArray jarr, GFunc free_function, OutConverter convert); +static int remove_from_list(JNIEnv *env,GList **list,jobject obj,GFunc free_function,GCompareFunc compare,OutConverter convert); +static int add_to_list(JNIEnv* env, GList** list, jobject obj, OutConverter convert); +static int get_hash(JNIEnv *env, char *clsName, GHashTable *hashtable, Converter convert, jobjectArray *jarr); +static int set_hash_of_objects(JNIEnv *env, GHashTable *hashtable, jobjectArray jarr); +static int set_hash_of_strings(JNIEnv *env, GHashTable *hashtable, jobjectArray jarr); +static int remove_from_hash(JNIEnv *env, GHashTable *hashtable, jstring jkey); +static int add_to_hash(JNIEnv *env, GHashTable *hashtable, jstring jkey, jobject jvalue, OutConverter convert, GFunc free_function); +static int get_hash_by_name(JNIEnv *env, GHashTable *hashtable, jstring jkey, Converter convert, jobject *jvalue); +#define get_list_of_strings(env,list,jarr) get_list(env,"java/lang/String",list,(Converter)string_to_jstring,jarr) +#define get_list_of_xml_nodes(env,list,jarr) get_list(env,"java/lang/String",list,(Converter)xml_node_to_jstring,jarr) +#define get_list_of_objects(env,list,jarr) get_list(env,"java/lang/Object",list,(Converter)gobject_to_jobject_and_ref,jarr) #define set_list_of_strings(env,list,jarr) set_list(env,list,jarr,(GFunc)g_free,(OutConverter)jstring_to_string) #define set_list_of_xml_nodes(env,list,jarr) set_list(env,list,jarr,(GFunc)xmlFreeNode,(OutConverter)jstring_to_xml_node) -#define set_list_of_objects(env,list,jarr) set_list(env,list,jarr,(GFunc)g_object_unref,(OutConverter)jobject_to_gobject_and_ref) -static void remove_from_list(JNIEnv*,GList**,jobject,GFunc,GCompareFunc,OutConverter); -#define remove_from_list_of_strings(env,list,obj) remove_from_list(env,list,obj,(GFunc)g_free,(GCompareFunc)strcmp,(OutConverter)jstring_to_string) -#define remove_from_list_of_xml_nodes(env,list,obj) remove_from_list(env,list,obj,(GFunc)xmlFreeNode,(GCompareFunc)strcmp,(OutConverter)jstring_to_xml_node) -#define remove_from_list_of_objects(env,list,obj) remove_from_list(env,list,obj,(GFunc)g_object_unref,(GCompareFunc)strcmp,(OutConverter)jobject_to_gobject_and_ref) -static void add_to_list(JNIEnv*,GList**,void *,OutConverter); +#define set_list_of_objects(env,list,jarr) set_list(env,list,jarr,(GFunc)g_object_unref,(OutConverter)jobject_to_gobject_for_list) +// remove_from_list_of_strings is now implemented directly +//#define remove_from_list_of_strings(env,list,obj) remove_from_list(env,list,obj,(GFunc)g_free,(GCompareFunc)strcmp,(OutConverter)jstring_to_local_string) +//#define remove_from_list_of_xml_nodes(env,list,obj) remove_from_list(env,list,obj,(GFunc)xmlFreeNode,(GCompareFunc)strcmp,(OutConverter)jstring_to_xml_node) +#define remove_from_list_of_objects(env,list,obj) remove_from_list(env,list,obj,(GFunc)g_object_unref,(GCompareFunc)gpointer_equal,(OutConverter)jobject_to_gobject) #define add_to_list_of_strings(env,list,obj) add_to_list(env,list,obj,(OutConverter)jstring_to_string) #define add_to_list_of_xml_nodes(env,list,obj) add_to_list(env,list,obj,(OutConverter)jstring_to_xml_node) -#define add_to_list_of_objects(env,list,obj) add_to_list(env,list,obj,(OutConverter)jobject_to_gobject_and_ref) - -/* hashtable handling */ -/* Use property array cell[i % 2 = 0] = keys and cell[i % 2 = 1] = values */ -static jobjectArray get_hash(JNIEnv *env, char *clsName, GHashTable *hashtable, Converter convert); -#define get_hash_of_strings(env,hash) get_hash(env,"java/lang/String",hash,(Converter)string_to_jstring) -#define get_hash_of_objects(env,hash) get_hash(env,"java/lang/String",hash,(Converter)gobject_to_jobject_and_ref) -static void set_hash(JNIEnv *env, GHashTable *hashtable, jobjectArray arr, OutConverter convert); -#define set_hash_of_strings(env,hash,arr) set_hash(env,hash,arr,(OutConverter)jstring_to_string) -#define set_hash_of_objects(env,hash,arr) set_hash(env,hash,arr,(OutConverter)jobject_to_gobject_and_ref) -static void remove_from_hash(JNIEnv *env, GHashTable *hashtable, jstring key); -#define remove_from_hash_of_strings(env,hash,key) remove_from_hash(env,hash,key) -#define remove_from_hash_of_objects(env,hash,key) remove_from_hash(env,hash,key) -static void add_to_hash(JNIEnv *env, GHashTable *hashtable, jstring key, jobject obj, OutConverter convert); +// Use jobject_to_gobject_for_list because ref count must be augmented by one when inserted inside a list +#define add_to_list_of_objects(env,list,obj) add_to_list(env,list,obj,(OutConverter)jobject_to_gobject_for_list) +#define get_hash_of_strings(env,hash,jarr) get_hash(env,"java/lang/String",hash,(Converter)string_to_jstring, jarr) +#define get_hash_of_objects(env,hash,jarr) get_hash(env,"java/lang/String",hash,(Converter)gobject_to_jobject_and_ref, jarr) +//#define remove_from_hash_of_strings(env,hash,key) remove_from_hash(env,hash,key) +//#define remove_from_hash_of_objects(env,hash,key) remove_from_hash(env,hash,key) #define add_to_hash_of_strings(env,hash,key,obj) add_to_hash(env,hash,key,obj,(OutConverter)jstring_to_string) -#define add_to_hash_of_objects(env,hash,key,obj) add_to_hash(env,hash,key,obj,(OutConverter)jobject_to_gobject_and_ref) -static jobject get_hash_by_name(JNIEnv *env, GHashTable *hashtable, jstring key, Converter convert); -#define get_hash_of_strings_by_name(end,hash,key) get_hash_by_name(end,hash,key,(Converter)string_to_jstring) -#define get_hash_of_objects_by_name(end,hash,key) get_hash_by_name(end,hash,key,(Converter)gobject_to_jobject_and_ref) +#define add_to_hash_of_objects(env,hash,key,obj) add_to_hash(env,hash,key,obj,(OutConverter)jobject_to_gobject_for_list) +//#define get_hash_of_strings_by_name(end,hash,key) get_hash_by_name(end,hash,key,(Converter)string_to_jstring) +//#define get_hash_of_objects_by_name(end,hash,key) get_hash_by_name(end,hash,key,(Converter)gobject_to_jobject_and_ref) + +/* Helper functions to access JNI interface functions */ +static int +gpointer_equal(gpointer p1, gpointer p2) { + return p1 != p2; +} +static int +new_object_with_gobject(JNIEnv *env, GObject *obj, char *clsName, jobject *jobj) { + jclass cls; + jmethodID mid; + g_error_if_fail(env && clsName && obj && G_IS_OBJECT(obj)); + g_return_val_if_fail(cls = (*env)->FindClass(env, clsName), 0); + g_return_val_if_fail(mid = (*env)->GetMethodID(env, cls, "<init>", "(J)V"), 0); + g_return_val_if_fail(*jobj = (*env)->NewObject(env, cls, mid, PTR_TO_JLONG(obj)), 0); + return 1; +} +/** Convert a java string to a jstring */ +static int +jstring_to_local_string(JNIEnv *env, jstring jstr, const char **str) +{ + g_error_if_fail(env); -/* utility functions */ -static jlong -get_jlong_field(JNIEnv *env, jobject *obj, char *field) + if (jstr) { + *str = (*env)->GetStringUTFChars(env, jstr, NULL); + g_return_val_if_fail(*str, 0); + } else { + *str = NULL; + } + return 1; +} +/** Release a local string. IT'S MANDATORY TO CALL THIS !!! */ +static void +release_local_string(JNIEnv *env, jstring str, const char *utf_str) { + g_error_if_fail(env); + + if (utf_str && str) { + (*env)->ReleaseStringUTFChars(env, str, utf_str); + } +} +static int +get_jlong_field(JNIEnv *env, jobject obj, char *field, jlong *dest) { jclass cls; jfieldID fid; cls = (*env)->GetObjectClass(env, obj); - if (cls == NULL) - return 0; + g_return_val_if_fail(cls, 0); fid = (*env)->GetFieldID(env, cls, field, "J"); - if (fid == NULL) - return 0; - return (*env)->GetLongField(env, obj, fid); + g_return_val_if_fail(fid, 0); + *dest = (*env)->GetLongField(env, obj, fid); + g_return_val_if_exception(0); + + return 1; } static jclass get_jclass_by_name(JNIEnv *env, char *name) { return (*env)->FindClass(env,name); } +static int +get_array_element(JNIEnv *env, jobjectArray arr, jsize i, jobject *dest) { + *dest = (*env)->GetObjectArrayElement(env, arr, i); + g_return_val_if_fail(! (*env)->ExceptionCheck(env), 0); + return 1; +} +static int +set_array_element(JNIEnv *env, jobjectArray arr, jsize i, jobject value) { + (*env)->SetObjectArrayElement(env, arr, i, value); + g_return_val_if_exception(0); + return 1; +} +static int +get_array_size(JNIEnv *env, jobjectArray jarr, jsize *dest) { + *dest = (*env)->GetArrayLength(env, jarr); + g_return_val_if_exception(0); + return 1; +} +static int +create_object_array(JNIEnv *env, char *clsName, jsize size, jobjectArray *jarr) { + jclass cls; -/* string handling impl */ -static jstring -string_to_jstring(JNIEnv *env, const char* str) -{ - if (str) - return (*env)->NewStringUTF(env, str); - else + g_error_if_fail(env && clsName && jarr); + + cls = get_jclass_by_name(env, clsName); + g_return_val_if_fail(cls, 0); + *jarr = (*env)->NewObjectArray(env, size, get_jclass_by_name(env, clsName), NULL); + g_return_val_if_fail(*jarr, 0); + return 1; +} +static int nullWeakRef(JNIEnv *env, jweak weakRef) { + return weakRef && (*env)->IsSameObject(env, weakRef, NULL); +} +/** Return the shadow object associated with the gobject. + * If the weak global reference is dead, frees it. + * If not shadow object is present, return NULL. */ +static jobject +get_shadow_object(JNIEnv *env, GObject *obj) { + jweak weakRef; + + g_error_if_fail (obj && env); + weakRef = (jweak)g_object_get_qdata(obj, lasso_wrapper_key); + if (weakRef == NULL) { + return NULL; + } else if (nullWeakRef(env, weakRef)) { + /** Remove null weak ref. */ + (*env)->DeleteWeakGlobalRef(env, weakRef); + g_object_set_qdata(obj, lasso_wrapper_key, NULL); return NULL; + } else { + return (*env)->NewLocalRef(env, weakRef); + } +} +/** Sets the java shadow object associated with the GObject obj. + * If a shadow object is already present, frees its weak global reference. + * Replacing a non NULL weak global reference by another one should not happend. + * It means that two java shadow object for the same GObject exist at the same time + */ +static void +set_shadow_object(JNIEnv *env, GObject *obj, jobject shadow_object) { + jweak weakRef; + jweak old_weakRef; + + g_error_if_fail(obj && env); + + old_weakRef = (jweak)g_object_get_qdata(obj, lasso_wrapper_key); + if (old_weakRef) { + if (shadow_object != NULL && ! (*env)->IsSameObject(env, old_weakRef, NULL)) { + g_warning("remplacement d'un shadow object non nulle par un shadow object non nulle %p %p", shadow_object, old_weakRef); + } + (*env)->DeleteWeakGlobalRef(env, old_weakRef); + } + g_object_set_qdata(obj, lasso_wrapper_key, NULL); + if (shadow_object) { + weakRef = (*env)->NewWeakGlobalRef(env, shadow_object); + g_object_set_qdata(obj, lasso_wrapper_key, weakRef); + } +} +/** Throw a new RuntimeException containing this message. */ +static void +exception(JNIEnv *env, char *message) { + jclass cls = (*env)->FindClass(env, "java/lang/RuntimeException"); + if (cls != NULL) { + (*env)->ThrowNew(env, "java/lang/RuntimeException", message); + } + (*env)->DeleteLocalRef(env, cls); } -static jstring -string_to_jstring_and_free(JNIEnv *env, char* str) -{ +/* Conversion fonctions */ +/** Convert a C string to java string. NULL is a valid C string giving a null + * java object. */ +static int +string_to_jstring(JNIEnv *env, const char* str, jstring *jstr) { if (str) { - jstring ret = (*env)->NewStringUTF(env, str); - g_free(str); - return ret; + *jstr = (*env)->NewStringUTF(env, str); + g_return_val_if_fail(jstr, 0); } else { - return NULL; + *jstr = NULL; } + return 1; } -static const char * -jstring_to_string(JNIEnv *env, jstring str) -{ +/** Convert a string to a java string then free it. Don't frees it + * if conversion failed. */ +static int +string_to_jstring_and_free(JNIEnv *env, char* str, jstring *jstr) { + g_return_val_if_fail(string_to_jstring(env, str, jstr), 0); if (str) - return (*env)->GetStringUTFChars(env, str, NULL); - else - return NULL; -} - -static const char * -jstring_to_string_dup(JNIEnv *env, jstring jstr) -{ - const char *str = jstring_to_string(env, jstr); - char * ret = NULL; - - if (! str) - return NULL; - - ret = g_strdup(str); - release_utf_string(env, jstr, str); - return ret; + g_free(str); + return 1; } -static void -release_utf_string(JNIEnv *env, jstring str, const char *utf_str) { - if (utf_str && str) - (*env)->ReleaseStringUTFChars(env, str, utf_str); +/** Convert a jstring to a C string and copy it. Returned string is owner by the caller.*/ +static int +jstring_to_string(JNIEnv *env, jstring jstr, char **str) { + const char *local_str; + char * ret; + + g_return_val_if_fail(jstring_to_local_string(env, jstr, &local_str), 0); + if (local_str) { + *str = g_strdup(local_str); + release_local_string(env, jstr, local_str); + if (!str) { + /* Maybe launch a OutOfMemoryException. */ + exception(env, "could not alloc a copy of a jstring"); + return 0; + } + } else { + *str = NULL; + } + return 1; } /* xmlNode handling */ -static jstring -xml_node_to_jstring(JNIEnv *env, xmlNode *xmlnode) -{ +static int +xml_node_to_jstring(JNIEnv *env, xmlNode *xmlnode, jstring *jstr) { xmlOutputBufferPtr buf; - if (! xmlnode || ! env) { - return NULL; + g_error_if_fail(env); + if (! xmlnode) { + *jstr = NULL; + return 1; } buf = xmlAllocOutputBuffer(NULL); if (buf) { - jstring ret = NULL; + int ret = 1; xmlNodeDumpOutput(buf, NULL, xmlnode, 0, 1, NULL); xmlOutputBufferFlush(buf); + char *str; if (buf->conv == NULL) { - ret = string_to_jstring(env, (char*)buf->buffer->content); + str = (char*)buf->buffer->content; } else { - ret = string_to_jstring(env, (char*)buf->conv->content); + str = buf->conv->content; } + ret = string_to_jstring(env, str, jstr); xmlOutputBufferClose(buf); return ret; } else { - return NULL; + exception(env, "could not alloc an xml output buffer"); + return 0; } + return 1; } -static xmlNode* -jstring_to_xml_node(JNIEnv *env, jstring string) { - xmlDoc *doc; - xmlNode *node; - const char *str; - - str = jstring_to_string(env, string); - if (str == NULL) - return NULL; - - doc = xmlReadDoc((unsigned char *)str, NULL, NULL, XML_PARSE_NONET); - node = xmlDocGetRootElement(doc); - if (node != NULL) { - node = xmlCopyNode(node, 1); +/** Convert a java string to an xml node. Return 0 if it failed with an exception + * throwed. */ +static int +jstring_to_xml_node(JNIEnv *env, jstring jstr, xmlNode **xmlnode) { + xmlDoc *doc = NULL; + xmlNode *node = NULL; + const char *local_str; + int ret = 1; + + g_error_if_fail(env && xmlnode); + g_return_val_if_fail(jstring_to_local_string(env, jstr, &local_str), 0); + + if (local_str) { + doc = xmlReadDoc((unsigned char *)local_str, NULL, NULL, XML_PARSE_NONET); + if (!doc) { + exception(env, "could not read an xml document"); + ret = 0; + goto out; + } + node = xmlDocGetRootElement(doc); + if (node != NULL) { + node = xmlCopyNode(node, 1); + } } - xmlFreeDoc(doc); - release_utf_string(env, string, str); - - return node; +out: + *xmlnode = node; + if (doc) + xmlFreeDoc(doc); + if (jstr && local_str) + release_local_string(env, jstr, local_str); + return ret; } /* lasso objects handling impl */ -static jobject -gobject_to_jobject_aux(JNIEnv *env, GObject *obj, gboolean doRef) { - jobject *self; -#define LASSO_ROOT "com/entrouvert/lasso/" +static void +create_class_name(char *dest, const char *typename) { + char *ret; + + ret = strstr(typename, "Lasso"); + if (ret) { + typename = ret+5; + } + strncpy(dest+sizeof(LASSO_ROOT)-1, typename,50); + dest[sizeof(LASSO_ROOT)+49] = 0; +} +/** Convert the GObject obj to a java object encapsulating it. + * If obj is NULL, return NULL. + * Throws if obj is not a GObject or if anyhting fail. */ +static int +gobject_to_jobject_aux(JNIEnv *env, GObject *obj, gboolean doRef, jobject *jobj) { + jweak weakRef = NULL; + jobject self = NULL; + int ret = 1; + if (obj == NULL) { - return NULL; + goto out; + } + + if (! G_IS_OBJECT(obj)) { + exception(env, "tried to convert something that is not a GObject to a Java object"); + ret = 0; + goto out; } - self = (jobject)g_object_get_qdata(obj, lasso_wrapper_key); - if (self == NULL) { - jclass nodeCls; - jmethodID cid; + /* Try to get an already created java object. */ + self = get_shadow_object(env, obj); + if (self) { + goto out; + } else { + /* Create the shadow object */ char clsName[sizeof(LASSO_ROOT)+50] = LASSO_ROOT; - const char *typename = G_OBJECT_TYPE_NAME(obj); - if (! typename) // Moche - return NULL; - typename = typename + 5; - strncpy(clsName+sizeof(LASSO_ROOT)-1, typename,50); - clsName[sizeof(LASSO_ROOT)+49] = 0; - nodeCls = (*env)->FindClass(env, clsName); - if (nodeCls == NULL) { - return NULL; - } - cid = (*env)->GetMethodID(env, nodeCls, "<init>", "(J)V"); - if (cid == NULL) { - return NULL; - } - self = (*env)->NewObject(env, nodeCls, cid, (jlong)(unsigned int)obj); - if (self == NULL) { - return NULL; + const char *typename; + + typename = G_OBJECT_TYPE_NAME(obj); + create_class_name(clsName, typename); + if (! new_object_with_gobject(env, obj, clsName, &self)) { + ret = 0; + goto out; } - g_object_set_qdata_full(obj, lasso_wrapper_key, self, NULL); + set_shadow_object(env, obj, self); + /** If all goes well increment reference count eventually. */ if (doRef) { g_object_ref(obj); } } - return self; +out: + *jobj = self; + return ret; } /** Get or create a new java object encapsulating this lasso GObject, do not increase ref count if created. */ -static jobject -gobject_to_jobject(JNIEnv *env, GObject *obj) { - return gobject_to_jobject_aux(env, obj, FALSE); +static int +gobject_to_jobject(JNIEnv *env, GObject *obj, jobject *jobj) { + return gobject_to_jobject_aux(env, obj, FALSE, jobj); } /** Get or create a new java object encapsulating this lasso GObject, increase ref count if created. */ -static jobject -gobject_to_jobject_and_ref(JNIEnv *env, GObject *obj) { - return gobject_to_jobject_aux(env, obj, TRUE); +static int +gobject_to_jobject_and_ref(JNIEnv *env, GObject *obj, jobject *jobj) { + return gobject_to_jobject_aux(env, obj, TRUE, jobj); } -/** Get the gobject encapsulated by the java object obj */ -static GObject* -jobject_to_gobject(JNIEnv *env, jobject *obj) { - return (GObject*)(int)get_jlong_field(env, obj, "cptr"); +/** Get the gobject encapsulated by the java object obj. If cptr is + * null return NULL. + * It throws and return 0 if anything fail unexpectedly. */ +static int +jobject_to_gobject(JNIEnv *env, jobject obj, GObject **gobj) { + jlong value; + GObject *gobject; + + g_error_if_fail(env); + + if (! obj) { + *gobj = NULL; + return 1; + } + g_return_val_if_fail(get_jlong_field(env, obj, "cptr", &value), 0); + gobject = convert_jlong_to_gobject(value); + if (gobject && ! G_IS_OBJECT(gobject)) { +#define s "jobject->cptr is not a pointer on a gobject: XXXXXXXXXXXXXXXXXXXXXXX" + char str[] = s; + snprintf(str, sizeof(s)-1, "jobject->cptr is not a pointer on a gobject = %p", gobject); + exception(env, str); +#undef s + return 0; + } else { + *gobj = gobject; + return 1; + } } /** Get the gobject encapsulated by the java object obj and increase its ref count. The only * use for this function is composed with set_list_of_objects or set_hash_of_object. */ -static GObject* -jobject_to_gobject_and_ref(JNIEnv *env, jobject *obj) { - GObject *ret; - - ret = jobject_to_gobject(env, obj); - if (ret) { - g_object_ref(obj); +static int +jobject_to_gobject_for_list(JNIEnv *env, jobject *obj, GObject **gobj) { + g_return_val_if_fail(jobject_to_gobject(env, obj, gobj), 0); + if (*gobj) { + g_object_ref(*gobj); } - - return ret; + return 1; } + /* List handling */ static void free_glist(GList **list, GFunc free_function) { - if (!list) - return; + g_return_if_fail(list); if (*list) { if (free_function) { g_list_foreach(*list, free_function, NULL); } g_list_free(*list); } - if (list) - *list = NULL; + *list = NULL; } -static jobjectArray -get_list(JNIEnv *env, char *clsName, GList *list, Converter convert) { - jsize l = g_list_length(list),i; - jobjectArray jarr; +/** Get an object array from a GList*, convert C object to java object using + * the convert function. + * + * Can throw. If list is null or empty, return NULL. + */ +static int +get_list(JNIEnv *env, char *clsName, GList *list, Converter convert, jobjectArray *jarr) { + jsize l,i; jclass cls; - if (!env || !list || !clsName || !convert) { - return NULL; + g_error_if_fail (env && clsName && convert); + l = g_list_length(list); + if (!l) { + *jarr = NULL; + goto out; } cls = get_jclass_by_name(env, clsName); - if (!cls) { - return NULL; - } - - jarr = (*env)->NewObjectArray(env, l, get_jclass_by_name(env, clsName), NULL); - if (! jarr) { - return NULL; - } + g_return_val_if_fail(cls, 0); + g_return_val_if_fail(create_object_array(env, clsName, l, jarr), 0); for (i=0;i<l;i++) { jobject item; - item = convert(env, list->data); - if ((*env)->ExceptionOccurred(env)) { - return NULL; - } - (*env)->SetObjectArrayElement(env, jarr, i, item); - if ((*env)->ExceptionOccurred(env)) { - return NULL; - } + g_return_val_if_fail(convert(env, list->data, &item), 0); + g_return_val_if_fail(set_array_element(env, *jarr, i, item), 0); list = g_list_next(list); } - return jarr; +out: + return 1; } -static void +/** Sets a GList* field using a java array of object. Use free_function if an old list exist. + * Use convert to convert the java objects to C values. */ +static int set_list(JNIEnv *env, GList **list, jobjectArray jarr, GFunc free_function, OutConverter convert) { jobject element; jsize size; jsize i; - - if (!list || !free_function || !convert || !env) - return; - - free_glist(list, free_function); - if (!jarr) { - *list = NULL; - return; - } - size = (*env)->GetArrayLength(env, jarr); - for (i=0; i < size; i++) { - element = (*env)->GetObjectArrayElement(env, jarr, i); - if ((*env)->ExceptionOccurred(env)) { - free_glist(list, free_function); - return; + GList *new = NULL; + + g_error_if_fail (list && free_function && convert && env); + if (jarr) { + if (! get_array_size(env, jarr, &size)) + goto error; + for (i=0; i < size; i++) { + gpointer result; + + if (! get_array_element(env, jarr, i, &element) + || ! convert(env, element, &result)) { + goto error; + } + new = g_list_append(new, result); } - *list = g_list_append(*list, convert(env, element)); } -} -static void -remove_from_list(JNIEnv *env,GList **list,jobject obj,GFunc free_function,GCompareFunc compare,OutConverter convert) { - void *c; + free_glist(list, free_function); + *list = new; + return 1; + +error: + free_glist(&new, free_function); + return 0; +} +/** Remove a value obtained via the convert function on obj from *list. + * It is searched inside *list using the compare function. + * If pointer is found, it is freed using the free_function. + * Return 0 if an exception was throwed. + **/ +static int +remove_from_list(JNIEnv *env, GList **list, jobject obj, GFunc free_function, GCompareFunc compare, OutConverter convert) { + gpointer data; GList *found; - c = convert(env, obj); - if ((*env)->ExceptionOccurred(env)) { - return; - } - found = g_list_find_custom(*list, c, compare); + g_error_if_fail(env && list && compare && convert && free_function); + g_return_val_if_fail(obj, 1); + g_return_val_if_fail(convert(env, obj, &data), 0); + found = g_list_find_custom(*list, data, compare); if (found) { free_function(found->data, NULL); *list = g_list_delete_link(*list, found); } + return 1; } -static void -add_to_list(JNIEnv* env,GList** list,jobject obj, OutConverter convert) { - void *data; +static int +remove_from_list_of_strings(JNIEnv *env, GList **list, jstring jstr) { + const char *local_string; + GList *found; - data = convert(env, obj); - if ((*env)->ExceptionOccurred(env)) { - return; + g_error_if_fail(env && list); + g_return_val_if_fail(jstr, 1); + g_return_val_if_fail(jstring_to_local_string(env, jstr, &local_string), 0); + found = g_list_find_custom(*list, local_string, (GCompareFunc)strcmp); + if (found) { + g_free(found->data); + *list = g_list_delete_link(*list, found); } - *list = g_list_append(*list, data); + release_local_string(env, jstr, local_string); + return 1; } - -struct Aux { - JNIEnv *env; - Converter convert; - gboolean crashed; - int idx; - jobjectArray jarr; -}; -static void -get_hash_aux(gpointer key, gpointer data, gpointer udata) -{ - struct Aux *aux = (struct Aux*)udata; - JNIEnv *env = aux->env; - jobjectArray jarr = aux->jarr; - - if (! aux->crashed) { - jstring jkey; - jobject jvalue; - - jkey = string_to_jstring(env, key); - if (!jkey) { - aux->crashed = TRUE; - return; - } - jvalue = aux->convert(env, data); - if ((*env)->ExceptionOccurred(env)) { - aux->crashed = TRUE; - return; - } - (*env)->SetObjectArrayElement(env, jarr, aux->idx, jkey); - if ((*env)->ExceptionOccurred(env)) { - aux->crashed = TRUE; - return; - } - (*env)->SetObjectArrayElement(env, jarr, aux->idx+1, jvalue); - if ((*env)->ExceptionOccurred(env)) { - aux->crashed = TRUE; - return; - } - aux->idx += 2; - } +/** Add obj to GList *list. + * Returns 1. + * Returns 0 and throws if anything fail. + */ +static int +add_to_list(JNIEnv* env, GList** list, jobject obj, OutConverter convert) { + gpointer data; + + g_error_if_fail(env && list && convert); + g_return_val_if_fail(convert(env, obj, &data),0); + if (data) + *list = g_list_append(*list, data); + return 1; } /* Ghash table handling impl */ -/** Set a hash table from an array of size multiple of 2 */ -static jobjectArray -get_hash(JNIEnv *env, char *clsName, GHashTable *hashtable,Converter convert) +/** Create a java array from a GHashTable, using the convert function. */ +static int +get_hash(JNIEnv *env, char *clsName, GHashTable *hashtable, Converter convert, jobjectArray *jarr) { - jsize l; - jobjectArray jarr; + jsize l,i; jclass cls; - struct Aux udata = {env, convert, FALSE, 0, NULL }; - if (!env || !hashtable || !clsName || !convert) { - return NULL; - } + GList *keys = NULL, *values = NULL; + int ret = 1; + + g_error_if_fail (env && hashtable && convert); l = g_hash_table_size(hashtable); - cls = get_jclass_by_name(env, clsName); - if (!cls) { - return NULL; + g_return_val_if_fail(create_object_array(env, clsName, 2*l, jarr), 0); + keys = g_hash_table_get_keys(hashtable); + values = g_hash_table_get_values(hashtable); + if (! (keys && values)) { + ret = 0; + exception(env, "cannot allocate for converting GHashTable to an array"); + goto out; } - - udata.jarr = (*env)->NewObjectArray(env, l, get_jclass_by_name(env, clsName), NULL); - if (! jarr) { - return NULL; + for (i=0; i < 2*l && keys && values; i+=2) { + jstring key; + jobject value; + + if (! (string_to_jstring(env, (char*)keys->data, &key) + && convert(env, (gpointer)values->data, &value) + && set_array_element(env, *jarr, i, key) + && set_array_element(env, *jarr, i+1, value))) { + ret = 0; + goto out; + } + keys = g_list_next(keys); + values = g_list_next(values); } - g_hash_table_foreach (hashtable, (GHFunc)get_hash_aux, &udata); - if (udata.crashed) - return NULL; - return udata.jarr; +out: + if (keys) + g_list_free(keys); + if (values) + g_list_free(values); + return ret; +} +/** Fill a GHashTable with content of java array arr. + * Even indexed element coressponds to keys (jstring) and + * odd indexed one to value (GObject). + * Returns 1. + * Returns 0 and thows an exception if anything fail. + */ +static int +set_hash_of_objects(JNIEnv *env, GHashTable *hashtable, jobjectArray jarr) +{ + jsize l, i; + gpointer *array; + + g_error_if_fail (env && hashtable); + if (jarr) { + /** First increment ref count of object in jarr */ + g_return_val_if_fail(get_array_size(env, jarr, &l), 0); + if (l % 2 != 0) { + exception(env, "java array not of an even size"); + return 0; + } + for (i = 1; i < l; i += 2) { + jobject jobj; + GObject *gobj; + + g_return_val_if_fail(get_array_element(env, jarr, i, &jobj), 0); + g_return_val_if_fail(jobject_to_gobject(env, jobj, &gobj), 0); + g_object_ref(gobj); + } + } + /** Remove old values, if hashtable is well initialized it should unref objects automatically. */ + g_hashtable_remove_all(hashtable); + /** Insert new values */ + if (jarr) { + for (i = 0; i < l; i += 2) { + jstring jkey; + char *key; + jobject jvalue; + GObject *value; + + g_return_val_if_fail(get_array_element(env, jarr, i, &jkey), 0); + g_return_val_if_fail(get_array_element(env, jarr, i+1, &jvalue), 0); + g_return_val_if_fail(jstring_to_string(env, jkey, &key), 0); + if (! jobject_to_gobject(env, jvalue, &value)) { + if (key) + g_free(key); + g_hashtable_remove_all(hashtable); + return 0; + } + /* Can use insert because hash table is empty */ + g_hash_table_insert (hashtable, key, value); + (*env)->DeleteLocalRef(env, jkey); + (*env)->DeleteLocalRef(env, jvalue); + } + } + return 1; } -static void set_hash(JNIEnv *env, GHashTable *hashtable, jobjectArray arr, OutConverter convert) { +/** Insert a java String array, containing + * keys at odd indexes, and values at even indexes into an existing + * GHashTable. Old entries are lost, but hopefully deallocated by + * the hashtable free functions --- setted at creation, see GLib + * documentation. + * + * @param env the JNI context given by the JVM + * @param hashtable an existing GHashTable + * @param a ref to a java object Array of size multiple of two + * + * @return 1 if successful, 0 if anything bad happen. + */ +static int +set_hash_of_strings(JNIEnv *env, GHashTable *hashtable, jobjectArray jarr) { jsize l,i; - if (! env || ! hashtable || ! arr || ! convert) - return; + g_error_if_fail (env && hashtable); - l = (*env)->GetArrayLength(env, arr); - if ((*env)->ExceptionOccurred(env) || l % 2 != 0) { - return; - } g_hash_table_remove_all(hashtable); - for (i = 0; i < l; i += 2) { - jobject key,item; - const char *skey; - void *value; - - key = (*env)->GetObjectArrayElement(env, arr, i); - if ((*env)->ExceptionOccurred(env)) { - return; - } - item = (*env)->GetObjectArrayElement(env, arr, i); - if ((*env)->ExceptionOccurred(env)) { - return; - } - value = convert(env, item); - if ((*env)->ExceptionOccurred(env)) { - return; + if (jarr) { + g_return_val_if_fail(get_array_size(env, jarr, &l), 0); + if (l % 2 != 0) { + exception(env, "java array not of an even size"); + return 0; } - skey = jstring_to_string(env, (jstring)key); - if ((*env)->ExceptionOccurred(env)) { - return; + for (i = 0; i < l; i += 2) { + jstring jkey; + char *key; + jstring jvalue; + char *value; + + g_return_val_if_fail(get_array_element(env, jarr, i, &jkey) + && get_array_element(env, jarr, i+1, &jvalue) + && jstring_to_string(env, jkey, &key), 0); + if (! key) { + exception(env, "key is null"); + return 0; + } + if (! jstring_to_string(env, jvalue, &value), 0) { + if (key) + g_free(key); + g_hash_table_remove_all(hashtable); + return 0; + } + /* Can use insert because hash table is empty */ + g_hash_table_insert(hashtable, key, value); + (*env)->DeleteLocalRef(env, jkey); + (*env)->DeleteLocalRef(env, jvalue); } - g_hash_table_insert(hashtable, g_strdup(skey), value); - release_utf_string(env, key, skey); } + return 1; } -static void remove_from_hash(JNIEnv *env, GHashTable *hashtable, jstring key) { - const char *str; - if (! env || !hashtable || !key) { - return; - } - str = jstring_to_string(env, key); - if (!str) { - return; - } - g_hash_table_remove(hashtable, str); - release_utf_string(env, key, str); +/** Remove the value for the given key from hashtable. */ +static int +remove_from_hash(JNIEnv *env, GHashTable *hashtable, jstring jkey) { + const char *key; + + g_error_if_fail (env && hashtable); + + g_return_val_if_fail(jstring_to_local_string(env, jkey, &key), 0); + g_hash_table_remove(hashtable, key); + release_local_string(env, jkey, key); + return 1; } -static void add_to_hash(JNIEnv *env, GHashTable *hashtable, jstring key, jobject obj, OutConverter convert) +/** Add a jobject to an hashtable */ +static int +add_to_hash(JNIEnv *env, GHashTable *hashtable, jstring jkey, jobject jvalue, OutConverter convert, GFunc free_function) { - void *data; - const char *str; - - if (!env || !hashtable || !key || !obj || !convert) { - return; - } - data = convert(env, obj); - if ((*env)->ExceptionOccurred(env)) { - return; - } - str = jstring_to_string(env,key); - if (!str) { - return; - } - g_hash_table_insert(hashtable, g_strdup(str), data); - release_utf_string(env, key, str); + void *value = NULL; + char *key = NULL; + + g_error_if_fail (env && hashtable && key && convert); + + if (! (convert(env, jvalue, &value) + && jstring_to_string(env, jkey, &key))) + goto error; + + g_hash_table_replace(hashtable, key, value); + return 1; +error: + if (key) + g_free(key); + if (value) + free_function(value, NULL); + return 0; } -static jobject -get_hash_by_name(JNIEnv *env, GHashTable *hashtable, jstring key, Converter convert) +static int +get_hash_by_name(JNIEnv *env, GHashTable *hashtable, jstring jkey, Converter convert, jobject *jvalue) { - void *data; - const char *str; + const char *key; + gpointer value; - if (! env || !hashtable || !key || !convert) { - return NULL; - } - str = jstring_to_string(env,key); - if (!str) { - return NULL; - } - data = g_hash_table_lookup(hashtable,str); - release_utf_string(env, key, str); - return convert(env, data); + g_error_if_fail (env && hashtable && convert); + + g_return_val_if_fail(jstring_to_local_string(env, jkey, &key), 0); + value = g_hash_table_lookup(hashtable, key); + release_local_string(env, jkey, key); + return convert(env, value, jvalue); } /* JNI Functions */ JNIEXPORT void JNICALL Java_com_entrouvert_lasso_LassoJNI_init2(JNIEnv *env, jclass cls) { lasso_wrapper_key = g_quark_from_static_string("JavaLasso::wrapper"); } +JNIEXPORT void JNICALL Java_com_entrouvert_lasso_LassoJNI_destroy(JNIEnv *env, jclass cls, jlong cptr) { + GObject *obj = (GObject*)(ptrdiff_t)cptr; + set_shadow_object(env, obj, NULL); + g_object_unref(obj); +} +JNIEXPORT void JNICALL Java_com_entrouvert_lasso_LassoJNI_set_1shadow_1object(JNIEnv *env, jclass cls, jlong cptr, jobject shadow_object) { + GObject *gobj; + + gobj = convert_jlong_to_gobject(cptr); + set_shadow_object(env, gobj, shadow_object); +} diff --git a/bindings/overrides.xml b/bindings/overrides.xml index 418ee2e9..8cfa9ffc 100644 --- a/bindings/overrides.xml +++ b/bindings/overrides.xml @@ -18,6 +18,8 @@ <!-- LassoWsfProfile --> <func name="lasso_wsf_profile_get_identity" return_owner="false" /> <func name="lasso_wsf_profile_get_session" return_owner="false" /> + <!-- LassoIdentity --> + <func name="lasso_identity_get_federation" return_owner="false" /> <!-- LassoServer --> <func name="lasso_server_new"> <param name="private_key" optional="true"/> @@ -78,6 +80,8 @@ <func name="lasso_lib_federation_termination_notification_new_full" return_type="LassoLibFederationTerminationNotification*"/> <func name="lasso_lib_name_identifier_mapping_request_new_full" return_type="LassoLibNameIdentifierMappingRequest*"/> <func name="lasso_lib_register_name_identifier_request_new_full" return_type="LassoLibRegisterNameIdentifierRequest*"/> + <!-- LassoServer --> + <func name="lasso_server_get_provider" return_owner="false" /> <!-- Exceptions --> <exception> |