diff options
-rw-r--r-- | bindings/Makefile.am | 2 | ||||
-rw-r--r-- | bindings/bindings.py | 38 | ||||
-rw-r--r-- | bindings/java/GObject.java | 9 | ||||
-rw-r--r-- | bindings/java/LassoException_top.java | 31 | ||||
-rw-r--r-- | bindings/java/Makefile.am | 40 | ||||
-rw-r--r-- | bindings/java/TODO | 14 | ||||
-rw-r--r-- | bindings/java/tests/BindingTests.java | 282 | ||||
-rw-r--r-- | bindings/java/tests/LoginTest.java | 244 | ||||
-rw-r--r-- | bindings/java/tests/Test.java | 11 | ||||
-rw-r--r-- | bindings/lang_java.py | 777 | ||||
-rw-r--r-- | bindings/lang_java.pyc | bin | 0 -> 27747 bytes | |||
-rw-r--r-- | bindings/lang_java_wrapper_bottom.c | 0 | ||||
-rw-r--r-- | bindings/lang_java_wrapper_top.c | 522 | ||||
-rw-r--r-- | bindings/overrides.xml | 24 | ||||
-rw-r--r-- | bindings/utility-scripts/error-analyzer.pl | 147 | ||||
-rw-r--r-- | bindings/utils.py | 52 |
16 files changed, 2183 insertions, 10 deletions
diff --git a/bindings/Makefile.am b/bindings/Makefile.am index 698d43fe..6fbf0a36 100644 --- a/bindings/Makefile.am +++ b/bindings/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = python php5 +SUBDIRS = python php5 java EXTRA_DIST = bindings.py \ lang_python.py \ diff --git a/bindings/bindings.py b/bindings/bindings.py index 30b7c80e..fe427758 100644 --- a/bindings/bindings.py +++ b/bindings/bindings.py @@ -25,6 +25,7 @@ import os import re import sys +import utils from optparse import OptionParser import elementtree.ElementTree as ET @@ -70,7 +71,7 @@ class BindingData: for f in self.functions[:]: if len(f.args) == 0: continue - if f.name.endswith('_new'): + if f.name.endswith('_new') or '_new_' in f.name: # constructor for another class continue arg_type = f.args[0][0] @@ -85,7 +86,13 @@ class BindingData: f.docstring.parameters = f.docstring.parameters[1:] self.functions.remove(f) - def look_for_docstrings(self, srcdir): + def look_for_docstrings(self, srcdir, exception_doc): + def getfunc(name): + funcs = [f for f in self.functions if f.name == name] + if not funcs: + return None + else: + return funcs[0] regex = re.compile(r'\/\*\*\s(.*?)\*\*\/', re.DOTALL) for base, dirnames, filenames in os.walk(srcdir): if base.endswith('/.svn'): @@ -102,12 +109,17 @@ class BindingData: for d in docstrings: docstring = '\n'.join([x[3:] for x in d.splitlines()]) function_name = docstring.splitlines(1)[0].strip().strip(':') - func = [f for f in self.functions if f.name == function_name] + func = getfunc(function_name) if not func: continue - func = func[0] func.docstring = DocString(func, docstring) - + if exception_doc: + lines = os.popen('perl ../utility-scripts/error-analyzer.pl %s' % srcdir, 'r').readlines() + for line in lines: + elts = re.split(r' +',line.strip()) + func = getfunc(elts[0]) + if func: + func.errors = elts[1:] class Struct: @@ -136,6 +148,7 @@ class Function: docstring = None return_owner = True skip = False + errors = None def __repr__(self): return '%s %s %r' % (self.return_type, self.name, self.args) @@ -159,6 +172,8 @@ class Function: self.rename = func.attrib.get('rename') if func.attrib.get('return_owner'): self.return_owner = (func.attrib.get('return_owner') != 'false') + if func.attrib.get('return_type'): + self.return_type = func.attrib.get('return_type') if func.attrib.get('skip') == 'true': self.skip = True @@ -283,7 +298,9 @@ def parse_header(header_file): elif line.startswith('struct _'): m = re.match('struct ([a-zA-Z0-9_]+)', line) struct_name = m.group(1) + #print struct_name if struct_name in struct_names: + #print struct_name in_struct = Struct(struct_name) in_struct_private = False elif in_struct: @@ -352,7 +369,7 @@ def parse_header(header_file): def parse_headers(srcdir, enable_idwsf): wsf_prefixes = ['disco', 'dst', 'is', 'profile_service', 'discovery', 'wsf', 'interaction', 'utility', 'sa', 'soap', 'authentication', - 'wsse', 'sec', 'ds', 'idwsf2', 'wsf2', 'wsa', 'wsu'] + 'wsse', 'sec', 'idwsf2', 'wsf2', 'wsa', 'wsu'] for base, dirnames, filenames in os.walk(srcdir): if base.endswith('/.svn'): @@ -377,7 +394,6 @@ def parse_headers(srcdir, enable_idwsf): binding.headers.insert(0, 'lasso/xml/saml-2.0/saml2_assertion.h') binding.constants.append(('b', 'LASSO_WSF_ENABLED')) - def main(): global binding @@ -385,6 +401,7 @@ def main(): parser.add_option('-l', '--language', dest = 'language') parser.add_option('-s', '--src-dir', dest = 'srcdir', default = '../lasso/') parser.add_option('--enable-id-wsf', dest = 'idwsf', action = 'store_true') + parser.add_option('--enable-exception-docs', dest= 'exception_doc', action = 'store_true') options, args = parser.parse_args() if not options.language: @@ -393,7 +410,7 @@ def main(): binding = BindingData() parse_headers(options.srcdir, options.idwsf) - binding.look_for_docstrings(options.srcdir) + binding.look_for_docstrings(options.srcdir,options.exception_doc) binding.order_class_hierarchy() binding.attach_methods() @@ -408,6 +425,11 @@ def main(): php5_binding = lang_php5.Php5Binding(binding) php5_binding.generate() + elif options.language == 'java': + import lang_java + + java_binding = lang_java.JavaBinding(binding) + java_binding.generate(); if __name__ == '__main__': main() diff --git a/bindings/java/GObject.java b/bindings/java/GObject.java new file mode 100644 index 00000000..ccb59c22 --- /dev/null +++ b/bindings/java/GObject.java @@ -0,0 +1,9 @@ +package com.entrouvert.lasso; + +class GObject { + private long cptr; + + protected GObject(long ptr) { + cptr = ptr; + } +} diff --git a/bindings/java/LassoException_top.java b/bindings/java/LassoException_top.java new file mode 100644 index 00000000..19b4d8e0 --- /dev/null +++ b/bindings/java/LassoException_top.java @@ -0,0 +1,31 @@ +package com.entrouvert.lasso; + +public class LassoException extends RuntimeException { + public int errorCode; + private static boolean throws_for_recoverable_errors = false; + /** If set to true, enables throwing of exception for + * recoverable errors, i.e. errors with a positive error + * code. + * + * @param bool true if exception are throwed on recoverable errors. + */ + public static void setThrowsForRecoverableErrors(boolean bool) { + throws_for_recoverable_errors = bool; + } + public static boolean getThrowsForRecoverableErrors() { + return throws_for_recoverable_errors; + } + + protected LassoException(int errorCode) { + super(LassoJNI.strError(errorCode)); + errorCode = errorCode; + } + protected LassoException(int errorCode, String message) { + super(message); + errorCode = errorCode; + } + private static final Class[] paramst = { Integer.class }; + protected static int throwError(int errorCode) throws LassoException { + if (errorCode == 0 || (! throws_for_recoverable_errors && errorCode > 0)) + return errorCode; + diff --git a/bindings/java/Makefile.am b/bindings/java/Makefile.am new file mode 100644 index 00000000..d72d0c24 --- /dev/null +++ b/bindings/java/Makefile.am @@ -0,0 +1,40 @@ +if JAVA_ENABLED +INCLUDES = -I$(top_srcdir) \ + -I$(top_builddir) \ + $(SASL_CFLAGS) + +java_extension_LTLIBRARIES = libjnilasso.la +java_extensiondir = ${libdir} + +nodist_java_extension_DATA = + +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 + +BUILT_SOURCES = com_entrouvert_lasso_LassoJNI.c + +%.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: ../lang_java_wrapper_top.c ../lang_java.py + $(PYTHON) $(top_srcdir)/bindings/bindings.py -l java --src-dir=$(top_srcdir)/lasso/ + cp 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 + +publish: doc/index.html + 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 + +endif diff --git a/bindings/java/TODO b/bindings/java/TODO new file mode 100644 index 00000000..9e0c346f --- /dev/null +++ b/bindings/java/TODO @@ -0,0 +1,14 @@ +* generate_wrapper_getter_setter DONE +* generate_JNI_functions DONE +* generate_JNI_getter_setter DONE +* get_glist_from_jlist_of_strings DONE +* get_glist_from_jlist_of_xmlnodes DONE +* get_glist_from_jlist_of_objects DONE +* generate_class DOINE + +* Générer la liste des erreurs possibles par fonction + -> Construire callgraph de lasso DONE + -> 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 diff --git a/bindings/java/tests/BindingTests.java b/bindings/java/tests/BindingTests.java new file mode 100644 index 00000000..53a508df --- /dev/null +++ b/bindings/java/tests/BindingTests.java @@ -0,0 +1,282 @@ +/* + * $Id: BindingTests.java 3238 2007-05-30 17:24:50Z dlaniel $ + * + * Java unit tests for Lasso library + * + * Copyright (C) 2004-2007 Entr'ouvert + * http://LassoConstants.LASSO_entrouvert.org + * + * Authors: See AUTHORS file in top-level directory. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// To run it: +// $ export LD_LIBRARY_PATH=../ +// $ javac -classpath /usr/share/java/junit.jar:../LassoConstants.LASSO_jar:. BindingTests.java +// $ java -classpath /usr/share/java/junit.jar:../LassoConstants.LASSO_jar:. BindingTests +// or for gcj: +// $ export LD_LIBRARY_PATH=../ +// $ gcj -C -classpath /usr/share/java/junit.jar:../LassoConstants.LASSO_jar:. BindingTests.java +// $ gij -classpath /usr/share/java/junit.jar:../LassoConstants.LASSO_jar:. BindingTests + + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.entrouvert.lasso.*; +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()); + } + + public static Test suite() { + return new TestSuite(BindingTests.class); + } + + public void test01() { + // Create and delete nodes. + + LibAuthnRequest authnRequest = new LibAuthnRequest(); + authnRequest = null; + } + + public void test02() { + // Get & set simple attributes of nodes. + + LibAuthnRequest authnRequest = new LibAuthnRequest(); + + // Test a string attribute. + assertNull(authnRequest.getConsent()); + authnRequest.setConsent(LassoConstants.LASSO_LIB_CONSENT_OBTAINED); + assertEquals(authnRequest.getConsent(), LassoConstants.LASSO_LIB_CONSENT_OBTAINED); + authnRequest.setConsent(null); + assertNull(authnRequest.getConsent()); + + // Test a renamed string attribute. + assertNull(authnRequest.getRelayState()); + authnRequest.setRelayState("Hello World!"); + assertEquals(authnRequest.getRelayState(), "Hello World!"); + authnRequest.setRelayState(null); + assertNull(authnRequest.getRelayState()); + + // Test an integer attribute. + assertEquals(authnRequest.getMajorVersion(), 0); + authnRequest.setMajorVersion(314); + assertEquals(authnRequest.getMajorVersion(), 314); + + authnRequest = null; + } + + public void test03() { + // Get & set attributes of nodes of type string list. + + LibAuthnRequest authnRequest = new LibAuthnRequest(); + + assertNull(authnRequest.getRespondWith()); + + List respondWith = new ArrayList(); + assertEquals(respondWith.size(), 0); + respondWith.add("first string"); + assertEquals(respondWith.size(), 1); + assertEquals(respondWith.get(0), "first string"); + assertEquals(respondWith.get(0), "first string"); + respondWith.add("second string"); + assertEquals(respondWith.size(), 2); + assertEquals(respondWith.get(0), "first string"); + assertEquals(respondWith.get(1), "second string"); + respondWith.add("third string"); + assertEquals(respondWith.size(), 3); + 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"); + 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(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"); + authnRequest.setRespondWith(null); + System.out.println("coin"+authnRequest.getRespondWith()); + assertNull(authnRequest.getRespondWith()); + + authnRequest = null; + } + + public void test04() { + // Get & set attributes of nodes of type node list. + + SamlpResponse response = new SamlpResponse(); + + assertNull(response.getAssertion()); + + List assertions = new ArrayList(); + assertEquals(assertions.size(), 0); + SamlAssertion assertion1 = new SamlAssertion(); + assertion1.setAssertionId("assertion 1"); + assertions.add(assertion1); + assertEquals(assertions.size(), 1); + assertEquals(((SamlAssertion) assertions.get(0)).getAssertionId(), "assertion 1"); + assertEquals(((SamlAssertion) assertions.get(0)).getAssertionId(), "assertion 1"); + SamlAssertion assertion2 = new SamlAssertion(); + assertion2.setAssertionId("assertion 2"); + assertions.add(assertion2); + assertEquals(assertions.size(), 2); + assertEquals(((SamlAssertion) assertions.get(0)).getAssertionId(), "assertion 1"); + assertEquals(((SamlAssertion) assertions.get(1)).getAssertionId(), "assertion 2"); + SamlAssertion assertion3 = new SamlAssertion(); + assertion3.setAssertionId("assertion 3"); + assertions.add(assertion3); + assertEquals(assertions.size(), 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"); + 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"); + 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) 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"); + response.setAssertion(null); + assertNull(response.getAssertion()); + + response = null; + } + + public void test05() { + // Get & set attributes of nodes of type XML list. + + LibAuthnRequest authnRequest = new LibAuthnRequest(); + + 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>"; + List extension = new ArrayList(); + assertEquals(extension.size(), 0); + extension.add(actionString1); + assertEquals(extension.size(), 1); + assertEquals(extension.get(0), actionString1); + assertEquals(extension.get(0), actionString1); + extension.add(actionString2); + assertEquals(extension.size(), 2); + assertEquals(extension.get(0), actionString1); + assertEquals(extension.get(1), actionString2); + extension.add(actionString3); + assertEquals(extension.size(), 3); + 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); + 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(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); + authnRequest.setExtension(null); + assertNull(authnRequest.getExtension()); + + authnRequest = null; + } + + public void test06() { + // Get & set attributes of nodes of type node. + + Login login = new Login(new Server(null, null, null, null)); + + 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); + login.setRequest(null); + assertNull(login.getRequest()); + + login = null; + } +} diff --git a/bindings/java/tests/LoginTest.java b/bindings/java/tests/LoginTest.java new file mode 100644 index 00000000..755ffd7b --- /dev/null +++ b/bindings/java/tests/LoginTest.java @@ -0,0 +1,244 @@ +/* + * $Id: LoginTest.java 3307 2007-06-13 13:17:51Z dlaniel $ + * + * Java unit tests for Lasso library + * + * Copyright (C) 2004-2007 Entr'ouvert + * http://lasso.entrouvert.org + * + * Authors: See AUTHORS file in top-level directory. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// To run it: +// $ export LD_LIBRARY_PATH=../ +// $ javac -classpath /usr/share/java/junit.jar:../lasso.jar:. LoginTest.java +// $ java -classpath /usr/share/java/junit.jar:../lasso.jar:. LoginTest +// or for gcj: +// $ export LD_LIBRARY_PATH=../ +// $ gcj -C -classpath /usr/share/java/junit.jar:../lasso.jar:. LoginTest.java +// $ gij -classpath /usr/share/java/junit.jar:../lasso.jar:. LoginTest + + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +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", + null, + "../../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"); + 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", + null, + "../../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"); + String serverDump = server.dump(); + return serverDump; + } + + public void test01_generateServersDumps() { + String identityProviderDump = generateIdentityProviderDump(); + assertNotNull(identityProviderDump); + String serviceProviderDump = generateServiceProviderDump(); + assertNotNull(serviceProviderDump); + } + + public void test02_serviceProviderLogin() { + boolean userAuthenticated, userConsentObtained; + int method, requestType; + LibAuthnRequest authnRequest; + Identity idpIdentity, spIdentity; + Login idpLogin, spLogin; + Logout idpLogout, spLogout; + SamlAssertion assertion; + Server idp, sp; + Session spSession; + String artifact, authenticationMethod, authnRequestQuery, authnRequestUrl, idpDump, + idpIdentityDump, idpRemoteProviderId, idpSessionDump, nameIdentifier, relayState, + responseQuery, responseUrl, soapEndpoint, soapResponseMsg, soapRequestMsg, + spDump, spIdentityDump, spSessionDump; + + // Service provider login using HTTP redirect. + spDump = generateServiceProviderDump(); + assertNotNull(spDump); + sp = Server.newFromDump(spDump); + spLogin = new Login(sp); + spLogin.initAuthnRequest("https://idp1/metadata", 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); + relayState = "fake"; + authnRequest.setRelayState(relayState); + spLogin.buildAuthnRequestMsg(); + authnRequestUrl = spLogin.getMsgUrl(); + authnRequestQuery = authnRequestUrl.substring(authnRequestUrl.indexOf("?") + 1); + + // Identity provider singleSignOn, for a user having no federation. + idpDump = generateIdentityProviderDump(); + assertNotNull(idpDump); + idp = Server.newFromDump(idpDump); + idpLogin = new Login(idp); + idpLogin.processAuthnRequestMsg(authnRequestQuery); + assertTrue(idpLogin.mustAuthenticate()); + assertFalse(idpLogin.mustAskForConsent()); + + userAuthenticated = true; + userConsentObtained = false; + idpLogin.validateRequestMsg(userAuthenticated, userConsentObtained); + authenticationMethod = 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); + idpIdentityDump = idpLogin.getIdentity().dump(); + assertNotNull(idpIdentityDump); + idpSessionDump = idpLogin.getSession().dump(); + assertNotNull(idpSessionDump); + responseUrl = idpLogin.getMsgUrl(); + responseQuery = responseUrl.substring(responseUrl.indexOf("?") + 1); + idpRemoteProviderId = idpLogin.getRemoteProviderId(); + nameIdentifier = ((SamlNameIdentifier)idpLogin.getNameIdentifier()).getContent(); + artifact = idpLogin.getAssertionArtifact(); + assertNotNull(artifact); + method = lasso.HTTP_METHOD_REDIRECT; + + // Service provider assertion consumer. + spDump = generateServiceProviderDump(); + assertNotNull(spDump); + sp = Server.newFromDump(spDump); + spLogin = new Login(sp); + spLogin.initRequest(responseQuery, method); + spLogin.buildRequestMsg(); + soapEndpoint = spLogin.getMsgUrl(); + assertNotNull(soapEndpoint); + soapRequestMsg = spLogin.getMsgBody(); + assertNotNull(soapRequestMsg); + + // Identity provider SOAP endpoint. + requestType = lasso.getRequestTypeFromSoapMsg(soapRequestMsg); + assertEquals(lasso.REQUEST_TYPE_LOGIN, requestType); + idpDump = generateIdentityProviderDump(); + assertNotNull(idpDump); + idp = Server.newFromDump(idpDump); + idpLogin = new Login(idp); + idpLogin.processRequestMsg(soapRequestMsg); + assertEquals(artifact, idpLogin.getAssertionArtifact()); + assertNotNull(idpSessionDump); + idpLogin.setSessionFromDump(idpSessionDump); + idpLogin.buildResponseMsg(idpRemoteProviderId); + soapResponseMsg = idpLogin.getMsgBody(); + assertNotNull(soapResponseMsg); + + // Service provider assertion consumer (step 2: process SOAP response). + spLogin.processResponseMsg(soapResponseMsg); + assertEquals(nameIdentifier, ((SamlNameIdentifier)spLogin.getNameIdentifier()).getContent()); + // The user doesn't have any federation yet. + spLogin.acceptSso(); + spIdentity = spLogin.getIdentity(); + assertNotNull(spIdentity); + spIdentityDump = spIdentity.dump(); + assertNotNull(spIdentityDump); + spSession = spLogin.getSession(); + assertNotNull(spSession); + spSessionDump = spSession.dump(); + assertNotNull(spSessionDump); + assertion = (SamlAssertion) spSession.getAssertions("https://idp1/metadata").getItem(0); + authenticationMethod = assertion.getAuthenticationStatement().getAuthenticationMethod(); + assertEquals(lasso.SAML_AUTHENTICATION_METHOD_PASSWORD, authenticationMethod); + + // Service provider logout. + spDump = generateServiceProviderDump(); + assertNotNull(spDump); + sp = Server.newFromDump(spDump); + assertNotNull(sp); + spLogout = new Logout(sp); + assertNotNull(spIdentityDump); + spLogout.setIdentityFromDump(spIdentityDump); + assertNotNull(spSessionDump); + spLogout.setSessionFromDump(spSessionDump); + spLogout.initRequest(null, 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); + idpDump = generateIdentityProviderDump(); + assertNotNull(idpDump); + idp = Server.newFromDump(idpDump); + assertNotNull(idp); + idpLogout = new Logout(idp); + idpLogout.processRequestMsg(soapRequestMsg); + assertEquals(nameIdentifier, ((SamlNameIdentifier)idpLogout.getNameIdentifier()).getContent()); + assertNotNull(idpIdentityDump); + idpLogout.setIdentityFromDump(idpIdentityDump); + assertNotNull(idpSessionDump); + idpLogout.setSessionFromDump(idpSessionDump); + idpLogout.validateRequest(); + idpIdentity = idpLogout.getIdentity(); + assertNotNull(idpIdentity); + idpIdentityDump = idpIdentity.dump(); + assertNotNull(idpIdentityDump); + // There is no other service provider from which the user must be logged out. + assertEquals(null, idpLogout.getNextProviderId()); + idpLogout.buildResponseMsg(); + soapResponseMsg = idpLogout.getMsgBody(); + + // Service provider logout (step 2: process SOAP response). + spLogout.processResponseMsg(soapResponseMsg); + spIdentityDump = spLogout.getIdentity().dump(); + assertNotNull(spIdentityDump); + } + + public static Test suite() { + return new TestSuite(LoginTest.class); + } + + public static void main(String args[]) { + System.out.println(System.mapLibraryName("jlasso")); + lasso.init(); + junit.textui.TestRunner.run(suite()); + lasso.shutdown(); + } +} + diff --git a/bindings/java/tests/Test.java b/bindings/java/tests/Test.java new file mode 100644 index 00000000..4e1450df --- /dev/null +++ b/bindings/java/tests/Test.java @@ -0,0 +1,11 @@ +import com.entrouvert.lasso.*; + +class Test { + + public static void main(String args[]) { + Samlp2AuthnRequest p; + + p = new Samlp2AuthnRequest(); + System.out.println(p.dump()); + } +} diff --git a/bindings/lang_java.py b/bindings/lang_java.py new file mode 100644 index 00000000..dbcec09f --- /dev/null +++ b/bindings/lang_java.py @@ -0,0 +1,777 @@ +# Lasso - A free implementation of the Liberty Alliance specifications. +# +# Copyright (C) 2004-2007 Entr'ouvert +# http://lasso.entrouvert.org +# +# Authors: See AUTHORS file in top-level directory. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import os +import sys +import re +import textwrap + +import utils + +lasso_package_name = 'com.entrouvert.lasso' +lasso_java_path = 'com/entrouvert/lasso/' + + +def generate_arg_list(self,args): + def arg_to_decl(arg): + type, name, option = arg + return self.JNI_arg_type(type) + ' ' + utils.format_as_camelcase(name) + return ', '.join([ arg_to_decl(x) for x in args ]) + +def generate_arg_list2(args): + def arg_to_decl(arg): + type, name, option = arg + return utils.format_as_camelcase(name) + return ', '.join([ arg_to_decl(x) for x in args ]) + +def convert_class_name(lasso_name): + return lasso_name[5:] + +def mangle_name(name): + s = name + s = s.replace('_', '_1') + s = s.replace(';', '_2') + s = s.replace('[', '_3') + return s + +def jni_elem_type(type): + if type in ('char*', 'gchar*', 'const char*', 'const gchar*'): + return 'jstring' + elif type == 'xmlNode*': + return 'jstring' + else: + return 'jobject' + +def JNI_elem_type(type): + if type in ('char*', 'gchar*', 'const char*', 'const gchar*'): + return 'String' + elif type == 'xmlNode*': + return 'String' + elif type != None and type.startswith('Lasso'): + return type[5:] + else: + return 'Object' + +def wrapper_name(name): + return 'Java_com_entrouvert_lasso_LassoJNI_' + mangle_name(name) + +def error_to_exception(error_name): + if 'LASSO_ERROR' in error_name: + name, = re.match('LASSO_ERROR(_.*)', error_name).groups() + super = 'Lasso' + else: + super, name = re.match('LASSO(_.*)_ERROR(_.*)', error_name).groups() + super = utils.format_as_camelcase(super.lower()) + name = utils.format_as_camelcase(name.lower()) + return (super+name+'Exception',super+'Exception') + +def wrapper_decl(name, jnitype, fd): + jniname = wrapper_name(name) + print >> fd, 'JNIEXPORT %s JNICALL %s(JNIEnv *env, jclass clss' % \ + (jnitype,jniname), + +class JavaBinding: + def __init__(self, binding_data): + self.binding_data = binding_data + + def is_pygobject(self, t): + return t not in ['char*', 'const char*', 'gchar*', 'const gchar*', + 'GList*', 'GHashTable*', + 'int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums + + def generate(self): + self.generate_Constants() + self.generate_JNI() + self.generate_wrapper() + self.generate_exception_classes() + self.generate_lasso_classes() + + +# LassoConstants + def generate_Constants(self): + fd = open(lasso_java_path + 'LassoConstants.java', 'w') + self.generate_Constants_header(fd) + self.generate_Constants_constants(fd) + self.generate_Constants_footer(fd) + fd.close() + + def generate_Constants_header(self, fd): + print >> fd, '''\ +/* this file has been generated automatically; do not edit */ + +package %s; + +public abstract interface LassoConstants { +''' % lasso_package_name + + def generate_Constants_constants(self, fd): + print >> fd, '/* Constants (both enums and defines) */' + # Declaration + for c in self.binding_data.constants: + print >> fd, 'static final ', + if c[0] == 'i': + print >> fd, 'int ', + elif c[0] == 's': + print >> fd, 'String ', + elif c[0] == 'b': + print >> fd, 'boolean ', + print >> fd, '%s = LassoJNI.%s_get();' % (c[1], c[1]) + + def generate_Constants_footer(self, fd): + print >> fd, '}' + + +# LassoJNI + def generate_JNI(self): + fd = open(lasso_java_path + 'LassoJNI.java','w') + self.generate_JNI_header(fd) + self.generate_JNI_constants(fd) + for m in self.binding_data.functions: + self.generate_JNI_functions(m ,fd) + for c in self.binding_data.structs: + self.generate_JNI_member(c, fd) + for m in c.methods: + self.generate_JNI_functions(m, fd) + self.generate_JNI_footer(fd) + fd.close(); + + def generate_JNI_header(self, fd): + print >> fd, '''\ +/* this file has been generated automatically; do not edit */ + +package %s; + +public final class LassoJNI { +public static native void init2(); +''' % lasso_package_name + def generate_JNI_constants(self, fd): + print >>fd, '/* Constants getters */' + for c in self.binding_data.constants: + print >>fd, 'public static native ', + if c[0] == 'i': + print >>fd, 'int ', + elif c[0] == 's': + print >>fd, 'String ', + elif c[0] == 'b': + print >>fd, 'boolean ', + print >>fd, '%s_get();' % c[1] + + def JNI_arg_type(self, vtype): + if vtype == 'gboolean': + return 'boolean' + elif vtype in ['int','gint'] + self.binding_data.enums: + return 'int' + elif vtype in ('char*', 'gchar*', 'const char*', 'const gchar*'): + return 'String' + elif vtype in ('GList*','GHashTable*'): + return 'Object[]' + elif vtype == 'xmlNode*': + return 'String' + elif isinstance(vtype,basestring) and vtype.startswith('Lasso'): + if vtype.endswith('*'): + vtype = vtype[:-1] + return convert_class_name(vtype) + else: + return 'GObject' + + def JNI_return_type(self, vtype): + if vtype == 'gboolean': + return 'boolean' + elif vtype in ['int','gint'] + self.binding_data.enums: + return 'int' + elif vtype in ('char*', 'gchar*', 'const char*', 'const gchar*'): + return 'String' + elif vtype in ('GList*','GHashTable*'): + return 'Object[]' + elif vtype == 'xmlNode*': + return 'String' + elif isinstance(vtype,basestring) and vtype.startswith('Lasso'): + if vtype.endswith('*'): + vtype = vtype[:-1] + return convert_class_name(vtype) + else: + return 'void' + + def JNI_member_type(self,member): + type, name, options = member + if type in ('GList*','GHashTable*'): + return self.JNI_arg_type(options.get('elem_type')) + else: + return self.JNI_arg_type(type) + + def JNI_function_name(self, m): + if m.rename: + return m.rename + else: + return m.name[6:] + + def generate_JNI_functions(self, m, fd): + if m.name.endswith('_new'): + jtype = 'long' + else: + jtype = self.JNI_return_type(m.return_type) + name = self.JNI_function_name(m) + print >> fd, ' public static native %s %s(%s);' % (jtype,name, generate_arg_list(self,m.args)) + + def JNI_member_function_prefix(self,c,m): + klassname = c.name[5:] + mname = utils.format_as_camelcase(m[1]) + return '%s_%s' % (klassname,mname) + + def generate_JNI_member(self, c, fd): + for m in c.members: + prefix = self.JNI_member_function_prefix(c,m) + mname = utils.format_as_camelcase(m[1]) + mtype = m[0] + + jtype = self.JNI_member_type(m) + if mtype == 'GList*': + name = '%s_get' % prefix + print >> fd, ' public static native %s[] %s(GObject obj);' % (jtype,name) + name = '%s_set' % prefix + 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) + elif mtype == 'GHashTable*': + name = '%s_get' % prefix + print >> fd, ' public static native %s[] %s(GObject obj);' % (jtype,name) + name = '%s_set' % prefix + 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) + else: + name = '%s_get' % prefix + print >> fd, ' public static native %s %s(GObject obj);' % (jtype,name) + name = '%s_set' % prefix + print >> fd, ' public static native void %s(GObject obj, %s value);' % (name,jtype) + + def generate_JNI_footer(self, fd): + print >>fd, ''' + static { + System.loadLibrary("jnilasso"); + init(); + init2(); + } +''' + print >>fd, '}' + + +# Wrappers + def generate_wrapper(self): + fd = open('com_entrouvert_lasso_LassoJNI.c', 'w') + self.generate_wrapper_header(fd) + self.generate_wrapper_constants(fd) + + print >> fd, '/* Declaration of standalone functions */' + for m in self.binding_data.functions: + self.generate_wrapper_function(m, fd) + print >> fd, '/* End of declaration of standalone functions */' + print >> fd, '/* Declaration of getter/setter methods */' + for c in self.binding_data.structs: + self.generate_wrapper_getter_setter(c, fd) + print >> fd, '/* End of declaration of getter/setter methods */' + for c in self.binding_data.structs: + for m in c.methods: + self.generate_wrapper_function(m, fd) + print >> fd, open(os.path.join(self.binding_data.src_dir, + 'lang_java_wrapper_bottom.c')).read() + fd.close() + + def generate_wrapper_header(self, fd): + print >> fd, open(os.path.join(self.binding_data.src_dir, + 'lang_java_wrapper_top.c')).read() + print >> fd, '' + for h in self.binding_data.headers: + print >> fd, '#include <%s>' % h + + + def generate_wrapper_constants(self, fd): + print >> fd, '/* Declaration of constants */' + for c in self.binding_data.constants: + s = c[1]+'_get' + if c[0] == 'i': + wrapper_decl(s,'jint',fd) + print >>fd, ') {' + print >>fd, ' return %s;' % c[1] + print >>fd, '}' + elif c[0] == 's': + wrapper_decl(s,'jstring',fd) + print >>fd, ') {' + print >>fd, ' return (*env)->NewStringUTF(env, %s);' % c[1] + print >>fd, '}' + elif c[0] == 'b': + wrapper_decl(s,'jboolean',fd) + print >>fd, ') {' + print >>fd, '#ifdef %s' % c[1] + print >>fd, ' return 1;' + print >>fd, '#else' + print >>fd, ' return 0;' + print >>fd, '#endif' + print >>fd, '}' + print >> fd, '/* End of declaration of constants */' + + def jni_return_type(self, vtype): + if vtype == 'gboolean': + return 'jboolean' + elif vtype in ['int','gint'] + self.binding_data.enums: + return 'jint' + elif vtype in ('char*', 'gchar*', 'const char*', 'const gchar*'): + return 'jstring' + elif vtype in ('GList*','GHashTable*'): + return 'jobjectArray' + elif vtype == 'xmlNode*': + return 'jstring' + elif not vtype: + 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*',): + elem_type = options.get('elem_type') + if elem_type == 'char*': + return 'get_list_of_strings(env, %s)' % name + elif elem_type == 'xmlNode*': + return 'get_list_of_xml_nodes(env, %s)' % name + else: + return 'get_list_of_objects(env, %s)' % name + elif vtype in ('GHashTable*',): + elem_type = options.get('elem_type') + if elem_type == 'char*': + return 'get_hash_of_strings(env, %s)' % name + else: + return 'get_hash_of_objects(env, %s)' % name + elif vtype == 'xmlNode*': + return 'xml_node_to_jstring(env, %s)' % name + else: + if 'return_owner' in options: + return 'gobject_to_jobject(env, (GObject*)%s);' % name + 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*',): + elem_type = options.get('elem_type') + if elem_type == 'char*': + return 'set_list_of_strings(env, &%s,%s);' % (left,right) + elif elem_type == 'xmlNode*': + 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*',): + 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) + 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) + + def generate_wrapper_function(self, m, fd): + print >> fd, '/* Wrapper function for ', + if m.return_type: + print >> fd, m.return_type, + else: + print >> fd, 'void', + print >> fd, '%s(' % m.name, + for arg in m.args: + print >> fd, '%s %s %s,' % (arg[0],arg[1],arg[2]), + print >> fd, ') */' + if m.rename: + name = m.rename + else: + name = m.name[6:] +# self.wrapper_list.append(name) +# print >> fd, '''static PyObject* +#%s(PyObject *self, PyObject *args) +#{''' % name + if m.name.endswith('_new'): + jtype = 'jlong' + else: + jtype = self.jni_return_type(m.return_type) + wrapper_decl(name, jtype, fd) + parse_tuple_format = [] + parse_tuple_args = [] + idx = 0 + # Declare java args + for arg in m.args: + idx = idx + 1 + arg_type, arg_name, arg_options = arg + print >> fd, ',%s jarg%s' % (self.jni_return_type(arg_type.replace('const ','')),idx), + print >> fd, ')' + print >> fd, ' {' + idx = 0 + if m.return_type: + 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) + # Declare return vars + if m.return_type: + print >> fd, ' %s return_value;' % m.return_type + idx = 0 + # Convert args + 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) + # 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) + + # Return + if m.return_type: + if m.name.endswith('_new'): + print >> fd, ' return (jlong) return_value;' + else: + 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);' + print >> fd, ' }' + + def generate_wrapper_getter_setter(self, c, fd): + klassname = c.name + for m in c.members: + mtype = m[0] + prefix = self.JNI_member_function_prefix(c,m) + # getter + jtype = self.jni_return_type(mtype) + 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, ' if (gobj) {' + print >> fd, ' return %s;' % self.c_to_java_value ('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, '}' + 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' % self.java_to_c_value('gobj->%s' % m[1], 'value', mtype, m[2]) + print >> fd, '}' + # add/remove + if mtype in ('GList*', ): + # add + print >> fd,'/* Adder for %s %s.%s */' % (mtype,klassname,m[1]) + 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, ' 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] + else: + 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, '}' + # add/remove/get_by_name + if mtype in ('GHashTable*',): + # add + print >> fd,'/* Adder for %s %s.%s */' % (mtype,klassname,m[1]) + 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) + 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, '}' + +# + def generate_exception_switch_case(self, fd, name, orig): + print >> fd, ' if (errorCode == LassoConstants.%s) {' % orig + print >> fd, ' throw new %s(errorCode);' % name + print >> fd, ' }' + + def generate_exception_classes(self): + efd = open(lasso_java_path + 'LassoException.java', 'w') + print >> efd, open(os.path.join(self.binding_data.src_dir, + 'java/LassoException_top.java')).read() + # Generate the function to get class name by error code + supers = [] + 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) + self.generate_exception_switch_case(efd, name, orig) + if super not in supers: + supers.append(super) + self.generate_exception_class(name,super,0,orig) + for s in supers: + self.generate_exception_class(s,'LassoException',1,'') + # Special errors, UNIMPLEMENTED and UNDEFINED + for c in self.binding_data.constants: + type, orig = c + if 'LASSO_ERROR_' not in orig: + continue + name, = re.match('LASSO_ERROR(.*)',orig).groups() + name = name.lower() + name = utils.format_underscore_as_camelcase(name) + name = 'Lasso%sException' % name + self.generate_exception_class(name, 'LassoException', 0, orig) + self.generate_exception_switch_case(efd, name, orig) + print >> efd, ' throw new LassoException(errorCode, "Uknown lasso error code, maybe a bug in the binding, report it!");' + print >> efd, ' }' + print >> efd, '}' + efd.close() + + + def generate_exception_class(self, name, super,abstract,orig): + fd = open(lasso_java_path + '%s.java' % name, 'w') + print >> fd, 'package %s;' % lasso_package_name + print >> fd, '' + if abstract: + print >> fd, 'abstract ', + print >> fd, 'public class %s extends %s {' % (name,super) + if not abstract: + print >> fd, ' public %s() {' % name + print >> fd, ' super(LassoConstants.%s);' % orig + print >> fd, ' }' + print >> fd, ' protected %s(int errorCode) {' % name + print >> fd, ' super(errorCode);' + print >> fd, ' }' + print >> fd, '}' + fd.close() + + # Generate classes for Lasso Objects + def generate_lasso_classes(self): + def method_name(m,class_name): + prefix = len(class_name) + if m.rename: + return m.rename + else: + name = utils.format_as_camelcase(m.name[6:]) + name = name[prefix:] + return name[0].lower() + name[1:] + for c in self.binding_data.structs: + class_name = convert_class_name(c.name) + parent_name = c.parent + if parent_name != 'GObject': + parent_name = convert_class_name(parent_name) + path = lasso_java_path + '%s.java' % class_name + fd = open(path,'w') + print >> fd, 'package %s;' % lasso_package_name + print >> fd, '' + #print 'class %s extends %s {' % (class_name,parent_name) + print >> fd, 'public class %s extends %s {' % (class_name,parent_name) + # Constructeur private + print >> fd, ' /* Constructors */' + print >> fd, ' protected %s(long cptr) {' % class_name + print >> fd, ' super(cptr);' + print >> fd, ' }' + # Constructeur de base + def cprefix(name): + i = name.find('_new') + if i == -1: + return name + else: + return name[:i].replace('_','').lower() + cons = [ x for x in self.binding_data.functions if cprefix(x.name) == c.name.lower() and x.name.endswith('_new') ] + #print 'cons ', cons + for m in cons: + print >> fd, ' public %s(%s) {' % (class_name, generate_arg_list(self,m.args)) + print >> fd, ' super(LassoJNI.%s(%s));' % (self.JNI_function_name(m),generate_arg_list2(m.args)) + print >> fd, ' }' + # Constructeurs speciaux + cons = [ x for x in self.binding_data.functions if cprefix(x.name) == c.name.lower() and not x.name.endswith('_new') ] + #print 'cons ', cons + for m in cons: + name = method_name(m,class_name) + print >> fd, ' static public %s %s(%s) {' % (class_name, name, generate_arg_list(self,m.args)) + print >> fd, ' return LassoJNI.%s(%s);' % (self.JNI_function_name(m),generate_arg_list2(m.args)) + print >> fd, ' }' + print >> fd, ' /* Setters and getters */' + for m in c.members: + type, name, options = m + prefix = self.JNI_member_function_prefix(c,m) + 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, ' }' + print >> fd, ' public %s[] get%s() {' % (jtype,jname) + print >> fd, ' return LassoJNI.%s_get(this);' % prefix + 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, ' }' + elif type == 'GHashTable*': + print >> fd, ' public void set%s(%s[] value) {' % (jname,jtype) + print >> fd, ' LassoJNI.%s_set(this, value);' % prefix + print >> fd, ' }' + print >> fd, ' public %s[] get%s() {' % (jtype,jname) + print >> fd, ' return 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 ' void set%s(%s[] value)' % (jname,jtype) + #print ' %s[] get%s()' % (jtype,jname) + #print ' void addTo%s(String key, %s value)' % (jname,jtype) + #print ' void removeFrom%s(String key)' % (jname,jtype) + #print ' %s get%sByName(String key)' % (jtype,jname) + else: + print >> fd, ' public void set%s(%s value) {' % (jname,jtype) + print >> fd, ' LassoJNI.%s_set(this, value);' % prefix + print >> fd, ' }' + print >> fd, ' public %s get%s() {' % (jtype,jname) + print >> fd, ' return LassoJNI.%s_get(this);' % prefix + print >> fd, ' }' + #print ' void set%s(%s value)' % (jname,jtype) + #print ' %s get%s()' % (jtype,jname) + print >> fd, ' /* Methods */' + for m in c.methods: + return_type = self.JNI_return_type(m.return_type) + jni_name = self.JNI_function_name(m) + mname = method_name(m,class_name) + args = m.args + doc = m.docstring + def normalize(str,first=' * '): + wrapper = textwrap.TextWrapper() + 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'[^.]*must *be *freed *by[^.]*\.?', '', str) + str = re.sub(r'[^.]*internally[^.]*\.?[^.]*freed[^.]*\.?', '', str) + + str = re.sub(r'[^.]*\bfreed?\b[^.]*\.?', '', str) + str = re.sub(r'(a +)?#?GList\*?','an array', str) + return wrapper.fill(re.sub(r'@\b(\w+)\b',r'\1',str)) + if doc: + print >> fd, normalize(doc.description, ' /** ') + print >> fd, ' *' + for name, desc in doc.parameters[1:]: + print >> fd, normalize(desc, ' * @param %s ' % utils.format_as_camelcase(name)) + if doc.return_value: + print >> fd, normalize(doc.return_value, ' * @return ') + if m.errors: + for err in m.errors: + 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, ');' + else: + print >> fd, ';' + print >> fd, ' }' + print >> fd, '}' + fd.close() diff --git a/bindings/lang_java.pyc b/bindings/lang_java.pyc Binary files differnew file mode 100644 index 00000000..4815f8f1 --- /dev/null +++ b/bindings/lang_java.pyc diff --git a/bindings/lang_java_wrapper_bottom.c b/bindings/lang_java_wrapper_bottom.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/bindings/lang_java_wrapper_bottom.c diff --git a/bindings/lang_java_wrapper_top.c b/bindings/lang_java_wrapper_top.c new file mode 100644 index 00000000..123bb996 --- /dev/null +++ b/bindings/lang_java_wrapper_top.c @@ -0,0 +1,522 @@ +#include <lasso/lasso.h> +#include <lasso_config.h> +#include <jni.h> +#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 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 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); +#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) + + + +/* utility functions */ +static jlong +get_jlong_field(JNIEnv *env, jobject *obj, char *field) +{ + jclass cls; + jfieldID fid; + + cls = (*env)->GetObjectClass(env, obj); + if (cls == NULL) + return 0; + fid = (*env)->GetFieldID(env, cls, field, "J"); + if (fid == NULL) + return 0; + return (*env)->GetLongField(env, obj, fid); +} + +static jclass +get_jclass_by_name(JNIEnv *env, char *name) { + return (*env)->FindClass(env,name); +} + +/* string handling impl */ +static jstring +string_to_jstring(JNIEnv *env, const char* str) +{ + if (str) + return (*env)->NewStringUTF(env, str); + else + return NULL; +} + +static jstring +string_to_jstring_and_free(JNIEnv *env, char* str) +{ + if (str) { + jstring ret = (*env)->NewStringUTF(env, str); + g_free(str); + return ret; + } else { + return NULL; + } +} + +static const char * +jstring_to_string(JNIEnv *env, jstring str) +{ + 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; +} + +static void +release_utf_string(JNIEnv *env, jstring str, const char *utf_str) { + if (utf_str && str) + (*env)->ReleaseStringUTFChars(env, str, utf_str); +} + + +/* xmlNode handling */ +static jstring +xml_node_to_jstring(JNIEnv *env, xmlNode *xmlnode) +{ + xmlOutputBufferPtr buf; + + if (! xmlnode || ! env) { + return NULL; + } + + buf = xmlAllocOutputBuffer(NULL); + if (buf) { + jstring ret = NULL; + xmlNodeDumpOutput(buf, NULL, xmlnode, 0, 1, NULL); + xmlOutputBufferFlush(buf); + if (buf->conv == NULL) { + ret = string_to_jstring(env, (char*)buf->buffer->content); + } else { + ret = string_to_jstring(env, (char*)buf->conv->content); + } + xmlOutputBufferClose(buf); + return ret; + } else { + return NULL; + } +} + +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); + } + xmlFreeDoc(doc); + release_utf_string(env, string, str); + + return node; +} + +/* lasso objects handling impl */ +static jobject +gobject_to_jobject_aux(JNIEnv *env, GObject *obj, gboolean doRef) { + jobject *self; +#define LASSO_ROOT "com/entrouvert/lasso/" + if (obj == NULL) { + return NULL; + } + + self = (jobject)g_object_get_qdata(obj, lasso_wrapper_key); + if (self == NULL) { + jclass nodeCls; + jmethodID cid; + 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; + } + g_object_set_qdata_full(obj, lasso_wrapper_key, self, NULL); + if (doRef) { + g_object_ref(obj); + } + } + return self; +} +/** 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); +} +/** 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); +} + +/** 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 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); + } + + return ret; +} +/* List handling */ +static void +free_glist(GList **list, GFunc free_function) { + if (!list) + return; + if (*list) { + if (free_function) { + g_list_foreach(*list, free_function, NULL); + } + g_list_free(*list); + } + if (list) + *list = NULL; +} + +static jobjectArray +get_list(JNIEnv *env, char *clsName, GList *list, Converter convert) { + jsize l = g_list_length(list),i; + jobjectArray jarr; + jclass cls; + + if (!env || !list || !clsName || !convert) { + return NULL; + } + 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; + } + + 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; + } + list = g_list_next(list); + } + return jarr; +} + +static void +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; + } + *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; + GList *found; + + c = convert(env, obj); + if ((*env)->ExceptionOccurred(env)) { + return; + } + found = g_list_find_custom(*list, c, compare); + if (found) { + free_function(found->data, NULL); + *list = g_list_delete_link(*list, found); + } +} +static void +add_to_list(JNIEnv* env,GList** list,jobject obj, OutConverter convert) { + void *data; + + data = convert(env, obj); + if ((*env)->ExceptionOccurred(env)) { + return; + } + *list = g_list_append(*list, data); +} + +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; + } +} + +/* 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) +{ + jsize l; + jobjectArray jarr; + jclass cls; + struct Aux udata = {env, convert, FALSE, 0, NULL }; + + if (!env || !hashtable || !clsName || !convert) { + return NULL; + } + l = g_hash_table_size(hashtable); + cls = get_jclass_by_name(env, clsName); + if (!cls) { + return NULL; + } + + udata.jarr = (*env)->NewObjectArray(env, l, get_jclass_by_name(env, clsName), NULL); + if (! jarr) { + return NULL; + } + g_hash_table_foreach (hashtable, (GHFunc)get_hash_aux, &udata); + if (udata.crashed) + return NULL; + return udata.jarr; +} +static void set_hash(JNIEnv *env, GHashTable *hashtable, jobjectArray arr, OutConverter convert) { + jsize l,i; + + if (! env || ! hashtable || ! arr || ! convert) + return; + + 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; + } + skey = jstring_to_string(env, (jstring)key); + if ((*env)->ExceptionOccurred(env)) { + return; + } + g_hash_table_insert(hashtable, g_strdup(skey), value); + release_utf_string(env, key, skey); + } +} + +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); +} +static void add_to_hash(JNIEnv *env, GHashTable *hashtable, jstring key, jobject obj, OutConverter convert) +{ + 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); +} +static jobject +get_hash_by_name(JNIEnv *env, GHashTable *hashtable, jstring key, Converter convert) +{ + void *data; + const char *str; + + 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); +} + +/* 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"); +} diff --git a/bindings/overrides.xml b/bindings/overrides.xml index 1375fa3c..418ee2e9 100644 --- a/bindings/overrides.xml +++ b/bindings/overrides.xml @@ -8,9 +8,10 @@ <func name="lasso_profile_is_saml_query" rename="isSamlQuery"/> <func name="lasso_profile_get_request_type_from_soap_msg" rename="getRequestTypeFromSoapMsg"/> + <func name="lasso_session_get_assertions" return_owner="true"/> <!-- LassoProfile --> <func name="lasso_profile_get_nameIdentifier" - rename="lasso_profile_get_federation_nameIdentifier" + rename="getFederationNameIdentifier" return_owner="false" /> <func name="lasso_profile_get_identity" return_owner="false" /> <func name="lasso_profile_get_session" return_owner="false" /> @@ -57,6 +58,27 @@ <func name="lasso_name_identifier_mapping_init_request"> <param name="remote_providerID" optional="true" /> </func> + <!-- Fonctions utilisant des types venant de la partie id-wsf de la librarie --> + <func name="lasso_server_get_service" skip="true"> + </func> + <func name="lasso_login_set_encryptedResourceId" skip="true"> + </func> + <func name="lasso_node_new_from_dump" skip="true"/> + <func name="lasso_node_new_from_soap" skip="true"/> + <func name="lasso_node_new_from_xmlNode" skip="true"/> + <func name="lasso_provider_new_from_dump" skip="true"/> + <func name="lasso_saml2_name_id_new_with_string" return_type="LassoSaml2NameID*"/> + <func name="lasso_saml2_action_new_with_string" return_type="LassoSaml2Action*"/> + <func name="lasso_misc_text_node_new_with_string" return_type="LassoMiscTextNode*"/> + + <func name="lasso_lib_name_identifier_mapping_response_new_full" return_type="LassoLibNameIdentifierMappingResponse*"/> + <func name="lasso_lib_logout_request_new_full" return_type="LassoLibLogoutRequest*"/> + <func name="lasso_lib_logout_response_new_full" return_type="LassoLibLogoutResponse*"/> + <func name="lasso_lib_register_name_identifier_response_new_full" return_type="LassoLibRegisterNameIdentifierResponse*"/> + <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*"/> + <!-- Exceptions --> <exception> <category name="Profile"/> diff --git a/bindings/utility-scripts/error-analyzer.pl b/bindings/utility-scripts/error-analyzer.pl new file mode 100644 index 00000000..60b91c1f --- /dev/null +++ b/bindings/utility-scripts/error-analyzer.pl @@ -0,0 +1,147 @@ +#! /usr/bin/perl -w + eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' + if 0; #$running_under_some_shell + +use strict; +use File::Find (); +use Data::Dumper; + +# Set the variable $File::Find::dont_use_nlink if you're using AFS, +# since AFS cheats. + +# for the convenience of &wanted calls, including -eval statements: +use vars qw/*name *dir *prune/; +*name = *File::Find::name; +*dir = *File::Find::dir; +*prune = *File::Find::prune; + +sub wanted; + +sub unique { + my @in = @_; + my @ret = (); + + for my $x (@in) { + push @ret, $x if (! grep /$x/, @ret); + } + return @ret; +} + +my $functions = {}; + +my $p = $ARGV[0]; + +# Traverse desired filesystems +-d $p && File::Find::find({wanted => \&wanted}, $p); + +foreach my $function (keys %$functions) { + potential_errors($function); +} + +foreach my $name (sort (keys %$functions)) { + my $record = $functions->{$name}; + next if $record->{'return-type'} !~ /\bg?int\b/ || $record->{'return-type'} =~ /\bstatic\b/; + my @derr = @{$record->{'errors'}}; + my @inherr = @{$record->{'inherited-errors'}[0]}; + my $path = $record->{'file'}; + print "$name "; + my %temp = (); + @temp{@inherr} = (); + for (@derr) { + delete $temp{$_}; + print "$_ "; + } + if (keys %temp) { + foreach (keys %temp) { + print "$_ "; + } + } + print "\n"; +} + +exit; + +sub potential_errors { + my $function = shift; + + + return ([],[[],[]]) if ! exists $functions->{$function}; + my $record = $functions->{$function}; + + return ([],[[],[]]) if $record->{'return-type'} !~ /\bg?int\b/ || $record->{'recursing'}; + + if (! exists $record->{'inherited-errors'}) { + my @inheritederrors; + my @froms; + $record->{'recursing'} = 1; + + foreach my $call (@{$record->{'calls'}}) { + my ($err,$inh) = potential_errors($call); + my ($suberr,$subfrom) = @$inh; + + if (@$err || @$suberr) { + push @froms, $call; + push @inheritederrors, (@$err, @$suberr); + } + } + $record->{'inherited-errors'} = [[ unique(@inheritederrors) ],[@froms]]; + delete $record->{'recursing'}; + } + return ($record->{'errors'},$record->{'inherited-errors'}); +} + + +sub parse_file { + my $file = shift; + my $path = shift; + my $lastline; + my $curfunction; + my $curtype; + my @curerrors; + my @curcalls; + my $infunction = 0; + open FD, "<$file"; + while (<FD>) { + + MATCHING: { + if ($infunction) { + if (/^\}/) { + #print "finished funcctions $curfunction\n"; + $functions->{$curfunction} = { name => $curfunction, 'return-type' => $curtype, 'errors' => [ unique(@curerrors) ], 'calls' => [ @curcalls], 'file' => $path}; + $infunction = 0; + last MATCHING; + } + while (/(?:\breturn\b|=).*?([A-Za-z_]+)\(/g) { + push @curcalls, $1; + } + pos = 0; + while (/(LASSO_[A-Z_]*_ERROR_[A-Z_]*|LASSO_ERROR_[A-Z_]*)/g) { + push @curerrors, $1; + } + last MATCHING; + } + if (/^([a-z_]+)\([^;]*$/) { + $curfunction = $1; + chop $lastline; + $curtype = $lastline; + @curerrors = (); + @curcalls = (); + last MATCHING; + } + if ($curfunction && /^\{/) { + $infunction = 1; + last MATCHING; + } + } + $lastline = $_; + + } + close FD; +} + +sub wanted { + my ($dev,$ino,$mode,$nlink,$uid,$gid); + + parse_file($_,$File::Find::name) if ($_ =~ /^.*\.c$/s && $File::Find::name !~ /^.*\.svn.*/); +} + diff --git a/bindings/utils.py b/bindings/utils.py index c313bce3..2f6408f2 100644 --- a/bindings/utils.py +++ b/bindings/utils.py @@ -48,3 +48,55 @@ def format_underscore_as_camelcase(var): var = re.sub(r'([a-z])(ID)([A-Z]|$)', r'\1Id\3', var) # replace standing ID by Id return var + + +def last(x): + return x[len(x)-1] + +def common_prefix(x,y): + max = min(len(x),len(y)) + last = 0 + for i in range(max): + if x[i] != y[i]: + return min(i,last+1) + if x[i] == '_': + last = i + return max + +def pgroup(group,prev): + level, l = group + i = 0 + for x in l: + if i == 0: + prefix = prev + else: + prefix = level + if isinstance(x,tuple): + pgroup(x,prefix) + else: + print prefix * ' ' + x[prefix:] + i = i + 1 + +def group(list): + list.sort() + pile = [(0,[])] + prev = "" + for x in list: + l, g = last(pile) + u = common_prefix(x,prev) + # Find the good level of insertion + while u < l: + pile.pop() + l, g = last(pile) + # Insert here + if u == l: + g.append(x) + elif u > l: + t = (u, [g.pop(),x]) + g.append(t) + pile.append(t) + prev = x + return pile[0] + + + |