diff options
Diffstat (limited to 'bindings/corba')
-rw-r--r-- | bindings/corba/Makefile.am | 3 | ||||
-rw-r--r-- | bindings/corba/java/Makefile | 24 | ||||
-rw-r--r-- | bindings/corba/java/Makefile.in | 43 | ||||
-rw-r--r-- | bindings/corba/java/src/org/crosswire/sword/orb/SwordOrb.java | 248 | ||||
-rw-r--r-- | bindings/corba/java/src/org/crosswire/util/Base64.java | 1238 | ||||
-rw-r--r-- | bindings/corba/java/src/org/crosswire/web/i18n/ContextStart.java.notyet | 10 | ||||
-rw-r--r-- | bindings/corba/java/src/org/crosswire/web/i18n/TranslateTag.java | 87 | ||||
-rw-r--r-- | bindings/corba/java/swordorb.jpx | 41 | ||||
-rw-r--r-- | bindings/corba/java/swordorb.jpx.local | 10 | ||||
-rwxr-xr-x | bindings/corba/java/testclient | 6 | ||||
-rw-r--r-- | bindings/corba/orbitcpp/Makefile | 66 | ||||
-rw-r--r-- | bindings/corba/orbitcpp/Makefile.am | 40 | ||||
-rw-r--r-- | bindings/corba/orbitcpp/server.cpp | 71 | ||||
-rw-r--r-- | bindings/corba/orbitcpp/swordorb-impl.cpp | 357 | ||||
-rw-r--r-- | bindings/corba/orbitcpp/swordorb-impl.hpp | 79 | ||||
-rw-r--r-- | bindings/corba/orbitcpp/testclient.cpp | 87 | ||||
-rw-r--r-- | bindings/corba/orbitcpp/webmgr.hpp | 97 | ||||
-rw-r--r-- | bindings/corba/swordorb.idl | 92 |
18 files changed, 2599 insertions, 0 deletions
diff --git a/bindings/corba/Makefile.am b/bindings/corba/Makefile.am new file mode 100644 index 0000000..b626afd --- /dev/null +++ b/bindings/corba/Makefile.am @@ -0,0 +1,3 @@ +EXTRA_DIST = swordorb.idl + +SUBDIRS = orbitcpp java diff --git a/bindings/corba/java/Makefile b/bindings/corba/java/Makefile new file mode 100644 index 0000000..9f0ce39 --- /dev/null +++ b/bindings/corba/java/Makefile @@ -0,0 +1,24 @@ +TOMCAT_HOME=/opt/tomcat +#SERVLET_LIB=${TOMCAT_HOME}/common/lib/servlet-api.jar +SERVLET_LIB=${TOMCAT_HOME}/lib/servlet-api.jar +#instdir=/home/scribe/public_html/ +instdir=/home/scribe/src/swordweb/webapp +all: src/org/crosswire/sword/orb/SWMgr.java classes/org/crosswire/sword/orb/SwordOrb.class + +src/org/crosswire/sword/orb/SWMgr.java: ../swordorb.idl + idlj -pkgTranslate swordorb org.crosswire.sword.orb -td src ../swordorb.idl + +classes/org/crosswire/sword/orb/SwordOrb.class: src/org/crosswire/sword/orb/SwordOrb.java + javac -classpath ${SERVLET_LIB} -d classes -sourcepath src src/org/crosswire/sword/orb/*.java src/org/crosswire/util/*.java + + +clean: + rm -f src/org/crosswire/sword/orb/SW*.java + rm -f src/org/crosswire/sword/orb/_SW*.java + rm -f src/org/crosswire/sword/orb/Mod*.java + rm -f src/org/crosswire/sword/orb/Search*.java + rm -f src/org/crosswire/sword/orb/String*.java + rm -rf classes/* + +install: + cp -a classes/org/ ${instdir}/WEB-INF/classes/ diff --git a/bindings/corba/java/Makefile.in b/bindings/corba/java/Makefile.in new file mode 100644 index 0000000..320afcc --- /dev/null +++ b/bindings/corba/java/Makefile.in @@ -0,0 +1,43 @@ + +TOMCAT_HOME = @TOMCAT_HOME@ +VERSION = @VERSION@ +JAVAC = @JAVAC@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ +INSTALL = @INSTALL@ +JAR = @JAR@ + +#SWORDORBJAR=sword-orb-$(VERSION).jar +SWORDORBJAR=sword-orb.jar + +all: $(SWORDORBJAR) + +src/org/crosswire/sword/orb/SWMgr.java: $(top_builddir)/corba/java/src/org/crosswire/util/Base64.java + idlj -pkgTranslate swordorb org.crosswire.sword.orb -td src $(top_srcdir)/corba/swordorb.idl + +classes/org/crosswire/sword/orb/SwordOrb.class: src/org/crosswire/sword/orb/SWMgr.java + mkdir -p $(top_builddir)/corba/java/classes + $(JAVAC) -classpath ${TOMCAT_HOME}/common/lib/servlet-api.jar -d $(top_builddir)/corba/java/classes -sourcepath src src/org/crosswire/sword/orb/*.java src/org/crosswire/util/*.java + +$(top_builddir)/corba/java/src/org/crosswire/util/Base64.java: + cp -a $(top_srcdir)/corba/java/src . + find . -name .svn|xargs rm -r + +clean: + -rm src/org/crosswire/sword/orb/SW*.java + -rm src/org/crosswire/sword/orb/_SW*.java + -rm src/org/crosswire/sword/orb/Mod*.java + -rm src/org/crosswire/sword/orb/Search*.java + -rm src/org/crosswire/sword/orb/String*.java + -rm -rf classes/* + -rmdir -p src/org/crosswire/sword/orb + -rm $(SWORDORBJAR) + +$(SWORDORBJAR): classes/org/crosswire/sword/orb/SwordOrb.class + $(JAR) cf $(SWORDORBJAR) -C $(top_builddir)/corba/java/classes org + +install: + @INSTALL@ $(SWORDORBJAR) $(TOMCAT_HOME)/common/lib + +uninstall: + -rm $(TOMCAT_HOME)/common/lib/$(SWORDORBJAR) diff --git a/bindings/corba/java/src/org/crosswire/sword/orb/SwordOrb.java b/bindings/corba/java/src/org/crosswire/sword/orb/SwordOrb.java new file mode 100644 index 0000000..3597b4b --- /dev/null +++ b/bindings/corba/java/src/org/crosswire/sword/orb/SwordOrb.java @@ -0,0 +1,248 @@ +package org.crosswire.sword.orb; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.BufferedReader; +import java.io.StringWriter; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSessionBindingListener; +import javax.servlet.http.HttpSessionBindingEvent; +import java.util.Vector; +import java.util.Hashtable; +import java.util.Date; +import java.util.Properties; + +public class SwordOrb extends Object implements HttpSessionBindingListener { + public static Properties config = null; + public static String ORBEXE = "swordorbserver"; + public static final int MAX_REMOTE_ADDR_CONNECTIONS = 20; + public static final int MAX_ACCESS_COUNT_PER_INTERVAL = 10; + public static final long MAX_ACCESS_COUNT_INTERVAL = 10 * 1000; // milliseconds + public static final long BLACKLIST_DURATION = 10 * 60 * 1000; // milliseconds + public static final String BIBLES = "Biblical Texts"; + public static final String COMMENTARIES = "Commentaries"; + public static final String LEXDICTS = "Lexicons / Dictionaries"; + public static final String GENBOOKS = "Generic Books"; + public static final String DAILYDEVOS = "Daily Devotional"; + + static org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(new String[]{}, null); + static Hashtable clients = new Hashtable(); + String ior = null; + String remoteAddr = null; + String localeName = null; + long lastAccessed = 0; + int intervalCount = 0; + long intervalStamp = 0; + long blacklistTill = 0; + + private SWMgr attach() { + + // assert IOR has been set + if (ior == null) + return null; + + SWMgr retVal = null; + try { +System.out.println("attaching..."); + org.omg.CORBA.Object obj = orb.string_to_object(ior); + retVal = SWMgrHelper.narrow(obj); +System.out.println("calling testConnection"); + retVal.testConnection(); +System.out.println("testConnection successful"); + } + catch(Throwable e) { +// e.printStackTrace(); + retVal = null; +System.out.println("failed in attach"); + } + return retVal; + } + + public SwordOrb(String remoteAddr) { + this.remoteAddr = remoteAddr; + } + + +// this doesn't seem to work. Never seems to get called for me + public void finalize () throws Throwable { + // shut down external process + try { +System.out.println("calling finalize."); + getSWMgrInstance().terminate(); + } + catch (Exception e) {} // we know this doesn't return property cuz we killed the orb! :) + + } + + + public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {} + + public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) { + try { +// throw new Exception("value unbound; showing stacktrace"); + Vector orbs = (Vector)clients.get(remoteAddr); +int size = -1; + if (orbs != null) { +size = orbs.size(); + orbs.remove(this); + } +System.out.println("calling valueUnbound. size before: " + size + "; size after: "+orbs.size()); + getSWMgrInstance().terminate(); + } + catch (Exception e) {} // we know this doesn't return properly cuz we killed the orb! :) +// catch (Exception e) {e.printStackTrace();} // we know this doesn't return properly cuz we killed the orb! :) + } + + private static void loadConfig(HttpServletRequest request) { + try { + config = new Properties(); + File propName = new File(request.getSession().getServletContext().getRealPath("/WEB-INF/swordweb.properties")); + if (propName.exists()) { + FileInputStream propFile = new FileInputStream(propName); + config.load(propFile); + propFile.close(); + } + } + catch (Exception e) { e.printStackTrace(); } + ORBEXE = config.getProperty("orbexe", "swordorbserver"); + } + + private void startOrb() { + try { + // start external process + java.lang.Process p = Runtime.getRuntime().exec(ORBEXE); + InputStream is = p.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader input = new BufferedReader(isr); + + String line; + line = input.readLine(); +// retVal = p.waitFor(); + ior = line; +System.out.println("Launched ORB, IOR: " + ior); + } + catch (Exception e) {e.printStackTrace();} + } + + void checkAccessAbuse() throws Exception { + if ((blacklistTill > 0) && (System.currentTimeMillis() < blacklistTill)) { + throw new Exception("You're an abuser and have been blacklisted till " + new Date(blacklistTill)); + } + if (++intervalCount > MAX_ACCESS_COUNT_PER_INTERVAL) { + if (System.currentTimeMillis() < intervalStamp + MAX_ACCESS_COUNT_INTERVAL) { + // abuser + blacklistTill = System.currentTimeMillis() + BLACKLIST_DURATION; + } + intervalStamp = System.currentTimeMillis(); + intervalCount = 0; + } + } + + public SWMgr getSWMgrInstance() throws Exception { + lastAccessed = System.currentTimeMillis(); + checkAccessAbuse(); + SWMgr retVal = null; + try { +System.out.println("trying to attach to running ORB"); + retVal = attach(); + } + catch(Exception e) { +// e.printStackTrace(); + retVal = null; + } + if (retVal == null) { + try { +System.out.println("no ORB running; trying to launch"); + startOrb(); +System.out.println("trying to attach to newly launched ORB"); + retVal = attach(); + if (retVal != null) { + if (localeName != null) { + retVal.setDefaultLocale(localeName); + } + } + } + catch(org.omg.CORBA.SystemException e) { + e.printStackTrace(); + } + } + return retVal; + } + + public static void setSessionLocale(String localeName, HttpServletRequest request) throws Exception { + request.getSession().setAttribute("SwordOrbLocale", localeName); + SWMgr mgr = getSWMgrInstance(request); + if (mgr != null) { + mgr.setDefaultLocale(localeName); + } + } + + public static SwordOrb getSessionOrb(HttpServletRequest request) throws Exception { + if (config == null) loadConfig(request); + HttpSession session = request.getSession(); + SwordOrb orb = (SwordOrb)session.getAttribute("SwordOrb"); + String remoteAddr = request.getRemoteAddr(); + if (orb == null) { +System.out.println("No ORB found in session; constructing a new instance"); + + Vector orbs = (Vector)clients.get(remoteAddr); + if (orbs == null) { + orbs = new Vector(); + clients.put(remoteAddr, orbs); + } + if (orbs.size() < MAX_REMOTE_ADDR_CONNECTIONS) { + orb = new SwordOrb(remoteAddr); + orbs.add(orb); + + String locName = (String)session.getAttribute("SwordOrbLocale"); + if (locName != null) + orb.localeName = locName; + + session.setAttribute("SwordOrb", orb); + } + else throw new Exception("Max Remote Addr Connections from: ["+remoteAddr+"]"); + } + else { +System.out.println("ORB found in session"); + } + return orb; + } + + public static SWMgr getSWMgrInstance(HttpServletRequest request) throws Exception { + SwordOrb orb = getSessionOrb(request); + SWMgr mgr = orb.getSWMgrInstance(); + return mgr; + } + + + public static void main(String args[]) throws Exception { + SWMgr mgr = new SwordOrb("127.0.0.1").getSWMgrInstance(); + + System.out.println("PrefixPath: " + mgr.getPrefixPath()); + System.out.println("ConfigPath: " + mgr.getConfigPath()); + ModInfo[] modInfoList = mgr.getModInfoList(); + System.out.println("sequence size: " + modInfoList.length); + SWModule module; +/* + for (int i = 0; i < modInfoList.length; i++) { + System.out.println(modInfoList[i].name + ": " + modInfoList[i].category + ": " + modInfoList[i].language); + module = mgr.getModuleByName(modInfoList[i].name); + module.setKeyText("jas1:19"); + System.out.println(module.getRenderText()); + } +*/ + module = mgr.getModuleByName("WHNU"); + module.setKeyText("rev.22.21"); + System.out.println(new String(module.getRawEntry().getBytes("iso8859-1"), "UTF-8")); +/* + boolean lucene = module.hasSearchFramework(); + SearchHit[] searchResults = module.search("God love world", (lucene)?SearchType.LUCENE:SearchType.MULTIWORD, 0, ""); + for (int i = 0; i < searchResults.length; i++) + System.out.println(searchResults[i].key); + +*/ + } +} diff --git a/bindings/corba/java/src/org/crosswire/util/Base64.java b/bindings/corba/java/src/org/crosswire/util/Base64.java new file mode 100644 index 0000000..984dc7b --- /dev/null +++ b/bindings/corba/java/src/org/crosswire/util/Base64.java @@ -0,0 +1,1238 @@ +package org.crosswire.util; + +/** + * Changed last char from '/' to '-' because cookies can't use '/' so we're not really a BASE64 + * standard encoder anymore + * Changed package name. --crosswire. + * Thanks to Robert Harder for placing this code into the public domain + * + * Encodes and decodes to and from Base64 notation. + * + * <p> + * Change Log: + * </p> + * <ul> + * <li>v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream + * where last buffer being read, if not completely full, was not returned.</li> + * <li>v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time.</li> + * <li>v1.3.3 - Fixed I/O streams which were totally messed up.</li> + * </ul> + * + * <p> + * I am placing this code in the Public Domain. Do with it as you will. + * This software comes with no guarantees or warranties but with + * plenty of well-wishing instead! + * Please visit <a href="http://iharder.net/xmlizable">http://iharder.net/xmlizable</a> + * periodically to check for updates or to contribute improvements. + * </p> + * + * @author Robert Harder + * @author rob@iharder.net + * @version 1.3.4 + */ +public class Base64 +{ + + /** Specify encoding (value is <tt>true</tt>). */ + public final static boolean ENCODE = true; + + + /** Specify decoding (value is <tt>false</tt>). */ + public final static boolean DECODE = false; + + + /** Maximum line length (76) of Base64 output. */ + private final static int MAX_LINE_LENGTH = java.lang.Integer.MAX_VALUE; + + + /** The equals sign (=) as a byte. */ + private final static byte EQUALS_SIGN = (byte)'='; + + + /** The new line character (\n) as a byte. */ + private final static byte NEW_LINE = (byte)'\n'; + + + /** The 64 valid Base64 values. */ + private final static byte[] ALPHABET = + { + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', + (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'-' // changed last char from '/' to '-' because cookies can't use '/' + }; + + /** + * Translates a Base64 value to either its 6-bit reconstruction value + * or a negative number indicating some other meaning. + **/ + private final static byte[] DECODABET = + { + -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 + -5,-5, // Whitespace: Tab and Linefeed + -9,-9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 + -9,-9,-9,-9,-9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 + 62, // Plus sign at decimal 43 + -9,-9,-9, // Decimal 44 - 46 + 63, // Slash at decimal 47 + 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine + -9,-9,-9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9,-9,-9, // Decimal 62 - 64 + 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N' + 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z' + -9,-9,-9,-9,-9,-9, // Decimal 91 - 96 + 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm' + 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z' + -9,-9,-9,-9 // Decimal 123 - 126 + /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ + }; + + private final static byte BAD_ENCODING = -9; // Indicates error in encoding + private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding + private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding + + + /** Defeats instantiation. */ + private Base64(){} + + + + /** + * Testing. Feel free--in fact I encourage you--to throw out + * this entire "main" method when you actually deploy this code. + */ + public static void main( String[] args ) + { + try + { + // Test encoding/decoding byte arrays + { + byte[] bytes1 = { (byte)2,(byte)2,(byte)3,(byte)0,(byte)9 }; // My zip code + byte[] bytes2 = { (byte)99,(byte)2,(byte)2,(byte)3,(byte)0,(byte)9 }; + System.out.println( "Bytes 2,2,3,0,9 as Base64: " + encodeBytes( bytes1 ) ); + System.out.println( "Bytes 2,2,3,0,9 w/ offset: " + encodeBytes( bytes2, 1, bytes2.length-1 ) ); + byte[] dbytes = decode( encodeBytes( bytes1 ) ); + System.out.print( encodeBytes( bytes1 ) + " decoded: " ); + for( int i = 0; i < dbytes.length; i++ ) + System.out.print( dbytes[i] + (i<dbytes.length-1?",":"\n") ); + } // end testing byte arrays + + + + + // Test Input Stream + { + // Read GIF stored in base64 form. + java.io.FileInputStream fis = new java.io.FileInputStream( "test.gif.b64" ); + Base64.InputStream b64is = new Base64.InputStream( fis, DECODE ); + + byte[] bytes = new byte[0]; + int b = -1; + while( (b = b64is.read()) >= 0 ){ + byte[] temp = new byte[ bytes.length + 1 ]; + System.arraycopy( bytes,0, temp,0,bytes.length ); + temp[bytes.length] = (byte)b; + bytes = temp; + } // end while: terribly inefficient way to read data + b64is.close(); + javax.swing.ImageIcon iicon = new javax.swing.ImageIcon( bytes ); + javax.swing.JLabel jlabel = new javax.swing.JLabel( "Read from test.gif.b64", iicon,0 ); + javax.swing.JFrame jframe = new javax.swing.JFrame(); + jframe.getContentPane().add( jlabel ); + jframe.pack(); + jframe.show(); + + // Write raw bytes to file + java.io.FileOutputStream fos = new java.io.FileOutputStream( "test.gif_out" ); + fos.write( bytes ); + fos.close(); + + // Read raw bytes and encode + fis = new java.io.FileInputStream( "test.gif_out" ); + b64is = new Base64.InputStream( fis, ENCODE ); + byte[] ebytes = new byte[0]; + b = -1; + while( (b = b64is.read()) >= 0 ){ + byte[] temp = new byte[ ebytes.length + 1 ]; + System.arraycopy( ebytes,0, temp,0,ebytes.length ); + temp[ebytes.length] = (byte)b; + ebytes = temp; + } // end while: terribly inefficient way to read data + b64is.close(); + String s = new String( ebytes ); + javax.swing.JTextArea jta = new javax.swing.JTextArea( s ); + javax.swing.JScrollPane jsp = new javax.swing.JScrollPane( jta ); + jframe = new javax.swing.JFrame(); + jframe.setTitle( "Read from test.gif_out" ); + jframe.getContentPane().add( jsp ); + jframe.pack(); + jframe.show(); + + // Write encoded bytes to file + fos = new java.io.FileOutputStream( "test.gif.b64_out" ); + fos.write( ebytes ); + + // Read GIF stored in base64 form. + fis = new java.io.FileInputStream( "test.gif.b64_out" ); + b64is = new Base64.InputStream( fis, DECODE ); + byte[] edbytes = new byte[0]; + b = -1; + while( (b = b64is.read()) >= 0 ){ + byte[] temp = new byte[ edbytes.length + 1 ]; + System.arraycopy( edbytes,0, temp,0,edbytes.length ); + temp[edbytes.length] = (byte)b; + edbytes = temp; + } // end while: terribly inefficient way to read data + b64is.close(); + iicon = new javax.swing.ImageIcon( edbytes ); + jlabel = new javax.swing.JLabel( "Read from test.gif.b64_out", iicon,0 ); + jframe = new javax.swing.JFrame(); + jframe.getContentPane().add( jlabel ); + jframe.pack(); + jframe.show(); + } // end: Test Input Stream + + + // Test Output Stream + { + // Read raw bytes + java.io.FileInputStream fis = new java.io.FileInputStream( "test.gif_out" ); + byte[] rbytes = new byte[0]; + int b = -1; + while( (b = fis.read()) >= 0 ){ + byte[] temp = new byte[ rbytes.length + 1 ]; + System.arraycopy( rbytes,0, temp,0,rbytes.length ); + temp[rbytes.length] = (byte)b; + rbytes = temp; + } // end while: terribly inefficient way to read data + fis.close(); + + // Write raw bytes to encoded file + java.io.FileOutputStream fos = new java.io.FileOutputStream("test.gif.b64_out2"); + Base64.OutputStream b64os = new Base64.OutputStream( fos, ENCODE ); + b64os.write( rbytes ); + b64os.close(); + + + // Read raw bytes that are actually encoded (but we'll ignore that) + fis = new java.io.FileInputStream( "test.gif.b64_out2" ); + byte[] rebytes = new byte[0]; + b = -1; + while( (b = fis.read()) >= 0 ){ + byte[] temp = new byte[ rebytes.length + 1 ]; + System.arraycopy( rebytes,0, temp,0,rebytes.length ); + temp[rebytes.length] = (byte)b; + rebytes = temp; + } // end while: terribly inefficient way to read data + fis.close(); + String s = new String( rebytes ); + javax.swing.JTextArea jta = new javax.swing.JTextArea( s ); + javax.swing.JScrollPane jsp = new javax.swing.JScrollPane( jta ); + javax.swing.JFrame jframe = new javax.swing.JFrame(); + jframe.setTitle( "Read from test.gif.b64_out2" ); + jframe.getContentPane().add( jsp ); + jframe.pack(); + jframe.show(); + + // Write encoded bytes to decoded raw file + fos = new java.io.FileOutputStream("test.gif_out2"); + b64os = new Base64.OutputStream( fos, DECODE ); + b64os.write( rebytes ); + b64os.close(); + javax.swing.ImageIcon iicon = new javax.swing.ImageIcon( "test.gif_out2" ); + javax.swing.JLabel jlabel = new javax.swing.JLabel( "Read from test.gif_out2", iicon,0 ); + jframe = new javax.swing.JFrame(); + jframe.getContentPane().add( jlabel ); + jframe.pack(); + jframe.show(); + + } // end: Test Output Stream + + + // Test wagner's files + { + java.io.FileInputStream fis = new java.io.FileInputStream("D:\\temp\\testencoding.txt"); + Base64.InputStream b64is = new Base64.InputStream( fis, DECODE ); + java.io.FileOutputStream fos = new java.io.FileOutputStream("D:\\temp\\file.zip"); + int b; + while( (b=b64is.read()) >= 0 ) + fos.write( b ); + fos.close(); + b64is.close(); + + } // end test wagner's file + + } // end try + catch( Exception e) + { e.printStackTrace(); + } + } // end main + + +/* ******** E N C O D I N G M E T H O D S ******** */ + + + /** + * Encodes the first three bytes of array <var>threeBytes</var> + * and returns a four-byte array in Base64 notation. + * + * @param threeBytes the array to convert + * @return four byte array in Base64 notation. + * @since 1.3 + */ + private static byte[] encode3to4( byte[] threeBytes ) + { return encode3to4( threeBytes, 3 ); + } // end encodeToBytes + + + + /** + * Encodes up to the first three bytes of array <var>threeBytes</var> + * and returns a four-byte array in Base64 notation. + * The actual number of significant bytes in your array is + * given by <var>numSigBytes</var>. + * The array <var>threeBytes</var> needs only be as big as + * <var>numSigBytes</var>. + * + * @param threeBytes the array to convert + * @param numSigBytes the number of significant bytes in your array + * @return four byte array in Base64 notation. + * @since 1.3 + */ + private static byte[] encode3to4( byte[] threeBytes, int numSigBytes ) + { byte[] dest = new byte[4]; + encode3to4( threeBytes, 0, numSigBytes, dest, 0 ); + return dest; + } + + + + /** + * Encodes up to three bytes of the array <var>source</var> + * and writes the resulting four Base64 bytes to <var>destination</var>. + * The source and destination arrays can be manipulated + * anywhere along their length by specifying + * <var>srcOffset</var> and <var>destOffset</var>. + * This method does not check to make sure your arrays + * are large enough to accomodate <var>srcOffset</var> + 3 for + * the <var>source</var> array or <var>destOffset</var> + 4 for + * the <var>destination</var> array. + * The actual number of significant bytes in your array is + * given by <var>numSigBytes</var>. + * + * @param source the array to convert + * @param srcOffset the index where conversion begins + * @param numSigBytes the number of significant bytes in your array + * @param destination the array to hold the conversion + * @param destOffset the index where output will be put + * @return the <var>destination</var> array + * @since 1.3 + */ + private static byte[] encode3to4( + byte[] source, int srcOffset, int numSigBytes, + byte[] destination, int destOffset ) + { + // 1 2 3 + // 01234567890123456789012345678901 Bit position + // --------000000001111111122222222 Array position from threeBytes + // --------| || || || | Six bit groups to index ALPHABET + // >>18 >>12 >> 6 >> 0 Right shift necessary + // 0x3f 0x3f 0x3f Additional AND + + // Create buffer with zero-padding if there are only one or two + // significant bytes passed in the array. + // We have to shift left 24 in order to flush out the 1's that appear + // when Java treats a value as negative that is cast from a byte to an int. + int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24) >>> 8) : 0 ) + | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 ) + | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 ); + + switch( numSigBytes ) + { + case 3: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; + destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) & 0x3f ]; + return destination; + + case 2: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; + destination[ destOffset + 3 ] = EQUALS_SIGN; + return destination; + + case 1: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = EQUALS_SIGN; + destination[ destOffset + 3 ] = EQUALS_SIGN; + return destination; + + default: + return destination; + } // end switch + } // end encode3to4 + + /** + * Serializes an object and returns the Base64-encoded + * version of that serialized object. If the object + * cannot be serialized or there is another error, + * the method will return <tt>null</tt>. + * + * @param serializableObject The object to encode + * @return The Base64-encoded object + * @since 1.4 + */ + public static String encodeObject( java.io.Serializable serializableObject ) + { + return encodeObject( serializableObject, true ); + } // end encodeObject + + /** + * Serializes an object and returns the Base64-encoded + * version of that serialized object. If the object + * cannot be serialized or there is another error, + * the method will return <tt>null</tt>. + * + * @param serializableObject The object to encode + * @param breakLines Break lines at 80 characters or less. + * @return The Base64-encoded object + * @since 1.4 + */ + public static String encodeObject( java.io.Serializable serializableObject, boolean breakLines ) + { + java.io.ByteArrayOutputStream baos = null; + java.io.OutputStream b64os = null; + java.io.ObjectOutputStream oos = null; + + try + { + baos = new java.io.ByteArrayOutputStream(); + b64os = new Base64.OutputStream( baos, Base64.ENCODE, breakLines ); + oos = new java.io.ObjectOutputStream( b64os ); + + oos.writeObject( serializableObject ); + } // end try + catch( java.io.IOException e ) + { + e.printStackTrace(); + return null; + } // end catch + finally + { + try{ oos.close(); } catch( Exception e ){} + try{ b64os.close(); } catch( Exception e ){} + try{ baos.close(); } catch( Exception e ){} + } // end finally + + return new String( baos.toByteArray() ); + } // end encode + + + /** + * Encodes a byte array into Base64 notation. + * Equivalen to calling + * <code>encodeBytes( source, 0, source.length )</code> + * + * @param source The data to convert + * @since 1.4 + */ + public static String encodeBytes( byte[] source ) + { + return encodeBytes( source, true ); + } // end encodeBytes + + /** + * Encodes a byte array into Base64 notation. + * Equivalen to calling + * <code>encodeBytes( source, 0, source.length )</code> + * + * @param source The data to convert + * @param breakLines Break lines at 80 characters or less. + * @since 1.4 + */ + public static String encodeBytes( byte[] source, boolean breakLines ) + { + return encodeBytes( source, 0, source.length, breakLines ); + } // end encodeBytes + + + /** + * Encodes a byte array into Base64 notation. + * + * @param source The data to convert + * @param off Offset in array where conversion should begin + * @param len Length of data to convert + * @since 1.4 + */ + public static String encodeBytes( byte[] source, int off, int len ) + { + return encodeBytes( source, off, len, true ); + } // end encodeBytes + + + /** + * Encodes a byte array into Base64 notation. + * + * @param source The data to convert + * @param off Offset in array where conversion should begin + * @param len Length of data to convert + * @param breakLines Break lines at 80 characters or less. + * @since 1.4 + */ + public static String encodeBytes( byte[] source, int off, int len, boolean breakLines ) + { + int len43 = len * 4 / 3; + byte[] outBuff = new byte[ ( len43 ) // Main 4:3 + + ( (len % 3) > 0 ? 4 : 0 ) // Account for padding + + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; // New lines + int d = 0; + int e = 0; + int len2 = len - 2; + int lineLength = 0; + for( ; d < len2; d+=3, e+=4 ) + { + encode3to4( source, d+off, 3, outBuff, e ); + + lineLength += 4; + if( breakLines && lineLength == MAX_LINE_LENGTH ) + { + outBuff[e+4] = NEW_LINE; + e++; + lineLength = 0; + } // end if: end of line + } // en dfor: each piece of array + + if( d < len ) + { + encode3to4( source, d+off, len - d, outBuff, e ); + e += 4; + } // end if: some padding needed + + return new String( outBuff, 0, e ); + } // end encodeBytes + + + /** + * Encodes a string in Base64 notation with line breaks + * after every 75 Base64 characters. + * + * @param s the string to encode + * @return the encoded string + * @since 1.3 + */ + public static String encodeString( String s ) + { + return encodeString( s, true ); + } // end encodeString + + /** + * Encodes a string in Base64 notation with line breaks + * after every 75 Base64 characters. + * + * @param s the string to encode + * @param breakLines Break lines at 80 characters or less. + * @return the encoded string + * @since 1.3 + */ + public static String encodeString( String s, boolean breakLines ) + { + return encodeBytes( s.getBytes(), breakLines ); + } // end encodeString + + + + +/* ******** D E C O D I N G M E T H O D S ******** */ + + + /** + * Decodes the first four bytes of array <var>fourBytes</var> + * and returns an array up to three bytes long with the + * decoded values. + * + * @param fourBytes the array with Base64 content + * @return array with decoded values + * @since 1.3 + */ + private static byte[] decode4to3( byte[] fourBytes ) + { + byte[] outBuff1 = new byte[3]; + int count = decode4to3( fourBytes, 0, outBuff1, 0 ); + byte[] outBuff2 = new byte[ count ]; + + for( int i = 0; i < count; i++ ) + outBuff2[i] = outBuff1[i]; + + return outBuff2; + } + + + + + /** + * Decodes four bytes from array <var>source</var> + * and writes the resulting bytes (up to three of them) + * to <var>destination</var>. + * The source and destination arrays can be manipulated + * anywhere along their length by specifying + * <var>srcOffset</var> and <var>destOffset</var>. + * This method does not check to make sure your arrays + * are large enough to accomodate <var>srcOffset</var> + 4 for + * the <var>source</var> array or <var>destOffset</var> + 3 for + * the <var>destination</var> array. + * This method returns the actual number of bytes that + * were converted from the Base64 encoding. + * + * + * @param source the array to convert + * @param srcOffset the index where conversion begins + * @param destination the array to hold the conversion + * @param destOffset the index where output will be put + * @return the number of decoded bytes converted + * @since 1.3 + */ + private static int decode4to3( byte[] source, int srcOffset, byte[] destination, int destOffset ) + { + // Example: Dk== + if( source[ srcOffset + 2] == EQUALS_SIGN ) + { + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 ); + + destination[ destOffset ] = (byte)( outBuff >>> 16 ); + return 1; + } + + // Example: DkL= + else if( source[ srcOffset + 3 ] == EQUALS_SIGN ) + { + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) + // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) + | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 ); + + destination[ destOffset ] = (byte)( outBuff >>> 16 ); + destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 ); + return 2; + } + + // Example: DkLE + else + { + try{ + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) + // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ) + // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) + | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6) + | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) ); + + + destination[ destOffset ] = (byte)( outBuff >> 16 ); + destination[ destOffset + 1 ] = (byte)( outBuff >> 8 ); + destination[ destOffset + 2 ] = (byte)( outBuff ); + + return 3; + }catch( Exception e){ + System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) ); + System.out.println(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) ); + System.out.println(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) ); + System.out.println(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) ); + return -1; + } //e nd catch + } + } // end decodeToBytes + + + + /** + * Decodes data from Base64 notation. + * + * @param s the string to decode + * @return the decoded data + * @since 1.4 + */ + public static byte[] decode( String s ) + { + byte[] bytes = s.getBytes(); + return decode( bytes, 0, bytes.length ); + } // end decode + + + /** + * Decodes data from Base64 notation and + * returns it as a string. + * Equivlaent to calling + * <code>new String( decode( s ) )</code> + * + * @param s the strind to decode + * @return The data as a string + * @since 1.4 + */ + public static String decodeToString( String s ) + { return new String( decode( s ) ); + } // end decodeToString + + + /** + * Attempts to decode Base64 data and deserialize a Java + * Object within. Returns <tt>null if there was an error. + * + * @param encodedObject The Base64 data to decode + * @return The decoded and deserialized object + * @since 1.4 + */ + public static Object decodeToObject( String encodedObject ) + { + byte[] objBytes = decode( encodedObject ); + + java.io.ByteArrayInputStream bais = null; + java.io.ObjectInputStream ois = null; + + try + { + bais = new java.io.ByteArrayInputStream( objBytes ); + ois = new java.io.ObjectInputStream( bais ); + + return ois.readObject(); + } // end try + catch( java.io.IOException e ) + { + e.printStackTrace(); + return null; + } // end catch + catch( java.lang.ClassNotFoundException e ) + { + e.printStackTrace(); + return null; + } // end catch + finally + { + try{ bais.close(); } catch( Exception e ){} + try{ ois.close(); } catch( Exception e ){} + } // end finally + } // end decodeObject + + + /** + * Decodes Base64 content in byte array format and returns + * the decoded byte array. + * + * @param source The Base64 encoded data + * @param off The offset of where to begin decoding + * @param len The length of characters to decode + * @return decoded data + * @since 1.3 + */ + public static byte[] decode( byte[] source, int off, int len ) + { + int len34 = len * 3 / 4; + byte[] outBuff = new byte[ len34 ]; // Upper limit on size of output + int outBuffPosn = 0; + + byte[] b4 = new byte[4]; + int b4Posn = 0; + int i = 0; + byte sbiCrop = 0; + byte sbiDecode = 0; + for( i = 0; i < len; i++ ) + { + sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits + sbiDecode = DECODABET[ sbiCrop ]; + + if( sbiDecode >= WHITE_SPACE_ENC ) // White space, Equals sign or better + { + if( sbiDecode >= EQUALS_SIGN_ENC ) + { + b4[ b4Posn++ ] = sbiCrop; + if( b4Posn > 3 ) + { + outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn ); + b4Posn = 0; + + // If that was the equals sign, break out of 'for' loop + if( sbiCrop == EQUALS_SIGN ) + break; + } // end if: quartet built + + } // end if: equals sign or better + + } // end if: white space, equals sign or better + else + { + System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" ); + return null; + } // end else: + } // each input character + + byte[] out = new byte[ outBuffPosn ]; + System.arraycopy( outBuff, 0, out, 0, outBuffPosn ); + return out; + } // end decode + + + + + /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */ + + + + /** + * A {@link Base64#InputStream} will read data from another + * {@link java.io.InputStream}, given in the constructor, + * and encode/decode to/from Base64 notation on the fly. + * + * @see Base64 + * @see java.io.FilterInputStream + * @since 1.3 + */ + public static class InputStream extends java.io.FilterInputStream + { + private boolean encode; // Encoding or decoding + private int position; // Current position in the buffer + private byte[] buffer; // Small buffer holding converted data + private int bufferLength; // Length of buffer (3 or 4) + private int numSigBytes; // Number of meaningful bytes in the buffer + private int lineLength; + private boolean breakLines; // Break lines at less than 80 characters + + + /** + * Constructs a {@link Base64#InputStream} in DECODE mode. + * + * @param in the {@link java.io.InputStream} from which to read data. + * @since 1.3 + */ + public InputStream( java.io.InputStream in ) + { + this( in, Base64.DECODE ); + } // end constructor + + + /** + * Constructs a {@link Base64#InputStream} in + * either ENCODE or DECODE mode. + * + * @param in the {@link java.io.InputStream} from which to read data. + * @param encode Conversion direction + * @see Base64#ENCODE + * @see Base64#DECODE + * @since 1.3 + */ + public InputStream( java.io.InputStream in, boolean encode ) + { + this( in, encode, true ); + } // end constructor + + + /** + * Constructs a {@link Base64#InputStream} in + * either ENCODE or DECODE mode. + * + * @param in the {@link java.io.InputStream} from which to read data. + * @param encode Conversion direction + * @param breakLines Break lines at less than 80 characters. + * @see Base64#ENCODE + * @see Base64#DECODE + * @since 1.3 + */ + public InputStream( java.io.InputStream in, boolean encode, boolean breakLines ) + { + super( in ); + this.breakLines = breakLines; + this.encode = encode; + this.bufferLength = encode ? 4 : 3; + this.buffer = new byte[ bufferLength ]; + this.position = -1; + this.lineLength = 0; + } // end constructor + + /** + * Reads enough of the input stream to convert + * to/from Base64 and returns the next byte. + * + * @return next byte + * @since 1.3 + */ + public int read() throws java.io.IOException + { + // Do we need to get data? + if( position < 0 ) + { + if( encode ) + { + byte[] b3 = new byte[3]; + int numBinaryBytes = 0; + for( int i = 0; i < 3; i++ ) + { + try + { + int b = in.read(); + + // If end of stream, b is -1. + if( b >= 0 ) + { + b3[i] = (byte)b; + numBinaryBytes++; + } // end if: not end of stream + + } // end try: read + catch( java.io.IOException e ) + { + // Only a problem if we got no data at all. + if( i == 0 ) + throw e; + + } // end catch + } // end for: each needed input byte + + if( numBinaryBytes > 0 ) + { + encode3to4( b3, 0, numBinaryBytes, buffer, 0 ); + position = 0; + numSigBytes = 4; + } // end if: got data + else + { + return -1; + } // end else + } // end if: encoding + + // Else decoding + else + { + byte[] b4 = new byte[4]; + int i = 0; + for( i = 0; i < 4; i++ ) + { + // Read four "meaningful" bytes: + int b = 0; + do{ b = in.read(); } + while( b >= 0 && DECODABET[ b & 0x7f ] <= WHITE_SPACE_ENC ); + + if( b < 0 ) + break; // Reads a -1 if end of stream + + b4[i] = (byte)b; + } // end for: each needed input byte + + if( i == 4 ) + { + numSigBytes = decode4to3( b4, 0, buffer, 0 ); + position = 0; + } // end if: got four characters + else if( i == 0 ){ + return -1; + } // end else if: also padded correctly + else + { + // Must have broken out from above. + throw new java.io.IOException( "Improperly padded Base64 input." ); + } // end + + } // end else: decode + } // end else: get data + + // Got data? + if( position >= 0 ) + { + // End of relevant data? + if( /*!encode &&*/ position >= numSigBytes ) + return -1; + + if( encode && breakLines && lineLength >= MAX_LINE_LENGTH ) + { + lineLength = 0; + return '\n'; + } // end if + else + { + lineLength++; // This isn't important when decoding + // but throwing an extra "if" seems + // just as wasteful. + + int b = buffer[ position++ ]; + + if( position >= bufferLength ) + position = -1; + + return b & 0xFF; // This is how you "cast" a byte that's + // intended to be unsigned. + } // end else + } // end if: position >= 0 + + // Else error + else + { + // When JDK1.4 is more accepted, use an assertion here. + throw new java.io.IOException( "Error in Base64 code reading stream." ); + } // end else + } // end read + + + /** + * Calls {@link #read} repeatedly until the end of stream + * is reached or <var>len</var> bytes are read. + * Returns number of bytes read into array or -1 if + * end of stream is encountered. + * + * @param dest array to hold values + * @param off offset for array + * @param len max number of bytes to read into array + * @return bytes read into array or -1 if end of stream is encountered. + * @since 1.3 + */ + public int read( byte[] dest, int off, int len ) throws java.io.IOException + { + int i; + int b; + for( i = 0; i < len; i++ ) + { + b = read(); + + //if( b < 0 && i == 0 ) + // return -1; + + if( b >= 0 ) + dest[off + i] = (byte)b; + else if( i == 0 ) + return -1; + else + break; // Out of 'for' loop + } // end for: each byte read + return i; + } // end read + + } // end inner class InputStream + + + + + + + /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */ + + + + /** + * A {@link Base64#OutputStream} will write data to another + * {@link java.io.OutputStream}, given in the constructor, + * and encode/decode to/from Base64 notation on the fly. + * + * @see Base64 + * @see java.io.FilterOutputStream + * @since 1.3 + */ + public static class OutputStream extends java.io.FilterOutputStream + { + private boolean encode; + private int position; + private byte[] buffer; + private int bufferLength; + private int lineLength; + private boolean breakLines; + + + /** + * Constructs a {@link Base64#OutputStream} in ENCODE mode. + * + * @param out the {@link java.io.OutputStream} to which data will be written. + * @since 1.3 + */ + public OutputStream( java.io.OutputStream out ) + { + this( out, Base64.ENCODE ); + } // end constructor + + + /** + * Constructs a {@link Base64#OutputStream} in + * either ENCODE or DECODE mode. + * + * @param out the {@link java.io.OutputStream} to which data will be written. + * @param encode Conversion direction + * @see Base64#ENCODE + * @see Base64#DECODE + * @since 1.3 + */ + public OutputStream( java.io.OutputStream out, boolean encode ) + { + this( out, encode, true ); + } // end constructor + + + /** + * Constructs a {@link Base64#OutputStream} in + * either ENCODE or DECODE mode. + * + * @param out the {@link java.io.OutputStream} to which data will be written. + * @param encode Conversion direction + * @param breakLines Break lines to be less than 80 characters. + * @see Base64#ENCODE + * @see Base64#DECODE + * @since 1.3 + */ + public OutputStream( java.io.OutputStream out, boolean encode, boolean breakLines ) + { + super( out ); + this.breakLines = breakLines; + this.encode = encode; + this.bufferLength = encode ? 3 : 4; + this.buffer = new byte[ bufferLength ]; + this.position = 0; + this.lineLength = 0; + } // end constructor + + + /** + * Writes the byte to the output stream after + * converting to/from Base64 notation. + * When encoding, bytes are buffered three + * at a time before the output stream actually + * gets a write() call. + * When decoding, bytes are buffered four + * at a time. + * + * @param theByte the byte to write + * @since 1.3 + */ + public void write(int theByte) throws java.io.IOException + { + if( encode ) + { + buffer[ position++ ] = (byte)theByte; + if( position >= bufferLength ) // Enough to encode. + { + out.write( Base64.encode3to4( buffer, bufferLength ) ); + + lineLength += 4; + if( breakLines && lineLength >= MAX_LINE_LENGTH ) + { + out.write( NEW_LINE ); + lineLength = 0; + } // end if: end of line + + position = 0; + } // end if: enough to output + } // end if: encoding + + // Else, Decoding + else + { + // Meaningful Base64 character? + if( DECODABET[ theByte & 0x7f ] > WHITE_SPACE_ENC ) + { + buffer[ position++ ] = (byte)theByte; + if( position >= bufferLength ) // Enough to output. + { + out.write( Base64.decode4to3( buffer ) ); + position = 0; + } // end if: enough to output + } // end if: meaningful base64 character + else if( DECODABET[ theByte & 0x7f ] != WHITE_SPACE_ENC ) + { + throw new java.io.IOException( "Invalid character in Base64 data." ); + } // end else: not white space either + } // end else: decoding + } // end write + + + + /** + * Calls {@link #write} repeatedly until <var>len</var> + * bytes are written. + * + * @param theBytes array from which to read bytes + * @param off offset for array + * @param len max number of bytes to read into array + * @since 1.3 + */ + public void write( byte[] theBytes, int off, int len ) throws java.io.IOException + { + for( int i = 0; i < len; i++ ) + { + write( theBytes[ off + i ] ); + } // end for: each byte written + + } // end write + + + /** + * Appropriately pads Base64 notation when encoding + * or throws an exception if Base64 input is not + * properly padded when decoding. + * + * @since 1.3 + */ + public void flush() throws java.io.IOException + { + super.flush(); + + if( position > 0 ) + { + if( encode ) + { + out.write( Base64.encode3to4( buffer, position ) ); + } // end if: encoding + else + { + throw new java.io.IOException( "Base64 input not properly padded." ); + } // end else: decoding + } // end if: buffer partially full + + out.flush(); + } // end flush + + + /** + * Flushes and closes stream. + * + * @since 1.3 + */ + public void close() throws java.io.IOException + { + super.close(); + //this.flush(); + + out.close(); + + buffer = null; + out = null; + } // end close + + } // end inner class OutputStream + + +} // end class Base64 diff --git a/bindings/corba/java/src/org/crosswire/web/i18n/ContextStart.java.notyet b/bindings/corba/java/src/org/crosswire/web/i18n/ContextStart.java.notyet new file mode 100644 index 0000000..f6823e2 --- /dev/null +++ b/bindings/corba/java/src/org/crosswire/web/i18n/ContextStart.java.notyet @@ -0,0 +1,10 @@ +package org.crosswire.web.i18n; + +import javax.servlet.jsp.tagext.*; + +public class ContextStart extends TagSupport { + + public ContextStart() { + } + +} diff --git a/bindings/corba/java/src/org/crosswire/web/i18n/TranslateTag.java b/bindings/corba/java/src/org/crosswire/web/i18n/TranslateTag.java new file mode 100644 index 0000000..1ed20a5 --- /dev/null +++ b/bindings/corba/java/src/org/crosswire/web/i18n/TranslateTag.java @@ -0,0 +1,87 @@ +package org.crosswire.web.i18n; + +import javax.servlet.jsp.tagext.BodyTagSupport; +import javax.servlet.jsp.tagext.BodyContent; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspTagException; +//import javax.servlet.jsp.JspWriter; +import javax.servlet.http.HttpSession; +//import java.util.HashMap; +//import java.io.StringWriter; +import java.util.Locale; +import java.util.ResourceBundle; +import java.util.MissingResourceException; +import java.util.Properties; +import java.io.FileInputStream; +import java.io.FileOutputStream; + + +public class TranslateTag extends BodyTagSupport { + + private String _key=null; + private ResourceBundle _bundle=null; + private String _lang=null; + + /* Uses code from GNU gettext for translation */ + /* which is covered by the LGPL */ + public String doTranslate(ResourceBundle catalog, String msgid) throws JspTagException { + String hashkey = "" + msgid.hashCode(); + try { + if (catalog != null) { + String result = (String)catalog.getObject(hashkey); + if (result != null) + return result; + } + } catch (MissingResourceException e) { + // want to add the msgid to the properties file + Properties props = new Properties(); + + try { + FileInputStream tbtin = new FileInputStream(pageContext.getServletContext().getRealPath("/WEB-INF/classes/tbt.properties")); + props.load(tbtin); + tbtin.close(); + + props.put(hashkey, msgid); + + FileOutputStream tbtout = new FileOutputStream(pageContext.getServletContext().getRealPath("/WEB-INF/classes/tbt.properties")); + props.store(tbtout, null); + tbtout.close(); + + } + catch(java.io.IOException e2) + { + throw new JspTagException("IO Error: " + e2.getMessage()); + } + + } + return msgid; + } + + public int doAfterBody() throws JspTagException { + BodyContent bc = getBodyContent(); + _key = bc.getString(); + HttpSession session = pageContext.getSession(); + Locale locale = (Locale) session.getAttribute("TranslateLocale"); + + if ((_bundle == null) || (_lang != locale.toString())) { + _lang = locale.toString(); + _bundle = ResourceBundle.getBundle("tbt", locale); + } + + return 0; + } + + public int doEndTag() throws JspException { + try + { + pageContext.getOut().write(doTranslate(_bundle, _key)); + } + catch(java.io.IOException e) + { + throw new JspTagException("IO Error: " + e.getMessage()); + } + return EVAL_PAGE; + } + + +} diff --git a/bindings/corba/java/swordorb.jpx b/bindings/corba/java/swordorb.jpx new file mode 100644 index 0000000..34642c6 --- /dev/null +++ b/bindings/corba/java/swordorb.jpx @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--JBuilder XML Project--> +<project> + <property category="debug.0" name="SmartStepRedefineClasses" value="0"/> + <property category="debug.0" name="SmartStepSkipStaticInitializers" value="0"/> + <property category="debug.0" name="SmartStepSkipSynthetics" value="0"/> + <property category="runtime" name="DefaultConfiguration" value="-1"/> + <property category="runtime.0" name="BuildTargetOnRun" value="com.borland.jbuilder.build.ProjectBuilder$ProjectBuildAction;make"/> + <property category="runtime.0" name="ConfigurationName" value="Untitled Runtime Configuration1"/> + <property category="runtime.0" name="RunnableType" value="com.borland.jbuilder.runtime.ApplicationRunner"/> + <property category="runtime.0" name="application.class" value="org.crosswire.sword.orb.SwordOrb"/> + <property category="serverservices" name="single.server.name" value="Tomcat 4.0"/> + <property category="sys" name="AuthorLabel" value="@author"/> + <property category="sys" name="BackupPath" value="bak"/> + <property category="sys" name="CheckStable" value="1"/> + <property category="sys" name="Company" value=""/> + <property category="sys" name="CompanyLabel" value="Company:"/> + <property category="sys" name="Copyright" value="Copyright (c) 2003"/> + <property category="sys" name="CopyrightLabel" value="Copyright:"/> + <property category="sys" name="DefaultPath" value="src"/> + <property category="sys" name="Description" value=""/> + <property category="sys" name="DescriptionLabel" value="Description:"/> + <property category="sys" name="DocPath" value="doc"/> + <property category="sys" name="ExcludeClassEnabled" value="0"/> + <property category="sys" name="IncludeTestPath" value="1"/> + <property category="sys" name="InstanceVisibility" value="2"/> + <property category="sys" name="JDK" value="java 1.3.1-b24"/> + <property category="sys" name="LastTag" value="0"/> + <property category="sys" name="Libraries" value="tomcat-common"/> + <property category="sys" name="MakeStable" value="0"/> + <property category="sys" name="OutPath" value="classes"/> + <property category="sys" name="SourcePath" value="src;test"/> + <property category="sys" name="TestPath" value="test"/> + <property category="sys" name="Title" value=""/> + <property category="sys" name="TitleLabel" value="Title:"/> + <property category="sys" name="Version" value="1.0"/> + <property category="sys" name="VersionLabel" value="@version"/> + <property category="sys" name="WorkingDirectory" value="."/> + <node name="org.crosswire.sword.orb" type="Package"/> + <file path="../swordorb.idl"/> +</project> diff --git a/bindings/corba/java/swordorb.jpx.local b/bindings/corba/java/swordorb.jpx.local new file mode 100644 index 0000000..3303b21 --- /dev/null +++ b/bindings/corba/java/swordorb.jpx.local @@ -0,0 +1,10 @@ +debug.Breakpoints.1[0]=1 023 hellomodule.HelloClient32 src/hellomodule/HelloClient.java1 81 10 1 10 1 10 1 0 -1 +debug.Breakpoints.2[0]=1 032 org.crosswire.sword.orb.SwordOrb41 src/org/crosswire/sword/orb/SwordOrb.java2 991 10 1 10 1 10 1 0 -1 +debug.NoTracingClasses.1[0]=16 java.lang.Object1 1 -1 +debug.NoTracingClasses.2[0]=21 java.lang.ClassLoader1 1 -1 +debug.NoTracingClasses.3[0]=16 java.lang.String1 1 -1 +debug.SplitThreadsAndDataView[0]=0 +import.optimize.legacyPropertiesRead[0]=1 +sys.Author[0]= +sys.DefaultPackage[0]=org.crosswire.sword.orb +wizard.package.package_history.1[0]=helloworld diff --git a/bindings/corba/java/testclient b/bindings/corba/java/testclient new file mode 100755 index 0000000..c7a623f --- /dev/null +++ b/bindings/corba/java/testclient @@ -0,0 +1,6 @@ +#!/bin/sh +TOMCAT_HOME=/opt/tomcat +#SERVLET_LIB=${TOMCAT_HOME}/common/lib/servlet-api.jar +SERVLET_LIB=${TOMCAT_HOME}/lib/servlet-api.jar +TOMCAT_HOME=/usr/local/tomcat +java -cp $SERVLET_LIB:classes org.crosswire.sword.orb.SwordOrb $* diff --git a/bindings/corba/orbitcpp/Makefile b/bindings/corba/orbitcpp/Makefile new file mode 100644 index 0000000..c7a48a7 --- /dev/null +++ b/bindings/corba/orbitcpp/Makefile @@ -0,0 +1,66 @@ +all: server testclient + +PREFIX = $(shell grep ^prefix ../../../Makefile|cut -f3 -d' ') + +#sword stuff +CXXFLAGS += $(shell PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig pkg-config --cflags sword) +CFLAGS += $(shell PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig pkg-config --cflags sword) +LIBS += $(shell PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig pkg-config --libs sword) + +#orbit stuff +CFLAGS += $(shell orbit2-config --cflags) +CXXFLAGS += $(shell orbit2-config --cflags) +LIBS += $(shell orbit2-config --libs) + +#orbitcpp stuff-- this is silly. Is there really NOT a way to derive this? +CFLAGS += -I/usr/include/orbitcpp-2.0 +CXXFLAGS += -I/usr/include/orbitcpp-2.0 +LIBS += -L/usr/lib64 -lORBit-2-cpp + +#comment out for release +#CXXFLAGS += -g -O0 +#CFLAGS += -g -O0 +#LDFLAGS += -g -O0 +#----------------------------------------------------------------------------- + + +server: swordorb-common.o server.cpp swordorb-impl.o swordorb-cpp.o swordorb-cpp-common.o swordorb-stubs.o swordorb-cpp-stubs.o swordorb-cpp-skels.o swordorb-skels.o swordorb-cpp.o + $(CXX) $(CXXFLAGS) -I. -o server server.cpp swordorb-impl.o swordorb-common.o swordorb-cpp-common.o swordorb-stubs.o swordorb-cpp-stubs.o swordorb-cpp-skels.o swordorb-skels.o $(LIBS) + +testclient: testclient.cpp swordorb-impl.cpp swordorb-common.o swordorb-cpp-common.o swordorb-stubs.o swordorb-cpp-stubs.o swordorb-skels.o swordorb-cpp-skels.o + $(CXX) $(CXXFLAGS) -I. -o testclient testclient.cpp swordorb-common.o swordorb-cpp-common.o swordorb-stubs.o swordorb-cpp-stubs.o swordorb-skels.o swordorb-cpp-skels.o $(LIBS) + +swordorb-cpp.o: swordorb-cpp.cc + $(CXX) $(CXXFLAGS) -I. -c swordorb-cpp.cc + +swordorb-impl.o: swordorb-impl.cpp + $(CXX) $(CXXFLAGS) -I. -c swordorb-impl.cpp + +swordorb-common.o: swordorb-common.c + $(CC) $(CFLAGS) -I. -c swordorb-common.c + +swordorb-common.c: ./../swordorb.idl + orbit-idl-2 -l c ./../swordorb.idl + orbit-idl-2 -l cpp ./../swordorb.idl + +swordorb-cpp-common.o: swordorb-cpp-common.cc + $(CXX) $(CXXFLAGS) -I. -c swordorb-cpp-common.cc + +swordorb-stubs.o: swordorb-stubs.c + $(CC) $(CFLAGS) -I. -c swordorb-stubs.c + +swordorb-cpp-stubs.o: swordorb-cpp-stubs.cc + $(CXX) $(CXXFLAGS) -I. -c swordorb-cpp-stubs.cc + +swordorb-skels.o: swordorb-skels.c + $(CC) $(CFLAGS) -I. -c swordorb-skels.c + +swordorb-cpp-skels.o: swordorb-cpp-skels.cc + $(CXX) $(CXXFLAGS) -I. -c swordorb-cpp-skels.cc + +clean: + rm -f *.h *.cc *.o *.c server testclient + +install: + mkdir -p $(PREFIX)/bin + cp -f server $(PREFIX)/bin/swordorbserver diff --git a/bindings/corba/orbitcpp/Makefile.am b/bindings/corba/orbitcpp/Makefile.am new file mode 100644 index 0000000..2d36ddf --- /dev/null +++ b/bindings/corba/orbitcpp/Makefile.am @@ -0,0 +1,40 @@ +bin_PROGRAMS = swordorbserver + +noinst_PROGRAMS = testclient + +swordorbserver_SOURCES = server.cpp +swordorbserver_SOURCES += swordorb-common.c +swordorbserver_SOURCES += swordorb-impl.cpp +swordorbserver_SOURCES += swordorb-cpp-common.cc +swordorbserver_SOURCES += swordorb-stubs.c +swordorbserver_SOURCES += swordorb-cpp-stubs.cc +swordorbserver_SOURCES += swordorb-skels.c +swordorbserver_SOURCES += swordorb-cpp-skels.cc + +swordorbserver_CFLAGS = $(SWORD_CFLAGS) $(ORBIT_CFLAGS) +swordorbserver_CXXFLAGS = $(SWORD_CFLAGS) $(ORBIT_CXXFLAGS) +swordorbserver_LDADD = $(SWORD_LIBS) $(ORBIT_LIBS) + +testclient_SOURCES = testclient.cpp +testclient_SOURCES += swordorb-common.c +testclient_SOURCES += swordorb-impl.cpp +testclient_SOURCES += swordorb-cpp-common.cc +testclient_SOURCES += swordorb-stubs.c +testclient_SOURCES += swordorb-cpp-stubs.cc +testclient_SOURCES += swordorb-skels.c +testclient_SOURCES += swordorb-cpp-skels.cc + +testclient_CFLAGS = $(SWORD_CFLAGS) $(ORBIT_CFLAGS) +testclient_CXXFLAGS = $(SWORD_CFLAGS) $(ORBIT_CXXFLAGS) +testclient_LDADD = $(SWORD_LIBS) $(ORBIT_LIBS) + +BUILT_SOURCES = swordorb-common.c + +swordorb-common.c: $(top_srcdir)/corba/swordorb.idl + orbit-idl-2 -l c $(top_srcdir)/corba/swordorb.idl + orbit-idl-2 -l cpp $(top_srcdir)/corba/swordorb.idl + +clean: + rm -f *.h *.cc *.o *.c server testclient + + diff --git a/bindings/corba/orbitcpp/server.cpp b/bindings/corba/orbitcpp/server.cpp new file mode 100644 index 0000000..83b1864 --- /dev/null +++ b/bindings/corba/orbitcpp/server.cpp @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +#include "swordorb-impl.hpp" +#include <iostream> +#include <swmgr.h> +#include "webmgr.hpp" + +SWConfig *sysConf = 0; +WebMgr *swordMgr = 0; + +class CleanStatics { +public: + CleanStatics() {} + ~CleanStatics() { + if (swordMgr) + delete swordMgr; + + if (sysConf) + delete sysConf; + } +} cleanStatics; + + + + +int main (int argc, char* argv[]) { + try { + + for (int i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-sysConf")) { + if ((i+1) < argc) + sysConf = new SWConfig(argv[i+1]); + } + } + + swordMgr = new WebMgr(sysConf); + + // Initialize the CORBA orb + CORBA::ORB_ptr orb = CORBA::ORB_init (argc, argv); + + // Get the root POA + CORBA::Object_var pfobj = orb->resolve_initial_references("RootPOA"); + + PortableServer::POA_var rootPOA = + PortableServer::POA::_narrow(pfobj); + + // Activate the root POA's manager + PortableServer::POAManager_var mgr = rootPOA->the_POAManager(); + + mgr->activate(); + + // Create a Servant and explicitly create a CORBA object + swordorb::SWMgr_impl servant(swordMgr); + CORBA::Object_var object = servant._this(); + + // Here we get the IOR for the Hello server object. + // Our "client" will use the IOR to find the object to connect to + CORBA::String_var ref = orb->object_to_string( object ); + + // print out the IOR + std::cout << ref << std::endl; + + // run the server event loop + orb->run(); + } + catch(const CORBA::Exception& ex) + { + std::cout << "Exception caught." << std::endl; + } + +} diff --git a/bindings/corba/orbitcpp/swordorb-impl.cpp b/bindings/corba/orbitcpp/swordorb-impl.cpp new file mode 100644 index 0000000..29b5b5e --- /dev/null +++ b/bindings/corba/orbitcpp/swordorb-impl.cpp @@ -0,0 +1,357 @@ +#include "swordorb-impl.hpp" +#include <iostream> +#include <swmgr.h> +#include <versekey.h> +#include <treekeyidx.h> +#include <swbuf.h> +#include <localemgr.h> +#include <vector> + +/* +char* swordorb::SWModule_impl::helloWorld(const char* greeting) throw(CORBA::SystemException) { + std::cout << "Server: Greeting was \"" << greeting << "\"" << std::endl; + return CORBA::string_dup("Hello client, from server!"); +} +*/ + +using sword::VerseKey; +using sword::SWBuf; +using sword::TreeKeyIdx; + +namespace swordorb { + +sword::RawText NULLMod("/dev/null", SWNULL, SWNULL); + +ModInfoList *SWMgr_impl::getModInfoList() throw(CORBA::SystemException) { + + ModInfoList *milist = new ModInfoList; + sword::SWModule *module = 0; + int size = 0; + for (sword::ModMap::iterator it = delegate->Modules.begin(); it != delegate->Modules.end(); it++) { + if ((!(it->second->getConfigEntry("CipherKey"))) || (*(it->second->getConfigEntry("CipherKey")))) + size++; + } + milist->length(size); + int i = 0; + for (sword::ModMap::iterator it = delegate->Modules.begin(); it != delegate->Modules.end(); it++) { + module = it->second; + if ((!(module->getConfigEntry("CipherKey"))) || (*(module->getConfigEntry("CipherKey")))) { + SWBuf type = module->Type(); + SWBuf cat = module->getConfigEntry("Category"); + if (cat.length() > 0) + type = cat; + (*milist)[i].name = CORBA::string_dup(module->Name()); + (*milist)[i].description = CORBA::string_dup(module->Description()); + (*milist)[i].category = CORBA::string_dup(type.c_str()); + (*milist)[i++].language = CORBA::string_dup(module->Lang()); + } + } + return milist; +} + + + +SWModule_ptr SWMgr_impl::getModuleByName(const char *name) throw(CORBA::SystemException) { + SWModuleMap::iterator it; + SWModule_ptr retVal; + sword::SWModule *mod = delegate->Modules[name]; + it = moduleImpls.find((mod)?name:SWNULL); + if (it == moduleImpls.end()) { + moduleImpls[(mod)?name:SWNULL] = new SWModule_impl((mod)?mod:&NULLMod); + it = moduleImpls.find((mod)?name:SWNULL); + } + if (it != moduleImpls.end()) { + retVal = it->second->_this(); + } + return ::swordorb::SWModule::_duplicate(retVal); +} + + +StringList *SWMgr_impl::getGlobalOptions() throw(CORBA::SystemException) { + sword::StringList options = delegate->getGlobalOptions(); + StringList *retVal = new StringList; + int count = 0; + for (sword::StringList::iterator it = options.begin(); it != options.end(); it++) { + count++; + } + retVal->length(count); + count = 0; + for (sword::StringList::iterator it = options.begin(); it != options.end(); it++) { + (*retVal)[count++] = CORBA::string_dup(it->c_str()); + } + return retVal; +} + + +StringList *SWMgr_impl::getGlobalOptionValues(const char *option) throw(CORBA::SystemException) { + sword::StringList options = delegate->getGlobalOptionValues(option); + StringList *retVal = new StringList; + int count = 0; + for (sword::StringList::iterator it = options.begin(); it != options.end(); it++) { + count++; + } + retVal->length(count); + count = 0; + for (sword::StringList::iterator it = options.begin(); it != options.end(); it++) { + (*retVal)[count++] = CORBA::string_dup(it->c_str()); + } + return retVal; +} + +void SWMgr_impl::terminate() throw(CORBA::SystemException) { + exit(0); +} + + +CORBA::Boolean SWMgr_impl::testConnection() throw(CORBA::SystemException) { + return true; +} + +void SWMgr_impl::setJavascript(CORBA::Boolean val) throw(CORBA::SystemException) { + delegate->setJavascript(val); +} + +char *SWMgr_impl::filterText(const char *filterName, const char *text) throw(CORBA::SystemException) { + SWBuf buf = text; + delegate->setGlobalOption("Greek Accents", "Off"); + char errStatus = delegate->filterText(filterName, buf); + return CORBA::string_dup((char *)buf.c_str()); +} + +char *SWModule_impl::getCategory() throw(CORBA::SystemException) { + SWBuf type = delegate->Type(); + SWBuf cat = delegate->getConfigEntry("Category"); + if (cat.length() > 0) + type = cat; + return CORBA::string_dup((char *)type.c_str()); +} + + +StringList *SWModule_impl::parseKeyList(const char *keyText) throw(CORBA::SystemException) { + sword::VerseKey *parser = dynamic_cast<VerseKey *>(delegate->getKey()); + StringList *retVal = new StringList; + if (parser) { + sword::ListKey result; + result = parser->ParseVerseList(keyText, *parser, true); + int count = 0; + for (result = sword::TOP; !result.Error(); result++) { + count++; + } + retVal->length(count); + count = 0; + for (result = sword::TOP; !result.Error(); result++) { + (*retVal)[count++] = CORBA::string_dup((const char *)result); + } + } + else { + retVal->length(1); + (*retVal)[0] = CORBA::string_dup(keyText); + } + + return retVal; +} + + +SearchHitList *SWModule_impl::search(const char *istr, SearchType searchType, CORBA::Long flags, const char *scope) throw(CORBA::SystemException) { + int stype = 2; + sword::ListKey lscope; + sword::VerseKey parser; + if (searchType == REGEX) stype = 0; + if (searchType == PHRASE) stype = -1; + if (searchType == MULTIWORD) stype = -2; + if (searchType == ENTRYATTR) stype = -3; + if (searchType == LUCENE) stype = -4; + sword::ListKey result; + + if ((scope) && (strlen(scope)) > 0) { + lscope = parser.ParseVerseList(scope, parser, true); + result = delegate->Search(istr, stype, flags, &lscope); + } + else result = delegate->Search(istr, stype, flags); + + SearchHitList *retVal = new SearchHitList; + int count = 0; + for (result = sword::TOP; !result.Error(); result++) count++; + retVal->length(count); + int i = 0; + + // if we're sorted by score, let's re-sort by verse, because Java can always re-sort by score + result = sword::TOP; + if ((count) && (long)result.getElement()->userData) + result.sort(); + + for (result = sword::TOP; !result.Error(); result++) { + (*retVal)[i].modName = CORBA::string_dup(delegate->Name()); + (*retVal)[i].key = CORBA::string_dup((const char *)result); + (*retVal)[i++].score = (long)result.getElement()->userData; + } + + return retVal; +} + + +StringList *SWModule_impl::getEntryAttribute(const char *level1, const char *level2, const char *level3, CORBA::Boolean filtered) throw(CORBA::SystemException) { + delegate->RenderText(); // force parse + std::vector<SWBuf> results; + StringList *retVal = new StringList; + int count = 0; + + sword::AttributeTypeList &entryAttribs = delegate->getEntryAttributes(); + sword::AttributeTypeList::iterator i1Start, i1End; + sword::AttributeList::iterator i2Start, i2End; + sword::AttributeValue::iterator i3Start, i3End; + + if ((level1) && (*level1)) { + i1Start = entryAttribs.find(level1); + i1End = i1Start; + if (i1End != entryAttribs.end()) + i1End++; + } + else { + i1Start = entryAttribs.begin(); + i1End = entryAttribs.end(); + } + for (;i1Start != i1End; i1Start++) { + if ((level2) && (*level2)) { + i2Start = i1Start->second.find(level2); + i2End = i2Start; + if (i2End != i1Start->second.end()) + i2End++; + } + else { + i2Start = i1Start->second.begin(); + i2End = i1Start->second.end(); + } + for (;i2Start != i2End; i2Start++) { + if ((level3) && (*level3)) { + i3Start = i2Start->second.find(level3); + i3End = i3Start; + if (i3End != i2Start->second.end()) + i3End++; + } + else { + i3Start = i2Start->second.begin(); + i3End = i2Start->second.end(); + } + for (;i3Start != i3End; i3Start++) { + results.push_back(i3Start->second); + } + if (i3Start != i3End) + break; + } + if (i2Start != i2End) + break; + } + + retVal->length(results.size()); + for (int i = 0; i < results.size(); i++) { + if (filtered) { + (*retVal)[i] = CORBA::string_dup(delegate->RenderText(results[i].c_str())); + } + else { + (*retVal)[count++] = CORBA::string_dup(results[i].c_str()); + } + } + + return retVal; +} + + +StringList *SWModule_impl::getKeyChildren() throw(CORBA::SystemException) { + sword::SWKey *key = delegate->getKey(); + StringList *retVal = new StringList; + int count = 0; + + sword::VerseKey *vkey = SWDYNAMIC_CAST(VerseKey, key); + if (vkey) { + retVal->length(6); + SWBuf num; + num.appendFormatted("%d", vkey->Testament()); + (*retVal)[0] = CORBA::string_dup(num.c_str()); + num = ""; + num.appendFormatted("%d", vkey->Book()); + (*retVal)[1] = CORBA::string_dup(num.c_str()); + num = ""; + num.appendFormatted("%d", vkey->Chapter()); + (*retVal)[2] = CORBA::string_dup(num.c_str()); + num = ""; + num.appendFormatted("%d", vkey->Verse()); + (*retVal)[3] = CORBA::string_dup(num.c_str()); + num = ""; + num.appendFormatted("%d", vkey->books[vkey->Testament()-1][vkey->Book()-1].chapmax); + (*retVal)[4] = CORBA::string_dup(num.c_str()); + num = ""; + num.appendFormatted("%d", vkey->books[vkey->Testament()-1][vkey->Book()-1].versemax[vkey->Chapter()-1]); + (*retVal)[5] = CORBA::string_dup(num.c_str()); + } + else { + TreeKeyIdx *tkey = SWDYNAMIC_CAST(TreeKeyIdx, key); + if (tkey) { + if (tkey->firstChild()) { + do { + count++; + } + while (tkey->nextSibling()); + tkey->parent(); + } + retVal->length(count); + count = 0; + if (tkey->firstChild()) { + do { + (*retVal)[count++] = CORBA::string_dup(tkey->getLocalName()); + } + while (tkey->nextSibling()); + tkey->parent(); + } + } + } + return retVal; +} + +CORBA::Boolean SWModule_impl::hasKeyChildren() throw(CORBA::SystemException) { + sword::SWKey *key = delegate->getKey(); + bool retVal = ""; + + TreeKeyIdx *tkey = SWDYNAMIC_CAST(TreeKeyIdx, key); + if (tkey) { + retVal = tkey->hasChildren(); + } + return retVal; +} + + +char *SWModule_impl::getKeyParent() throw(CORBA::SystemException) { + sword::SWKey *key = delegate->getKey(); + SWBuf retVal = ""; + + TreeKeyIdx *tkey = SWDYNAMIC_CAST(TreeKeyIdx, key); + if (tkey) { + if (tkey->parent()) { + retVal = tkey->getText(); + } + } + return CORBA::string_dup((const char *)retVal); +} + + +StringList *SWMgr_impl::getAvailableLocales() throw(CORBA::SystemException) { + sword::StringList localeNames = LocaleMgr::getSystemLocaleMgr()->getAvailableLocales(); + StringList *retVal = new StringList; + int count = 0; + for (sword::StringList::iterator it = localeNames.begin(); it != localeNames.end(); it++) { + count++; + } + retVal->length(count); + count = 0; + for (sword::StringList::iterator it = localeNames.begin(); it != localeNames.end(); it++) { + (*retVal)[count++] = CORBA::string_dup(it->c_str()); + } + return retVal; +} + + +void SWMgr_impl::setDefaultLocale(const char *name) throw(CORBA::SystemException) { + LocaleMgr::getSystemLocaleMgr()->setDefaultLocaleName(name); +} + +} diff --git a/bindings/corba/orbitcpp/swordorb-impl.hpp b/bindings/corba/orbitcpp/swordorb-impl.hpp new file mode 100644 index 0000000..f9a88b1 --- /dev/null +++ b/bindings/corba/orbitcpp/swordorb-impl.hpp @@ -0,0 +1,79 @@ +#ifndef _ORBIT_CPP_IDL_sword_IMPL_HH +#define _ORBIT_CPP_IDL_sword_IMPL_HH + +#include "swordorb-cpp-skels.h" +#include "webmgr.hpp" +#include <swmodule.h> +#include <swmgr.h> +#include <rawtext.h> +#include <map> + + +namespace swordorb { + +static const char *SWNULL = "<SWNULL>"; +extern sword::RawText NULLMod; + +//Inherit from abstract Skeleton: +class SWModule_impl : public POA_swordorb::SWModule { + sword::SWModule *delegate; +public: + SWModule_impl(sword::SWModule *delegate) { this->delegate = delegate; } + + SearchHitList *search(const char *istr, SearchType searchType, CORBA::Long flags, const char *scope) throw(CORBA::SystemException); + StringList *parseKeyList(const char *keyText) throw(CORBA::SystemException); + void terminateSearch() throw(CORBA::SystemException) { delegate->terminateSearch = true; } + char error() throw(CORBA::SystemException) { return delegate->Error(); } + CORBA::Long getEntrySize() throw(CORBA::SystemException) { return delegate->getEntrySize(); } + void setKeyText(const char *key) throw(CORBA::SystemException) { delegate->KeyText(key); } + char *getKeyText() throw(CORBA::SystemException) { return CORBA::string_dup((char *)delegate->KeyText()); } + StringList *getKeyChildren() throw(CORBA::SystemException); + char *getKeyParent() throw(CORBA::SystemException); + CORBA::Boolean hasKeyChildren() throw(CORBA::SystemException); + char *getName() throw(CORBA::SystemException) { return CORBA::string_dup((char *)delegate->Name()); } + char *getDescription() throw(CORBA::SystemException) { return CORBA::string_dup((char *)delegate->Description()); } + char *getCategory() throw(CORBA::SystemException); + void previous() throw(CORBA::SystemException) { delegate->decrement(); } + void next() throw(CORBA::SystemException) { delegate->increment(); } + void begin() throw(CORBA::SystemException) { delegate->setPosition(sword::TOP); } + char *getStripText() throw(CORBA::SystemException) { return CORBA::string_dup((char *)delegate->StripText()); } + StringList *getEntryAttribute(const char *level1, const char *level2, const char *level3, CORBA::Boolean filtered) throw(CORBA::SystemException); + char *getRenderText() throw(CORBA::SystemException) { return CORBA::string_dup((char *)delegate->RenderText()); } + char *getRawEntry() throw(CORBA::SystemException) { return CORBA::string_dup((char *)delegate->getRawEntry()); } + void setRawEntry(const char *entryBuffer) throw(CORBA::SystemException) { delegate->setEntry(entryBuffer); } + char *getConfigEntry(const char *key) throw(CORBA::SystemException) { return CORBA::string_dup(((char *)delegate->getConfigEntry(key)) ? (char *)delegate->getConfigEntry(key):SWNULL); } + void deleteSearchFramework() throw(CORBA::SystemException) { return delegate->deleteSearchFramework(); } + CORBA::Boolean hasSearchFramework() throw(CORBA::SystemException) { return (delegate->hasSearchFramework() && delegate->isSearchOptimallySupported("God", -4, 0, 0)); } + +}; + +typedef std::map<std::string, SWModule_impl *> SWModuleMap; + +class SWMgr_impl : public POA_swordorb::SWMgr { + WebMgr *delegate; + SWModuleMap moduleImpls; +public: + SWMgr_impl(WebMgr *delegate) { this->delegate = delegate; } + + ModInfoList *getModInfoList() throw(CORBA::SystemException); + SWModule_ptr getModuleByName(const char *name) throw(CORBA::SystemException); + char *filterText(const char *filterName, const char *text) throw(CORBA::SystemException); + char *getPrefixPath() throw(CORBA::SystemException) { return CORBA::string_dup(delegate->prefixPath); } + char *getConfigPath() throw(CORBA::SystemException) { return CORBA::string_dup(delegate->configPath); } + void setGlobalOption(const char *option, const char *value) throw(CORBA::SystemException) { delegate->setGlobalOption(option, value); } + char *getGlobalOption(const char *option) throw(CORBA::SystemException) { return CORBA::string_dup((char *)delegate->getGlobalOption(option)); } + char *getGlobalOptionTip(const char *option) throw(CORBA::SystemException) { return CORBA::string_dup((char *)delegate->getGlobalOptionTip(option)); } + StringList *getGlobalOptions() throw(CORBA::SystemException); + StringList *getGlobalOptionValues(const char *option) throw(CORBA::SystemException); + void setCipherKey(const char *modName, const char *key) throw(CORBA::SystemException) { delegate->setCipherKey(modName, key); } + void terminate() throw(CORBA::SystemException); + CORBA::Boolean testConnection() throw(CORBA::SystemException); + void setJavascript(CORBA::Boolean) throw(CORBA::SystemException); + StringList *getAvailableLocales() throw(CORBA::SystemException); + void setDefaultLocale(const char *name) throw(CORBA::SystemException); + +}; +}; // namespace hellomodule + + +#endif //_ORBIT_CPP_IDL_helloworld_IMPL_HH diff --git a/bindings/corba/orbitcpp/testclient.cpp b/bindings/corba/orbitcpp/testclient.cpp new file mode 100644 index 0000000..8477d18 --- /dev/null +++ b/bindings/corba/orbitcpp/testclient.cpp @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: f; c-basic-offset: 4 -*- */ + +#include "swordorb-cpp-stubs.h" +#include "swordorb-cpp-common.h" +#include <iostream> +#include <swbuf.h> + +int main (int argc, char *argv[]) +{ + if (argc != 2) + { + std::cerr << "Usage:" << std::endl + << " " << argv[0] << " IOR" << std::endl + << std::endl; + return -1; + } + + try + { + // Initialize ORBit + CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv, "orbit-local-orb"); + + // Get a reference to the server from the IOR passed on the + // command line + CORBA::Object_var obj = orb->string_to_object(argv[1]); + swordorb::SWMgr_var mgr = swordorb::SWMgr::_narrow(obj); + + swordorb::SWModule_ptr module; + swordorb::ModInfoList *modInfoList; + + std::cout << "Connected: " << mgr->testConnection() << "\n"; + std::cout << "PrefixPath: " << mgr->getPrefixPath() << "\n"; + std::cout << "ConfigPath: " << mgr->getConfigPath() << "\n"; +// modInfoList = mgr->getModInfoList(); +// std::cout << "sequence length: " << modInfoList->length() << "\n"; +/* + for (int i = 0; i < modInfoList->length(); i++) { + std::cout << (*modInfoList)[i].name << ": " << (*modInfoList)[i].category << ": " << (*modInfoList)[i].language << "\n"; + if (!strncmp((*modInfoList)[i].category, "Bibl", 4)) { + module = mgr->getModuleByName((*modInfoList)[i].name); + module->setKeyText("jas1:19"); + std::cout << module->getRenderText() << "\n"; + } + std::cout << "\n"; + } + swordorb::StringList *localeNames = mgr->getAvailableLocales(); + for (int i = 0; i < localeNames->length(); i++) { + std::cout << (*localeNames)[i] << "\n"; + } + mgr->setDefaultLocale("de"); +*/ + mgr->setJavascript(true); + mgr->setGlobalOption("Textual Variants", "Secondary Reading"); + mgr->setGlobalOption("Footnotes", "On"); + module = mgr->getModuleByName("NASB"); +/* + module->setKeyText("jas.1.19"); + swordorb::StringList *attr = module->getEntryAttribute("Footnote", "", "body", true); + std::cout << "length: " << attr->length() << "\n"; + for (int i = 0; i < attr->length(); i++) { + std::cout << (*attr)[i] << "\n"; + } +*/ + int i = 0; + for (module->setKeyText("gen.2.8"); !module->error() && i < 3; module->next(), i++) { + std::cout << "KeyText: " << module->getKeyText() << "\n"; + std::cout << "Text: " << module->getRenderText() << "\n"; + } +/* + swordorb::SearchHitList *searchResults; + bool lucene = module->hasSearchFramework(); + searchResults = module->search("David", (lucene)?swordorb::LUCENE:swordorb::MULTIWORD, 0, ""); + for (int i = 0; i < searchResults->length(); i++) { + std::cout << (*searchResults)[i].key << "\n"; + } + + mgr->setGlobalOption("Greek Accents", "Off"); + std::cout << "\nFiltered text: " << mgr->filterText("Greek Accents", "ὁ θεὸς") << "\n"; +*/ + + + } catch(const CORBA::Exception& ex) { + std::cout << "Exception caught. Maybe the server is not running, or the IOR is wrong." << std::endl; + } + + return 0; +} diff --git a/bindings/corba/orbitcpp/webmgr.hpp b/bindings/corba/orbitcpp/webmgr.hpp new file mode 100644 index 0000000..2fba2c3 --- /dev/null +++ b/bindings/corba/orbitcpp/webmgr.hpp @@ -0,0 +1,97 @@ +#ifndef WEBMGR_HPP +#define WEBMGR_HPP + +#include <swmgr.h> +#include <swmodule.h> +#include <swfilter.h> +#include <markupfiltmgr.h> +#include <osiswordjs.h> +#include <thmlwordjs.h> +#include <gbfwordjs.h> + +using namespace sword; + +class WebMgr : public SWMgr { + OSISWordJS *osisWordJS; + ThMLWordJS *thmlWordJS; + GBFWordJS *gbfWordJS; + SWModule *defaultGreekLex; + SWModule *defaultHebLex; + SWModule *defaultGreekParse; + SWModule *defaultHebParse; + +public: + WebMgr(SWConfig *sysConf) : SWMgr(0, sysConf, false, new MarkupFilterMgr(FMT_WEBIF)) { + defaultGreekLex = 0; + defaultHebLex = 0; + defaultGreekParse = 0; + defaultHebParse = 0; + + osisWordJS = new OSISWordJS(); + thmlWordJS = new ThMLWordJS(); + gbfWordJS = new GBFWordJS(); + Load(); + osisWordJS->setDefaultModules(defaultGreekLex, defaultHebLex, defaultGreekParse, defaultHebParse); + thmlWordJS->setDefaultModules(defaultGreekLex, defaultHebLex, defaultGreekParse, defaultHebParse); + gbfWordJS->setDefaultModules(defaultGreekLex, defaultHebLex, defaultGreekParse, defaultHebParse); + osisWordJS->setMgr(this); + thmlWordJS->setMgr(this); + gbfWordJS->setMgr(this); + setGlobalOption("Textual Variants", "Primary Reading"); + } + + ~WebMgr() { + delete osisWordJS; + delete thmlWordJS; + delete gbfWordJS; + } + + + void AddGlobalOptions(SWModule *module, ConfigEntMap §ion, ConfigEntMap::iterator start, ConfigEntMap::iterator end) { + + // ThML word stuff needs to process before strongs strip + if (module->Markup() == FMT_THML) { + module->AddOptionFilter(thmlWordJS); + } + + if (module->Markup() == FMT_GBF) { + module->AddOptionFilter(gbfWordJS); + } + + // add other module filters + SWMgr::AddGlobalOptions(module, section, start, end); + + // add our special filters + if (module->getConfig().has("Feature", "GreekDef")) { + defaultGreekLex = module; + } + if (module->getConfig().has("Feature", "HebrewDef")) { + defaultHebLex = module; + } + if (module->getConfig().has("Feature", "GreekParse")) { + defaultGreekParse = module; + } + if (module->getConfig().has("Feature", "HebrewParse")) { + defaultHebParse = module; + } + if (module->getConfig().has("GlobalOptionFilter", "ThMLVariants")) { + OptionFilterMap::iterator it = optionFilters.find("ThMLVariants"); + if (it != optionFilters.end()) { + module->AddOptionFilter((*it).second); // add filter to module and option as a valid option + } + } + + if (module->Markup() == FMT_OSIS) { + module->AddOptionFilter(osisWordJS); + } + } + + + void setJavascript(bool val) { + osisWordJS->setOptionValue((val)?"On":"Off"); + thmlWordJS->setOptionValue((val)?"On":"Off"); + gbfWordJS->setOptionValue((val)?"On":"Off"); + } +}; + +#endif diff --git a/bindings/corba/swordorb.idl b/bindings/corba/swordorb.idl new file mode 100644 index 0000000..53c5aba --- /dev/null +++ b/bindings/corba/swordorb.idl @@ -0,0 +1,92 @@ +/****************************************************************************** + * sword.idl - This file contains a simple idl for accessing sword + */ + +#ifndef SWORDORB_IDL +#define SWORDORB_IDL + +module swordorb { + +typedef sequence<string> StringList; + +struct ModInfo { + string name; + string description; + string category; + string language; +}; + +typedef sequence<ModInfo> ModInfoList; + +struct SearchHit { + string modName; + string key; + long score; +}; + +typedef sequence<SearchHit> SearchHitList; +//----------------------------------------------------------------- +// SWModule methods + + enum SearchType { + REGEX, + PHRASE, + MULTIWORD, + ENTRYATTR, + LUCENE + }; + + +interface SWModule { + void terminateSearch(); + SearchHitList search(in string istr, in SearchType searchType, in long flags, in string scope); + char error(); + long getEntrySize(); + StringList getEntryAttribute(in string level1, in string level2, in string level3, in boolean filtered); + StringList parseKeyList(in string keyText); + void setKeyText(in string key); + string getKeyText(); + boolean hasKeyChildren(); + StringList getKeyChildren(); + string getKeyParent(); + string getName(); + string getDescription(); + string getCategory(); + void previous(); + void next(); + void begin(); + string getStripText(); + string getRenderText(); + string getRawEntry(); + void setRawEntry(in string entryBuffer); + string getConfigEntry(in string key); + void deleteSearchFramework(); + boolean hasSearchFramework(); +}; + + +//----------------------------------------------------------------- +// SWMgr methods +// +interface SWMgr { + ModInfoList getModInfoList(); + SWModule getModuleByName(in string name); + string getPrefixPath(); + string getConfigPath(); + void setGlobalOption(in string option, in string value); + string getGlobalOption(in string option); + string getGlobalOptionTip(in string option); + string filterText(in string filterName, in string text); + StringList getGlobalOptions(); + StringList getGlobalOptionValues(in string option); + void setCipherKey(in string modName, in string key); + void terminate(); + boolean testConnection(); + void setJavascript(in boolean val); + StringList getAvailableLocales(); + void setDefaultLocale(in string name); +}; + +}; + +#endif |