#!/usr/bin/env python # # __COPYRIGHT__ # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Real-world test (courtesy Leanid Nazdrynau) of the multi-step capabilities of the various Java Builders. """ import TestSCons test = TestSCons.TestSCons() where_javac, java_version = test.java_where_javac() where_javah = test.java_where_javah() where_java_include=test.java_where_includes() swig = test.where_is('swig') if not swig: test.skip_test('Can not find installed "swig", skipping test.\n') test.subdir(['src'], ['src', 'HelloApplet'], ['src', 'HelloApplet', 'com'], ['src', 'javah'], ['src', 'jni'], ['src', 'server'], ['src', 'server', 'JavaSource'], ['src', 'server', 'JavaSource', 'com'], ['src', 'server', 'JavaSource', 'com', 'gnu'], ['src', 'server', 'JavaSource', 'com', 'gnu', 'scons'], ['src', 'server', 'JavaSource', 'com', 'gnu', 'scons', 'web'], ['src', 'server', 'JavaSource', 'com', 'gnu', 'scons', 'web', 'tools'], ['src', 'server', 'WebContent'], ['src', 'server', 'WebContent', 'META-INF'], ['src', 'server', 'WebContent', 'WEB-INF'], ['src', 'server', 'WebContent', 'WEB-INF', 'conf'], ['src', 'server', 'WebContent', 'WEB-INF', 'lib'], ['src', 'server', 'WebContent', 'theme']) test.write(['SConstruct'], """\ import os,sys env=Environment(tools = ['default', 'javac', 'javah'], CPPPATH=%(where_java_include)s, JAVAC = r'%(where_javac)s', JAVAH = r'%(where_javah)s') Export('env') env.PrependENVPath('PATH',os.environ.get('PATH',[])) env['INCPREFIX']='-I' env.Append(SWIGFLAGS=['-c++','$_CPPINCFLAGS']) #this is for JNI #env.Append(CCFLAGS=['/IN:/jdk/v1.3.1/include','/IN:/jdk/v1.3.1/include/win32']) #this for windows only C++ build #env.Append(CXXFLAGS='-GX') env.Append(CPPPATH='.') env.VariantDir('buildout', 'src', duplicate=0) if sys.platform[:6]=='darwin': env.Append(CPPPATH=['/System/Library/Frameworks/JavaVM.framework/Headers']) #If you do not have swig on your system please remove 'buildout/jni/SConscript' line from next call env.SConscript(['buildout/server/JavaSource/SConscript', 'buildout/HelloApplet/SConscript', 'buildout/jni/SConscript', 'buildout/javah/SConscript']) """ % locals()) test.write(['src', 'HelloApplet', 'Hello.html'], """\ Applet Hello
""") test.write(['src', 'HelloApplet', 'SConscript'], """\ import os Import ("env") denv=env.Clone() classes=denv.Java(target='classes',source=['com']) #set correct path for jar denv['JARCHDIR']=os.path.join(denv.Dir('.').get_abspath(),'classes') denv.Jar('HelloApplet',classes) #To sign applet you have to create keystore before and made a calls like this #keystore='/path/to/jarsignkey' #denv['JARSIGNFLAGS']='-keystore '+keystore+' -storepass pass -keypass passkey' #denv['JARSIGNALIAS']='ALIAS' #denv['JARCOM']=[denv['JARCOM'],'$JARSIGNCOM'] """) test.write(['src', 'HelloApplet', 'com', 'Hello.java'], """\ package com.Hello; import java.awt.*; import java.applet.*; public class Hello extends Applet { public void paint(Graphics g) { g.drawString("Hello from SCons signed applet",250,150); } } """) test.write(['src', 'javah', 'MyID.cc'], """\ #include "MyID.h" int getMyID() { return 0; } """) test.write(['src', 'javah', 'MyID.java'], """\ import java.util.*; import java.io.IOException; import java.lang.reflect.*; public class MyID { static private long current = System.currentTimeMillis(); static public String get() { current++; return new Long( current ).toString(); } } """) test.write(['src', 'javah', 'SConscript'], """\ Import('env') denv=env.Clone() denv['JARCHDIR']=denv.Dir('.').get_abspath() denv.Jar('myid','MyID.java') denv.JavaH(denv.Dir('.').get_abspath(),'MyID.java') denv.SharedLibrary('myid','MyID.cc') """) test.write(['src', 'jni', 'A.java'], """\ package web.jni; import web.jni.*; public class A { class C { void echo2( String text ) { System.out.println( text+"aa" ); } } class B { void echo( String text ) { System.out.println( text ); C c = new C(); c.echo2("from B callin C"); } } public void main( String[] x) { B b = new B(); b.echo("123"); C c = new C(); c.echo2("456"); } } """) test.write(['src', 'jni', 'JniWrapper.cc'], """\ #include #include #include "JniWrapper.h" JniWrapper::JniWrapper( JNIEnv *pEnv ) : mpEnv( pEnv ) { } JniWrapper::JniWrapper( const JniWrapper& rJniWrapper ) : mpEnv( rJniWrapper.mpEnv ) { } JniWrapper::~JniWrapper() { } JniWrapper& JniWrapper::operator=( const JniWrapper& rJniWrapper ) { if ( this != &rJniWrapper ) { mpEnv = rJniWrapper.mpEnv; } return *this; } std::string JniWrapper::unmarshalString( jstring value ) { std::string result; if( value ) { const char *pStr = mpEnv->GetStringUTFChars( value, 0 ); result = pStr; mpEnv->ReleaseStringUTFChars( value, pStr ); } return result; } jobject JniWrapper::marshalDouble( double value ) { jclass classObject = mpEnv->FindClass( "java/lang/Double" ); jmethodID constructorId = mpEnv->GetMethodID( classObject, "", "(D)V" ); jobject result = mpEnv->NewObject( classObject, constructorId, value ); return result; } jobject JniWrapper::getVectorElement( jobject values, int i ) { jclass vectorClass = mpEnv->FindClass( "java/util/Vector" ); jmethodID methodID = mpEnv->GetMethodID( vectorClass, "elementAt", "(I)Ljava/lang/Object;" ); jobject result = mpEnv->CallObjectMethod( values, methodID, i ); return result; } jobject JniWrapper::newVector() { jclass vectorClass = mpEnv->FindClass( "java/util/Vector" ); jmethodID constructorID = mpEnv->GetMethodID( vectorClass, "", "()V" ); jobject result = mpEnv->NewObject( vectorClass, constructorID ); return result; } void JniWrapper::addElement( jobject vector, jobject element ) { jclass vectorClass = mpEnv->FindClass( "java/util/Vector" ); jmethodID addElementMethodID = mpEnv->GetMethodID( vectorClass, "addElement", "(Ljava/lang/Object;)V" ); mpEnv->CallVoidMethod( vector, addElementMethodID, element ); } jobject JniWrapper::marshalDoubleVector( const std::vector& rVector ) { jobject result = newVector(); for ( int i = 0; i < rVector.size(); i++ ) { addElement( result, marshalDouble( rVector[i] ) ); } return result; } std::pair JniWrapper::unmarshalPairString( jobject vector ) { std::pair result; result.first = unmarshalString( (jstring)getVectorElement( vector, 0 ) ); result.second = unmarshalString( (jstring)getVectorElement( vector, 1 ) ); return result; } """) test.write(['src', 'jni', 'JniWrapper.h'], """\ #ifndef JniWrapper_h #define JniWrapper_h #include /** * Provides routines for dealing with JNI translation etc. */ class JniWrapper { public: JniWrapper( JNIEnv *pEnv ); JniWrapper( const JniWrapper& rJniWrapper ); virtual ~JniWrapper(); JniWrapper& operator=( const JniWrapper& rJniWrapper ); std::string unmarshalString( jstring value ); jstring marshalString( const std::string& value ); jbyteArray marshalByteArray( const std::string& value ); double unmarshalDouble( jobject value ); jobject marshalDouble( double value ); jobject marshallStringVector( const std::vector& rMap ); jobject marshalDoubleVector( const std::vector& rVector ); std::pair unmarshalPairString( jobject ); protected: JNIEnv *mpEnv; private: JniWrapper(); jobject newVector(); void addElement( jobject vector, jobject element ); jobject getVectorElement( jobject values, int i ); }; #endif // JniWrapper_h """) test.write(['src', 'jni', 'SConscript'], """\ Import ("env") denv=env.Clone() denv.Append(SWIGFLAGS=['-java']) denv.SharedLibrary('scons',['JniWrapper.cc','Sample.i']) denv['JARCHDIR']=denv.Dir('.').get_abspath() denv.Jar(['Sample.i','A.java']) """) test.write(['src', 'jni', 'Sample.h'], """\ #include #include class SampleTest { public: std::vector test1( std::pair param ) { std::vector result; result.push_back(10); return result; } }; """) test.write(['src', 'jni', 'Sample.i'], """\ %module Sample %{ #include "Sample.h" #include "JniWrapper.h" %} %typemap(jni) std::vector, std::vector& "jobject" %typemap(jtype) std::vector, std::vector& "java.util.Vector" %typemap(jstype) std::vector, std::vector& "java.util.Vector" // return a Vector of Doubles %typemap(javaout) std::vector { return $jnicall; } %typemap(out) std::vector { JniWrapper JniWrapper(jenv); $result = JniWrapper.marshalDoubleVector( $1 ); } /********************************************************************* * * Pairs of String (IN/OUT) * *********************************************************************/ %typemap(jni) std::pair, const std::pair& "jobject" %typemap(jtype) std::pair, const std::pair& "java.util.Vector" %typemap(jstype) std::pair, const std::pair& "java.util.Vector" %typemap(javain) std::pair, const std::pair& "$javainput" // pass in by reference a Vector of std::string %typemap(in) const std::pair& { $1 = new std::pair(); JniWrapper JniWrapper(jenv); *($1) = JniWrapper.unmarshalPairString( $input ); } //cleanup %typemap(freearg) const std::pair& { delete $1; } %include "Sample.h" // generate:Sample.java // generate:SampleJni.java // generate:SampleTest.java """) test.write(['src', 'server', 'JavaSource', 'SConscript'], """\ import os Import ("env") classes=env.Java(target='classes',source=['com']) HelloApplet=os.path.join('#/buildout/HelloApplet/HelloApplet.jar') env['WARXFILES']=['SConscript','.cvsignore'] env['WARXDIRS']=['CVS'] #env.War('scons',[classes,Dir('../WebContent'),HelloApplet]) """) test.write(['src', 'server', 'JavaSource', 'com', 'gnu', 'scons', 'web', 'tools', 'Bool.java'], """\ package com.gnu.scons.web.tools; public class Bool { boolean flag; public Bool() { flag = false; } public Bool( boolean aFlag ) { flag = aFlag; } public boolean booleanValue() { return flag; } } """) test.write(['src', 'server', 'JavaSource', 'com', 'gnu', 'scons', 'web', 'tools', 'StringUtils.java'], """\ package com.gnu.scons.web.tools; import java.util.Iterator; import java.util.Map; public class StringUtils { public static String toPercent( String value ) { if ( value.equals("") ) { return ""; } else { return value + "%"; } } } """) test.write(['src', 'server', 'WebContent', 'index.html'], """\ index.html

go?action=home

""") test.write(['src', 'server', 'WebContent', 'META-INF', 'MANIFEST.MF'], """\ Manifest-Version: 1.0 Class-Path: """) test.write(['src', 'server', 'WebContent', 'WEB-INF', 'web.xml'], """\ scons WebExample WebExample com.gnu.scons.web.tool.WebExample WebExample /go index.html index.htm """) test.write(['src', 'server', 'WebContent', 'WEB-INF', 'conf', 'app.properties'], """\ logging = webExample.Example """) test.write(['src', 'server', 'WebContent', 'theme', 'Master.css'], """\ body { font-family: Helvetica,Sans-Serif; font-size: 11pt; } """) test.run(arguments = '.') test.must_exist(['buildout', 'javah', 'myid.jar']) test.must_exist(['buildout', 'javah', 'MyID', 'MyID.class']) test.must_exist(['buildout', 'jni', 'Sample.class']) test.must_exist(['buildout', 'jni', 'Sample.java']) test.must_exist(['buildout', 'jni', 'SampleJNI.class']) test.must_exist(['buildout', 'jni', 'SampleJNI.java']) test.must_exist(['buildout', 'jni', 'SampleTest.java']) # Some combinations of Java + SWIG apparently don't actually generate # a SampleTest.class file, while others do. Only issue a warning if # it doesn't exist. p = test.workpath('buildout', 'jni', 'SampleTest.class') import os.path if not os.path.exists(p): print 'Warning: %s does not exist' % p test.up_to_date(arguments = '.') test.pass_test()