| <!doctype html> |
| <html> |
| <head> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE- 2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <link href="/theme/css/lucene/global.css?v=0e493d7a" rel="stylesheet" type="text/css"> |
| |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> |
| <meta name="Distribution" content="Global"/> |
| <meta name="Robots" content="index,follow"/> |
| |
| <script type="text/javascript" src="/theme/javascript/lucene/prototype.js?v=0e493d7a"></script> |
| <script type="text/javascript" src="/theme/javascript/lucene/effects.js?v=0e493d7a"></script> |
| <script type="text/javascript" src="/theme/javascript/lucene/slides.js?v=0e493d7a"></script> |
| <script src="https://www.apachecon.com/event-images/snippet.js"></script> <title>Apache Lucene - Features</title> |
| <meta name="keywords" |
| content="apache, apache lucene, apache solr, solr, lucene |
| search, information retrieval, spell checking, faceting, inverted index, |
| open source"/> <meta property="og:type" content="website" /> |
| <meta property="og:url" content="https://lucene.apache.org/pylucene/jcc/features.html"/> |
| <meta property="og:title" content="Features"/> |
| <meta property="og:description" content="Warning Before calling any PyLucene API that requires the Java VM, start it by calling initVM(classpath, ...). More about this..."/> |
| <meta property="og:image" content="https://lucene.apache.org/theme/images/lucene/lucene_og_image.png?v=0e493d7a"/> |
| <meta property="og:image:secure_url" content="https://lucene.apache.org/theme/images/lucene/lucene_og_image.png?v=0e493d7a"/> |
| <link rel="shortcut icon" type="image/png" |
| href="/theme/images/lucene/lucene-favicon.png?v=0e493d7a"/><link href="/theme/css/lucene/pylucene.css?v=0e493d7a" rel="stylesheet" type="text/css"> |
| </head> |
| <body id="home"> |
| <div id="wrap"> |
| <div id="header"> |
| <div id="logo" style="float:left"> |
| <a href="/"> |
| <img border="0" src="/theme/images/lucene/lucene_logo_green_300.png?v=0e493d7a" alt="Lucene Logo"/> |
| </a> |
| </div> |
| <!-- TODO: Search disabled as it does not work, 2021-02-21 |
| <div id="search" style="float:right;zoom:1"> |
| <form id="quick-search" method="GET" action="https://sematext.com/opensee/lucene" name="searchform"> |
| <fieldset> |
| <input type="search" id="q" name="q" placeholder="Search with Apache Solr..." class="class1 class2 hint" accesskey="q"> |
| </fieldset> |
| </form> |
| </div>--> |
| <div id="nav"> |
| <ul> |
| <li><a href="/pylucene/jcc/index.html">JCC</a></li> |
| <li><a href="/pylucene/mailing-lists.html">Mailing Lists</a></li> |
| <li><a href="https://issues.apache.org/jira/browse/PYLUCENE">Issue Tracker</a></li> |
| <li><a href="/pylucene/index.html">PyLucene</a></li> |
| <li><a class="last" href="/">Lucene</a></li> |
| </ul> |
| </div> |
| |
| </div> <!-- End #header --> |
| |
| <div id="content-wrap" class="clearfix"> |
| <div id="main"> |
| <div> |
| <h1 class="title">Features</h1> |
| <h2 id="warning">Warning</h2> |
| <p><em>Before calling any PyLucene API that requires the Java VM, start it by calling |
| <em>initVM(classpath, ...)</em>. More about this function in <a href="#api">here</a>.</em></p> |
| <h2 id="installing-jcc">Installing JCC</h2> |
| <p>JCC is a Python extension written in Python and C++. It requires a Java Runtime |
| Environment (JRE) to operate as it uses Java's reflection APIs to do its work. |
| It is built and installed via <em>distutils</em> or <em>setuptools</em>.</p> |
| <p>See <a href="install.html">installation</a> for more information and operating system |
| specific notes.</p> |
| <h2 id="invoking-jcc">Invoking JCC</h2> |
| <p>JCC is installed as a package and how to invoke it depends on the Python version |
| used:</p> |
| <ul> |
| <li>python 3.6: <strong>python -m jcc</strong></li> |
| <li>python 2.7: <strong>python -m jcc</strong></li> |
| <li>python 2.6: <strong>python -m jcc.__main__</strong></li> |
| <li>python 2.5: <strong>python -m jcc</strong></li> |
| <li>python 2.4:<ul> |
| <li>no setuptools: <strong>python <em>site-packages</em>/jcc/__init__.py</strong></li> |
| <li>with setuptools: <strong>python <em>site-packages</em>/<em>jcc egg directory</em>/jcc/__init__.py</strong></li> |
| </ul> |
| </li> |
| <li>python 2.3: <strong>python <em>site-packages</em>/<em>jcc egg directory</em>/jcc/__init__.py</strong></li> |
| </ul> |
| <h2 id="generating-c-and-python-wrappers-with-jcc">Generating C++ and Python wrappers with JCC</h2> |
| <p>JCC started as a C++ code generator for hiding the gory details of accessing |
| methods and fields on Java classes via Java's |
| <a href="https://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/invocation.html">Native Invocation Interface</a>. |
| These C++ wrappers make it possible to access a Java object as if it was a regular |
| C++ object.</p> |
| <p>It then became apparent that JCC could also generate the C++ wrappers for making |
| these classes available to Python. Every class that gets thus wrapped becomes a |
| <a href="https://docs.python.org/2/extending/newtypes.html">CPython type</a>.</p> |
| <p>JCC generates wrappers for all public classes that are requested by name on the |
| command line or via the <em>--jar</em> command line argument. It generates wrapper methods |
| for all public methods and fields on these classes whose return type and parameter |
| types are found in one of the following ways:</p> |
| <ul> |
| <li>the type is one of the requested classes</li> |
| <li>the type is one of the requested classes' superclass or implemented interfaces</li> |
| <li>the type is available from one of the packages listed via the <em>--package</em> command |
| line argument</li> |
| </ul> |
| <p>Overloaded methods are supported and are selected at runtime on the basis of the |
| type and number of arguments passed in.</p> |
| <p>JCC does not generate wrappers for methods or fields which don't satisfy these |
| requirements. Thus, JCC can avoid generating code for runaway transitive closures |
| of type dependencies.</p> |
| <p>JCC generates property accessors for a property called <em>field</em> when it finds Java |
| methods named <em>setField(value)</em>, <em>getField()</em> or <em>isField()</em>.</p> |
| <p>The C++ wrappers are declared in a C++ namespace structure that mirrors the Java |
| classes' Java packages. The Python types are declared in a flat namespace at the |
| top level of the resulting Python extension module.</p> |
| <p>JCC's command-line arguments are best illustrated via the PyLucene example:</p> |
| <div class="highlight"><pre><span></span><code>$ python -m jcc <span class="c1"># run JCC to wrap</span> |
| --jar lucene.jar <span class="c1"># all public classes in the lucene jar file</span> |
| --jar analyzers.jar <span class="c1"># and the lucene analyzers contrib package</span> |
| --jar snowball.jar <span class="c1"># and the snowball contrib package</span> |
| --jar highlighter.jar <span class="c1"># and the highlighter contrib package</span> |
| --jar regex.jar <span class="c1"># and the regex search contrib package</span> |
| --jar queries.jar <span class="c1"># and the queries contrib package</span> |
| --jar extensions.jar <span class="c1"># and the Python extensions package</span> |
| --package java.lang <span class="c1"># including all dependencies found in the</span> |
| <span class="c1"># java.lang package</span> |
| --package java.util <span class="c1"># and the java.util package</span> |
| --package java.io <span class="c1"># and the java.io package</span> |
| java.lang.System <span class="c1"># and to explicitely wrap java.lang.System</span> |
| java.lang.Runtime <span class="c1"># as well as java.lang.Runtime</span> |
| java.lang.Boolean <span class="c1"># and java.lang.Boolean</span> |
| java.lang.Byte <span class="c1"># and java.lang.Byte</span> |
| java.lang.Character <span class="c1"># and java.lang.Character</span> |
| java.lang.Integer <span class="c1"># and java.lang.Integer</span> |
| java.lang.Short <span class="c1"># and java.lang.Short</span> |
| java.lang.Long <span class="c1"># and java.lang.Long</span> |
| java.lang.Double <span class="c1"># and java.lang.Double</span> |
| java.lang.Float <span class="c1"># and java.lang.Float</span> |
| java.text.SimpleDateFormat |
| <span class="c1"># and java.text.SimpleDateFormat</span> |
| java.io.StringReader |
| <span class="c1"># and java.io.StringReader</span> |
| java.io.InputStreamReader |
| <span class="c1"># and java.io.InputStreamReader</span> |
| java.io.FileInputStream |
| <span class="c1"># and java.io.FileInputStream</span> |
| java.util.Arrays <span class="c1"># and java.util.Arrays</span> |
| --exclude org.apache.lucene.queryParser.Token |
| <span class="c1"># while explicitely not wrapping</span> |
| <span class="c1"># org.apache.lucene.queryParser.Token</span> |
| --exclude org.apache.lucene.queryParser.TokenMgrError |
| <span class="c1"># nor org.apache.lucene.queryParser.TokenMgrError</span> |
| --exclude org.apache.lucene.queryParser.ParseException |
| <span class="c1"># nor.apache.lucene.queryParser.ParseException</span> |
| --python lucene <span class="c1"># generating Python wrappers into a module</span> |
| <span class="c1"># called lucene</span> |
| --version <span class="m">2</span>.4.0 <span class="c1"># giving the Python extension egg version 2.4.0</span> |
| --mapping org.apache.lucene.document.Document |
| <span class="s1">'get:(Ljava/lang/String;)Ljava/lang/String;'</span> |
| <span class="c1"># asking for a Python mapping protocol wrapper</span> |
| <span class="c1"># for get access on the Document class by</span> |
| <span class="c1"># calling its get method</span> |
| --mapping java.util.Properties |
| <span class="s1">'getProperty:(Ljava/lang/String;)Ljava/lang/String;'</span> |
| <span class="c1"># asking for a Python mapping protocol wrapper</span> |
| <span class="c1"># for get access on the Properties class by</span> |
| <span class="c1"># calling its getProperty method</span> |
| --sequence org.apache.lucene.search.Hits |
| <span class="s1">'length:()I'</span> |
| <span class="s1">'doc:(I)Lorg/apache/lucene/document/Document;'</span> |
| <span class="c1"># asking for a Python sequence protocol wrapper</span> |
| <span class="c1"># for length and get access on the Hits class by</span> |
| <span class="c1"># calling its length and doc methods</span> |
| --files <span class="m">2</span> <span class="c1"># generating all C++ classes into about 2 .cpp</span> |
| <span class="c1"># files</span> |
| --build <span class="c1"># and finally compiling the generated C++ code</span> |
| <span class="c1"># into a Python egg via setuptools - when</span> |
| <span class="c1"># installed - or a regular Python extension via</span> |
| <span class="c1"># distutils or setuptools otherwise</span> |
| --module collections.py |
| <span class="c1"># copying the collections.py module into the egg</span> |
| --install <span class="c1"># installing it into Python's site-packages</span> |
| <span class="c1"># directory.</span> |
| </code></pre></div> |
| |
| <p>There are limits to both how many files can fit on the command line and how large |
| a C++ file the C++ compiler can handle. By default, JCC generates one large C++ |
| file containing the source code for all wrapper classes.</p> |
| <p>Using the <em>--files</em> command line argument, this behaviour can be tuned to |
| workaround various limits:<br/> for example:</p> |
| <ul> |
| <li>to break up the large wrapper class file into about 2 files:<br/><code>--files 2</code></li> |
| <li>to break up the large wrapper class file into about 10 files:<br/><code>--files 10</code></li> |
| <li>to generate one C++ file per Java class wrapped:<br/><code>--files separate</code></li> |
| </ul> |
| <p>The <em>--prefix</em> and <em>--root</em> arguments are passed through to <em>distutils</em>' <em>setup()</em>.</p> |
| <h2 id="classpath-considerations">Classpath considerations</h2> |
| <p>When generating wrappers for Python, the JAR files passed to JCC via <em>--jar</em> are |
| copied into the resulting Python extension egg as resources and added to the extension |
| module's <em>CLASSPATH</em> variable. Classes or JAR files that are required by the classes |
| contained in the argument JAR files need to be made findable via JCC's <em>--classpath</em> |
| command line argument. At runtime, these need to be appended to the extension's |
| <em>CLASSPATH</em> variable before starting the VM with <em>initVM(CLASSPATH)</em>.</p> |
| <p>To have such required jar files also automatically copied into resulting Python |
| extension egg and added to the classpath at build and runtime, use the <em>--include</em> |
| option. This option works like the <em>--jar</em> option except that no wrappers are |
| generated for the classes contained in them unless they're explicitly named on |
| the command line.</p> |
| <p>When more than one JCC-built extension module is going to be used in the same |
| Python VM and these extension modules share Java classes, only one extension module |
| should be generated with wrappers for these shared classes. The other extension |
| modules must be built by importing the one with the shared classes by using the |
| <em>--import</em> command line parameter. This ensures that only one copy of the |
| wrappers for the shared classes are generated and that they are compatible among |
| all extension modules sharing them.</p> |
| <h2 id="using-distutils-vs-setuptools">Using <em>distutils</em> vs <em>setuptools</em></h2> |
| <p>By default, when building a Python extension, if <em>setuptools</em> is found to be |
| installed, it is used over <em>distutils</em>. If you want to force the use of <em>distutils</em> |
| over <em>setuptools</em>, use the <em>--use-distutils</em> command line argument.</p> |
| <h2 id="distributing-an-egg">Distributing an egg</h2> |
| <p>The <em>--bdist</em> option can be used to ask JCC to invoke <em>distutils</em> with <em>bdist</em> |
| or <em>setuptools</em> with <em>bdist_egg</em>. If <em>setuptools</em> is used, the resulting egg has |
| to be installed with the <a href="https://setuptools.readthedocs.io/en/latest/easy_install.html"><em>easy_install</em></a> |
| installer which is normally part of a Python installation that includes <em>setuptools</em>.</p> |
| <h2 id="jccs-runtime-api-functions">JCC's runtime API functions</h2> |
| <p>JCC includes a small runtime component that is compiled into any Python extension |
| it produces.</p> |
| <p>This runtime component makes it possible to manage the Java VM from Python. Because |
| a Java VM can be configured with a myriad of options, it is not automatically started |
| when the resulting Python extension module is loaded into the Python interpreter.</p> |
| <p>Instead, the <em>initVM()</em> function must be called from the main thread before using |
| any of the wrapped classes. It takes the following keyword arguments:</p> |
| <p>- |
| <em>classpath</em><br/> |
| A string containing one or more directories or jar files for the Java VM to search |
| for classes. Every Python extension produced by JCC exports a <em>CLASSPATH</em> variable |
| that is hardcoded to the jar files that it was produced from. A copy of each jar file |
| is installed as a resource file with the extension when JCC is invoked with the |
| <em>--install</em> command line argument. This parameter is optional and defaults to the |
| <em>CLASSPATH</em> string exported by the module |
| <em>initVM</em> is imported from.</p> |
| <div class="highlight"><pre><span></span><code> <span class="o">>>></span> <span class="kn">import</span> <span class="nn">lucene</span> |
| <span class="o">>>></span> <span class="n">lucene</span><span class="o">.</span><span class="n">initVM</span><span class="p">(</span><span class="n">classpath</span><span class="o">=</span><span class="n">lucene</span><span class="o">.</span><span class="n">CLASSPATH</span><span class="p">)</span> |
| </code></pre></div> |
| |
| <p>- |
| <em>initialheap</em><br/> |
| The initial amount of Java heap to start the Java VM with. This argument is a string |
| that follows the same syntax as the similar <em>-Xms</em> java command line argument.</p> |
| <div class="highlight"><pre><span></span><code> <span class="o">>>></span> <span class="kn">import</span> <span class="nn">lucene</span> |
| <span class="o">>>></span> <span class="n">lucene</span><span class="o">.</span><span class="n">initVM</span><span class="p">(</span><span class="n">initialheap</span><span class="o">=</span><span class="s1">'32m'</span><span class="p">)</span> |
| <span class="o">>>></span> <span class="n">lucene</span><span class="o">.</span><span class="n">Runtime</span><span class="o">.</span><span class="n">getRuntime</span><span class="p">()</span><span class="o">.</span><span class="n">totalMemory</span><span class="p">()</span> |
| <span class="il">33357824L</span> |
| </code></pre></div> |
| |
| <p>- |
| <em>maxheap</em><br/> |
| The maximum amount of Java heap that could become available to the Java VM. This |
| argument is a string that follows the same syntax as the similar <em>-Xmx</em> java command |
| line argument.</p> |
| <p>- |
| <em>maxstack</em><br/> |
| The maximum amount of stack space that available to the Java VM. This argument |
| is a string that follows the same syntax as the similar <em>-Xss</em> java command line |
| argument.</p> |
| <p>- |
| <em>vmargs</em><br/> |
| A string of comma separated additional options to pass to the VM startup rountine. |
| These are passed through as-is. For example:</p> |
| <div class="highlight"><pre><span></span><code> <span class="o">>>></span> <span class="kn">import</span> <span class="nn">lucene</span> |
| <span class="o">>>></span> <span class="n">lucene</span><span class="o">.</span><span class="n">initVM</span><span class="p">(</span><span class="n">vmargs</span><span class="o">=</span><span class="s1">'-Xcheck:jni,-verbose:jni,-verbose:gc'</span><span class="p">)</span> |
| </code></pre></div> |
| |
| <p>The <em>initVM()</em> and <em>getVMEnv()</em> functions return a JCCEnv object that has a few |
| utility methods on it:</p> |
| <p>- |
| <em>attachCurrentThread(name, asDaemon)</em><br/>Before a thread created in Python or |
| elsewhere but not in the Java VM can be used with the Java VM, this method needs |
| to be invoked. The two arguments it takes are optional and self-explanatory.</p> |
| <p>- |
| <em>detachCurrentThread()</em> |
| The opposite of <em>attachCurrentThread()</em>. This method should be used with extreme |
| caution as Python's and java VM's garbage collectors may use a thread detached |
| too early causing a system crash. The utility of this method seems dubious at the |
| moment.</p> |
| <p>There are several differences between JNI's <em>findClass()</em> and Java's <em>Class.forName()</em>:</p> |
| <p>- |
| className is a '/' separated string of names</p> |
| <p>- |
| the class loaders are different, <em>findClass()</em> may find classes that <em>Class.forName()</em> won't.</p> |
| <p>For example:</p> |
| <div class="highlight"><pre><span></span><code> <span class="o">>>></span> <span class="kn">from</span> <span class="nn">lucene</span> <span class="kn">import</span> <span class="o">*</span> |
| <span class="o">>>></span> <span class="n">initVM</span><span class="p">(</span><span class="n">CLASSPATH</span><span class="p">)</span> |
| <span class="o">>>></span> <span class="n">findClass</span><span class="p">(</span><span class="s1">'org/apache/lucene/document/Document'</span><span class="p">)</span> |
| <span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="n">Class</span><span class="p">:</span> <span class="k">class</span> <span class="nc">org</span><span class="o">.</span><span class="n">apache</span><span class="o">.</span><span class="n">lucene</span><span class="o">.</span><span class="n">document</span><span class="o">.</span><span class="n">Document</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span> |
| <span class="o">>>></span> <span class="n">Class</span><span class="o">.</span><span class="n">forName</span><span class="p">(</span><span class="s1">'org.apache.lucene.document.Document'</span><span class="p">)</span> |
| <span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span> |
| <span class="n">File</span> <span class="s2">"&lt;stdin&gt;"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="n">module</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span> |
| <span class="n">lucene</span><span class="o">.</span><span class="n">JavaError</span><span class="p">:</span> <span class="n">java</span><span class="o">.</span><span class="n">lang</span><span class="o">.</span><span class="n">ClassNotFoundException</span><span class="p">:</span> <span class="n">org</span><span class="o">/</span><span class="n">apache</span><span class="o">/</span><span class="n">lucene</span><span class="o">/</span><span class="n">document</span><span class="o">/</span><span class="n">Document</span> |
| <span class="o">&</span><span class="n">gt</span><span class="o">&</span><span class="n">gt</span><span class="o">&</span><span class="n">gt</span> <span class="n">Class</span><span class="o">.</span><span class="n">forName</span><span class="p">(</span><span class="s1">'java.lang.Object'</span><span class="p">)</span> |
| <span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="n">Class</span><span class="p">:</span> <span class="k">class</span> <span class="nc">java</span><span class="o">.</span><span class="n">lang</span><span class="o">.</span><span class="n">Object</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span> |
| </code></pre></div> |
| |
| <h2 id="type-casting-and-instance-checks">Type casting and instance checks</h2> |
| <p>Many Java APIs are declared to return types that are less specific than the types |
| actually returned. In Java 1.5, this is worked around with type parameters. JCC |
| generates code to heed type parameters unless the <em>--no-generics</em> is used. See |
| next section for details on Java generics support.</p> |
| <p>In C++, casting the object into its actual type is supported via the regular C |
| casting operator.</p> |
| <p>In Python each wrapped class has a class method called _cast__ that implements |
| the same functionality.</p> |
| <p>Similarly, each wrapped class has a class method called _instance__ that tests |
| whether the wrapped java instance is of the given type. For example:</p> |
| <div class="highlight"><pre><span></span><code> <span class="k">if</span> <span class="n">BooleanQuery</span><span class="p">.</span><span class="n">instance_</span><span class="p">(</span><span class="n">query</span><span class="p">):</span> |
| <span class="n">booleanQuery</span> <span class="o">=</span> <span class="n">BooleanQuery</span><span class="p">.</span><span class="n">cast_</span><span class="p">(</span><span class="n">query</span><span class="p">)</span> |
| |
| <span class="n">print</span> <span class="n">booleanQuery</span><span class="p">.</span><span class="n">getClauses</span><span class="p">()</span> |
| </code></pre></div> |
| |
| <h2 id="handling-generic-classes">Handling generic classes</h2> |
| <p>Java 1.5 added support for parameterized types. JCC generates code to heed type |
| parameters unless the <em>--no-generics</em> command line parameter is used. Java type |
| parameterization is a runtime feature. The same class is used for all its |
| parameterizations. Similarly, JCC wrapper objects all use the same class but store |
| type parameterizations on instances and make them accessible as a tuple via the |
| _parameters__ property.</p> |
| <p>For example, an <em>ArrayList<Document></em> instance, has <em>(<type 'Document'>,)</em> |
| for <em>parameters__ and its _get()</em> method uses that type parameter to wrap its return |
| values.</p> |
| <p>To allocate an instance of a generic Java class with specific type parameters use |
| the <em>of</em>()<em> method. This method accepts one or more Python wrapper classes to use |
| as type parameters. For example, _java.util.ArrayList<E></em> is declared to |
| accept one type parameter. Its wrapper's <em>of</em>()<em> method hence accepts one parameter, |
| a Python class, to use as type parameter for the return type of its _get()</em> method, |
| among others:</p> |
| <div class="highlight"><pre><span></span><code><span class="err"> &gt&gt&gt a = ArrayList().of_(Document)</span> |
| <span class="err"> &gt&gt&gt a</span> |
| <span class="err"> &lt;ArrayList: []&gt;</span> |
| <span class="err"> &gt&gt&gt a.parameters_</span> |
| <span class="err"> (&lt;type 'Document'&gt;,)</span> |
| <span class="err"> >>> a.add(Document())</span> |
| <span class="err"> True</span> |
| <span class="err"> >>> a.get(0)</span> |
| <span class="err"> &lt;Document: Document&lt;&gt;&gt;</span> |
| </code></pre></div> |
| |
| <p>The use of type parameters is, of course, optional. A generic Java class can still |
| be used as before, without type parameters. Downcasting from <em>Object</em> is then necessary:</p> |
| <div class="highlight"><pre><span></span><code><span class="err"> >>> a = ArrayList()</span> |
| <span class="err"> >>> a</span> |
| <span class="err"> &lt;ArrayList: []&gt;</span> |
| <span class="err"> >>> a.parameters_</span> |
| <span class="err"> (None,)</span> |
| <span class="err"> >>> a.add(Document())</span> |
| <span class="err"> True</span> |
| <span class="err"> >>> a.get(0)</span> |
| <span class="err"> &lt;Object: Document&lt;&gt;&gt;</span> |
| <span class="err"> >>> Document.cast_(a.get(0))</span> |
| <span class="err"> &lt;Document: Document&lt;&gt;&gt;</span> |
| </code></pre></div> |
| |
| <h2 id="handling-arrays">Handling arrays</h2> |
| <p>Java arrays are wrapped with a C++ JArray template. The <em>[]</em> is available for read |
| access. This template, <em>JArray<T></em>, accomodates all java primitive types, |
| <em>jstring</em>, <em>jobject</em> and wrapper class arrays.</p> |
| <p>Java arrays are returned to Python in a <em>JArray</em> wrapper instance that implements |
| the Python sequence protocol. It is possible to change an array's elements but |
| not to change an array's size.</p> |
| <p>To convert a char array to a Python string use a <em>''.join(array)</em> construct.</p> |
| <p>Any Java method expecting an array can be called with the corresponding sequence |
| object from python.</p> |
| <p>To instantiate a Java array from Python, use one of the following forms:</p> |
| <div class="highlight"><pre><span></span><code> <span class="o">>>></span> <span class="nb">array</span> <span class="o">=</span> <span class="n">JArray</span><span class="p">(</span><span class="s1">'int'</span><span class="p">)(</span><span class="k">size</span><span class="p">)</span> |
| <span class="o">#</span> <span class="n">the</span> <span class="n">resulting</span> <span class="n">Java</span> <span class="nb">int</span> <span class="nb">array</span> <span class="k">is</span> <span class="n">initialized</span> <span class="k">with</span> <span class="n">zeroes</span> |
| |
| <span class="o">>>></span> <span class="nb">array</span> <span class="o">=</span> <span class="n">JArray</span><span class="p">(</span><span class="s1">'int'</span><span class="p">)(</span><span class="n">sequence</span><span class="p">)</span> |
| <span class="o">#</span> <span class="n">the</span> <span class="n">sequence</span> <span class="n">must</span> <span class="k">only</span> <span class="n">contain</span> <span class="n">ints</span> |
| <span class="o">#</span> <span class="n">the</span> <span class="n">resulting</span> <span class="n">Java</span> <span class="nb">int</span> <span class="nb">array</span> <span class="k">contains</span> <span class="n">the</span> <span class="n">ints</span> <span class="k">in</span> <span class="n">the</span> <span class="n">sequence</span> |
| </code></pre></div> |
| |
| <p>Instead of <em>'int'</em>, you may also use one of <em>'object'</em>, <em>'string'</em>, <em>'bool'</em>, |
| <em>'byte'</em>, <em>'char'</em>, <em>'double'</em>, <em>'float'</em>, <em>'long'</em> and <em>'short'</em> to create an |
| array of the corresponding type.</p> |
| <p>Because there is only one wrapper class for object arrays, the <em>JArray('object')</em> |
| type's constructor takes a second argument denoting the class of the object elements. |
| This argument is optional and defaults to <em>Object</em>.</p> |
| <p>As with the <em>Object</em> types, the <em>JArray</em> types also include a <em>cast__ method. This |
| method becomes useful when the array returned to Python is wrapped as a plain _Object</em>. |
| This is the case, for example, with nested arrays since there is no distinct Python |
| type for every different java object array class - all java object arrays are wrapped |
| by <em>JArray('object')</em>. For example:</p> |
| <div class="highlight"><pre><span></span><code><span class="err"># cast obj to an array of ints</span> |
| <span class="err">>>> JArray('int').cast_(obj)</span> |
| <span class="err"># cast obj to an array of Document</span> |
| <span class="err">>>> JArray('object').cast_(obj, Document)</span> |
| </code></pre></div> |
| |
| <p>In both cases, the java type of obj must be compatible with the array type it is |
| being cast to.</p> |
| <div class="highlight"><pre><span></span><code> <span class="cp"># using nested array:</span> |
| |
| <span class="o">>>></span> <span class="n">d</span> <span class="o">=</span> <span class="n">JArray</span><span class="p">(</span><span class="err">'</span><span class="n">object</span><span class="err">'</span><span class="p">)(</span><span class="mi">1</span><span class="p">,</span> <span class="n">Document</span><span class="p">)</span> |
| <span class="o">>>></span> <span class="n">d</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">Document</span><span class="p">()</span> |
| <span class="o">>>></span> <span class="n">d</span> |
| <span class="n">JArray</span><span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="n">object</span><span class="o">&</span><span class="n">gt</span><span class="p">;[</span><span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="nl">Document</span><span class="p">:</span> <span class="n">Document</span><span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="o">>></span><span class="p">]</span> |
| <span class="o">>>></span> <span class="n">d</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> |
| <span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="nl">Document</span><span class="p">:</span> <span class="n">Document</span><span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span> |
| <span class="o">>>></span> <span class="n">a</span> <span class="o">=</span> <span class="n">JArray</span><span class="p">(</span><span class="err">'</span><span class="n">object</span><span class="err">'</span><span class="p">)(</span><span class="mi">2</span><span class="p">)</span> |
| <span class="o">>>></span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">d</span> |
| <span class="o">>>></span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">JArray</span><span class="p">(</span><span class="err">'</span><span class="kt">int</span><span class="err">'</span><span class="p">)([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">])</span> |
| <span class="o">>>></span> <span class="n">a</span> |
| <span class="n">JArray</span><span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="n">object</span><span class="o">&</span><span class="n">gt</span><span class="p">;[</span><span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="nl">Object</span><span class="p">:</span> <span class="p">[</span><span class="n">Lorg</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">lucene</span><span class="p">.</span><span class="n">document</span><span class="p">.</span><span class="n">Document</span><span class="p">;</span><span class="mf">@694f</span><span class="mi">12</span><span class="o">&</span><span class="n">gt</span><span class="p">;,</span> <span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="nl">Object</span><span class="p">:</span> <span class="p">[</span><span class="n">I</span><span class="mi">@234265</span><span class="o">&</span><span class="n">gt</span><span class="p">;]</span> |
| <span class="o">>>></span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> |
| <span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="nl">Object</span><span class="p">:</span> <span class="p">[</span><span class="n">Lorg</span><span class="p">.</span><span class="n">apache</span><span class="p">.</span><span class="n">lucene</span><span class="p">.</span><span class="n">document</span><span class="p">.</span><span class="n">Document</span><span class="p">;</span><span class="mf">@694f</span><span class="mi">12</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span> |
| <span class="o">>>></span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> |
| <span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="nl">Object</span><span class="p">:</span> <span class="p">[</span><span class="n">I</span><span class="mi">@234265</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span> |
| <span class="o">>>></span> <span class="n">JArray</span><span class="p">(</span><span class="err">'</span><span class="n">object</span><span class="err">'</span><span class="p">).</span><span class="n">cast_</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">])[</span><span class="mi">0</span><span class="p">]</span> |
| <span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="nl">Object</span><span class="p">:</span> <span class="n">Document</span><span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span> |
| <span class="o">>>></span> <span class="n">JArray</span><span class="p">(</span><span class="err">'</span><span class="n">object</span><span class="err">'</span><span class="p">).</span><span class="n">cast_</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">Document</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> |
| <span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="nl">Document</span><span class="p">:</span> <span class="n">Document</span><span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span><span class="o">&</span><span class="n">gt</span><span class="p">;</span> |
| <span class="o">>>></span> <span class="n">JArray</span><span class="p">(</span><span class="err">'</span><span class="kt">int</span><span class="err">'</span><span class="p">).</span><span class="n">cast_</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> |
| <span class="n">JArray</span><span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="kt">int</span><span class="o">&</span><span class="n">gt</span><span class="p">;[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span> |
| <span class="o">>>></span> <span class="n">JArray</span><span class="p">(</span><span class="err">'</span><span class="kt">int</span><span class="err">'</span><span class="p">).</span><span class="n">cast_</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">])[</span><span class="mi">0</span><span class="p">]</span> |
| <span class="mi">0</span> |
| </code></pre></div> |
| |
| <p>To verify that a Java object is of a given array type, use the <em>instance</em>()_ method |
| available on the array type. This is not the same as verifying that it is assignable |
| with elements of a given type. For example, using the arrays created above:</p> |
| <div class="highlight"><pre><span></span><code> <span class="o">#</span> <span class="k">is</span> <span class="n">d</span> <span class="nb">array</span> <span class="k">of</span> <span class="k">Object</span> <span class="o">?</span> <span class="k">are</span> <span class="n">d</span><span class="s1">'s elements of type Object ?</span> |
| <span class="s1"> >>> JArray('</span><span class="k">object</span><span class="s1">').instance_(d)</span> |
| <span class="s1"> True</span> |
| |
| <span class="s1"> # can it receive Object instances ?</span> |
| <span class="s1"> >>> JArray('</span><span class="k">object</span><span class="s1">').assignable_(d)</span> |
| <span class="s1"> False</span> |
| |
| <span class="s1"> # is it array of Document ? are d'</span><span class="n">s</span> <span class="n">elements</span> <span class="k">of</span> <span class="k">type</span> <span class="n">Document</span> <span class="o">?</span> |
| <span class="o">>>></span> <span class="n">JArray</span><span class="p">(</span><span class="s1">'object'</span><span class="p">).</span><span class="n">instance_</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">Document</span><span class="p">)</span> |
| <span class="k">True</span> |
| |
| <span class="o">#</span> <span class="k">is</span> <span class="n">it</span> <span class="nb">array</span> <span class="k">of</span> <span class="k">Class</span> <span class="o">?</span> <span class="k">are</span> <span class="n">d</span><span class="s1">'s elements of type Class ?</span> |
| <span class="s1"> >>> JArray('</span><span class="k">object</span><span class="s1">').instance_(d, Class)</span> |
| <span class="s1"> False</span> |
| |
| <span class="s1"> # can it receive Document instances ?</span> |
| <span class="s1"> >>> JArray('</span><span class="k">object</span><span class="err">'</span><span class="p">).</span><span class="n">assignable_</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">Document</span><span class="p">)</span> |
| <span class="k">True</span> |
| </code></pre></div> |
| |
| <h2 id="exception-reporting">Exception reporting</h2> |
| <p>Exceptions that occur in the Java VM and that escape to C++ are reported as a |
| <em>javaError</em> C++ exception. When using Python wrappers, the C++ exceptions are handled |
| and reported with Python exceptions. When using C++ only, failure to handle the |
| exception in your C++ code will cause the process to crash.</p> |
| <p>Exceptions that occur in the Java VM and that escape to the Python VM are reported |
| with a <em>JavaError</em> python exception object. The <em>getJavaException()</em> method can |
| be called on <em>JavaError</em> objects to obtain the original java exception object |
| wrapped as any other Java object. This Java object can be used to obtain a Java |
| stack trace for the error, for example.</p> |
| <p>Exceptions that occur in the Python VM and that escape to the Java VM, as for |
| example can happen in Python extensions (see topic below) are reported to the |
| Java VM as a <em>RuntimeException</em> or as a <em>PythonException</em> when using shared mode. |
| See <a href="install.html">installation instructions</a> for more information about shared mode.</p> |
| <h2 id="writing-java-class-extensions-in-python">Writing Java class extensions in Python</h2> |
| <p>JCC makes it relatively easy to extend a Java class from Python. This is done |
| via an intermediary class written in Java that implements a special method called |
| <em>pythonExtension()</em> and that declares a number of native methods that are to be |
| implemented by the actual Python extension.</p> |
| <p>When JCC sees these special extension java classes it generates the C++ code |
| implementing the native methods they declare. These native methods call the |
| corresponding Python method implementations passing in parameters and returning |
| the result to the Java VM caller.</p> |
| <p>For example, to implement a Lucene analyzer in Python, one would implement first |
| such an extension class in Java:</p> |
| <div class="highlight"><pre><span></span><code><span class="n">package</span> <span class="n">org</span><span class="o">.</span><span class="n">apache</span><span class="o">.</span><span class="n">pylucene</span><span class="o">.</span><span class="n">analysis</span><span class="p">;</span> |
| |
| <span class="kn">import</span> <span class="nn">org.apache.lucene.analysis.Analyzer</span><span class="p">;</span> |
| <span class="kn">import</span> <span class="nn">org.apache.lucene.analysis.TokenStream</span><span class="p">;</span> |
| <span class="kn">import</span> <span class="nn">java.io.Reader</span><span class="p">;</span> |
| |
| <span class="n">public</span> <span class="k">class</span> <span class="nc">PythonAnalyzer</span> <span class="n">extends</span> <span class="n">Analyzer</span> <span class="p">{</span> |
| <span class="n">private</span> <span class="nb">long</span> <span class="n">pythonObject</span><span class="p">;</span> |
| |
| <span class="n">public</span> <span class="n">PythonAnalyzer</span><span class="p">()</span> |
| <span class="p">{</span> |
| <span class="p">}</span> |
| |
| <span class="n">public</span> <span class="n">void</span> <span class="n">pythonExtension</span><span class="p">(</span><span class="nb">long</span> <span class="n">pythonObject</span><span class="p">)</span> |
| <span class="p">{</span> |
| <span class="n">this</span><span class="o">.</span><span class="n">pythonObject</span> <span class="o">=</span> <span class="n">pythonObject</span><span class="p">;</span> |
| <span class="p">}</span> |
| <span class="n">public</span> <span class="nb">long</span> <span class="n">pythonExtension</span><span class="p">()</span> |
| <span class="p">{</span> |
| <span class="k">return</span> <span class="n">this</span><span class="o">.</span><span class="n">pythonObject</span><span class="p">;</span> |
| <span class="p">}</span> |
| |
| <span class="n">public</span> <span class="n">void</span> <span class="n">finalize</span><span class="p">()</span> |
| <span class="n">throws</span> <span class="n">Throwable</span> |
| <span class="p">{</span> |
| <span class="n">pythonDecRef</span><span class="p">();</span> |
| <span class="p">}</span> |
| |
| <span class="n">public</span> <span class="n">native</span> <span class="n">void</span> <span class="n">pythonDecRef</span><span class="p">();</span> |
| <span class="n">public</span> <span class="n">native</span> <span class="n">TokenStream</span> <span class="n">tokenStream</span><span class="p">(</span><span class="n">String</span> <span class="n">fieldName</span><span class="p">,</span> <span class="n">Reader</span> <span class="n">reader</span><span class="p">);</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| |
| <p>The <em>pythonExtension()</em> methods is what makes this class recognized as an extension |
| class by JCC. They should be included verbatim as above along with the declaration of |
| the <em>pythonObject</em> instance variable.</p> |
| <p>The implementation of the native <em>pythonDecRef()</em> method is generated by JCC and |
| is necessary because it seems that <em>finalize()</em> cannot itself be native. Since an |
| extension class wraps the Python instance object it's going to be calling methods |
| on, its ref count needs to be decremented when this Java wrapper class disappears. |
| A declaration for <em>pythonDecRef()</em> and a <em>finalize()</em> implementation should always |
| be included verbatim as above.</p> |
| <p>Really, the only non boilerplate user input is the constructor of the class and |
| the other native methods, <em>tokenStream()</em> in the example above.</p> |
| <p>The corresponding Python class(es) are implemented as follows:</p> |
| <div class="highlight"><pre><span></span><code><span class="err">class _analyzer(PythonAnalyzer):</span> |
| <span class="err"> def tokenStream(_self, fieldName, reader):</span> |
| <span class="err"> class _tokenStream(PythonTokenStream):</span> |
| <span class="err"> def __init__(self_):</span> |
| <span class="err"> super(_tokenStream, self_).__init__()</span> |
| <span class="err"> self_.TOKENS = ["1", "2", "3", "4", "5"]</span> |
| <span class="err"> self_.INCREMENTS = [1, 2, 1, 0, 1]</span> |
| <span class="err"> self_.i = 0</span> |
| <span class="err"> self_.posIncrAtt = self_.addAttribute(PositionIncrementAttribute.class_)</span> |
| <span class="err"> self_.termAtt = self_.addAttribute(TermAttribute.class_)</span> |
| <span class="err"> self_.offsetAtt = self_.addAttribute(OffsetAttribute.class_)</span> |
| <span class="err"> def incrementToken(self_):</span> |
| <span class="err"> if self_.i == len(self_.TOKENS):</span> |
| <span class="err"> return False</span> |
| <span class="err"> self_.termAtt.setTermBuffer(self_.TOKENS[self_.i])</span> |
| <span class="err"> self_.offsetAtt.setOffset(self_.i, self_.i)</span> |
| <span class="err"> self_.posIncrAtt.setPositionIncrement(self_.INCREMENTS[self_.i])</span> |
| <span class="err"> self_.i += 1</span> |
| <span class="err"> return True</span> |
| <span class="err"> def end(self_):</span> |
| <span class="err"> pass</span> |
| <span class="err"> def reset(self_):</span> |
| <span class="err"> pass</span> |
| <span class="err"> def close(self_):</span> |
| <span class="err"> pass</span> |
| <span class="err"> return _tokenStream()</span> |
| </code></pre></div> |
| |
| <p>When an <em>__init__()</em> is declared, <em>super()</em> must be called or else the Java |
| wrapper class will not know about the Python instance it needs to invoke.</p> |
| <p>When a java extension class declares native methods for which there are public |
| or protected equivalents available on the parent class, JCC generates code that |
| makes it possible to call <em>super()</em> on these methods from Python as well.</p> |
| <p>There are a number of extension examples available in PyLucene's test |
| <a href="https://svn.apache.org/viewvc/lucene/pylucene/trunk/test3">suite</a> and |
| <a href="https://svn.apache.org/viewvc/lucene/pylucene/trunk/samples">samples</a>.</p> |
| <h2 id="embedding-a-python-vm-in-a-java-vm">Embedding a Python VM in a Java VM</h2> |
| <p>Using the same techniques used when writing a Python extension of a Java class, |
| JCC may also be used to embed a Python VM in a Java VM. Following are the steps |
| and constraints to follow to achieve this:</p> |
| <p>- |
| JCC must be built in shared mode. See <a href="install.html">installation instructions</a> |
| for more information about shared mode. Note that for this use on macOS, JCC must |
| also be built with the link flags <em>"-framework", "Python"</em> in the <em>LFLAGS</em> value.</p> |
| <p>- |
| As described in the previous section, define one or more Java classes to be "extended" |
| from Python to provide the implementations of the native methods declared on them. |
| Instances of these classes implement the bridges into the Python VM from Java.</p> |
| <p>- |
| The <em>org.apache.jcc.PythonVM</em> Java class is going be used from the Java VM's main |
| thread to initialize the embedded Python VM. This class is installed inside the |
| JCC egg under the <em>jcc/classes</em> directory and the full path to this directory must |
| be on the Java <em>CLASSPATH</em>.</p> |
| <p>- |
| The JCC egg directory contains the JCC shared runtime library - not the JCC Python |
| extension shared library - but a library called <em>libjcc.dylib</em> on macOS, <em>libjcc.so</em> |
| on Linux or <em>jcc.dll</em> on Windows. This directory must be added to the Java VM's |
| shared library path via the <em>-Djava.library.path</em> command line parameter.</p> |
| <p>- |
| In the Java VM's main thread, initialize the Python VM by calling its static |
| <em>start()</em> method passing it a Python program name string and optional start-up |
| arguments in a string array that will be made accessible in Python via <em>sys.argv</em>. |
| Note that the program name string is purely informational, and is not used by the |
| <em>start()</em> code other than to initialize that Python variable. This method returns |
| the singleton PythonVM instance to be used in this Java VM. <em>start()</em> may be called |
| multiple times; it will always return the same singleton instance. This instance |
| may also be retrieved at any later time via the static <em>get()</em> method defined on |
| the <em>org.apache.jcc.PythonVM</em> class.</p> |
| <p>- |
| Any Java VM thread that is going to be calling into the Python VM should start |
| with acquiring a reference to the Python thread state object by calling |
| <em>acquireThreadState()</em> method on the Python VM instance. It should then release |
| the Python thread state before terminating by calling <em>releaseThreadState()</em>. |
| Calling these methods is optional but strongly recommended as it ensures that |
| Python is not creating and throwing away a thread state everytime the Python VM |
| is entered and exited from a given Java VM thread.</p> |
| <p>- |
| Any Java VM thread may instantiate a Python object for which an extension class |
| was defined in Java as described in the previous section by calling the |
| <em>instantiate()</em> method on the PythonVM instance. This method takes two string |
| parameters, the name of the Python module and the name of the Python class to |
| import and instantiate from it. The <em>__init__()</em> constructor on this class |
| must be callable without any parameters and, if defined, must call <em>super()</em> in |
| order to initialize the Java side. The <em>instantiate()</em> method is declared to return |
| <em>java.lang.Object</em> but the return value is actually an instance of the Java extension |
| class used and must be downcast to it.</p> |
| <h2 id="pythonic-protocols">Pythonic protocols</h2> |
| <p>When generating wrappers for Python, JCC attempts to detect which classes can be |
| made iterable:</p> |
| <p>- |
| When a class declares to implement <em>java.lang.Iterable</em>, JCC makes it iterable |
| from Python.</p> |
| <p>- |
| When a Java class declares a method called <em>next()</em> with no arguments returning |
| an object type, this class is made iterable. Its <em>next()</em> method is assumed to |
| terminate iteration by returning <em>null</em>.</p> |
| <p>JCC generates a Python mapping get method for a class when requested to do so via |
| the <em>--mapping</em> command line option which takes two arguments, the class to generate |
| the mapping get for and the Java method to use. The method is specified with its name |
| followed by ':' and its Java |
| <a href="https://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp16432">signature</a>.</p> |
| <p>For example, <em>System.getProperties()['java.class.path']</em> is made possible by:</p> |
| <div class="highlight"><pre><span></span><code><span class="err">--mapping java.util.Properties</span> |
| <span class="err"> 'getProperty:(Ljava/lang/String;)Ljava/lang/String;'</span> |
| <span class="err"> # asking for a Python mapping protocol wrapper</span> |
| <span class="err"> # for get access on the Properties class by</span> |
| <span class="err"> # calling its getProperty method</span> |
| </code></pre></div> |
| |
| <p>JCC generates Python sequence length and get methods for a class when requested |
| to do so via the <em>--sequence</em> command line option which takes three arguments, |
| the class to generate the sequence length and get for and the two java methods |
| to use. The methods are specified with their name followed by ':' and their Java |
| <a href="https://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html#wp16432">signature</a>. |
| For example:</p> |
| <div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">xrange</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">hits</span><span class="p">))</span><span class="err">:</span><span class="w"></span> |
| <span class="n">doc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">hits</span><span class="o">[</span><span class="n">i</span><span class="o">]</span><span class="w"></span> |
| <span class="p">...</span><span class="w"></span> |
| </code></pre></div> |
| |
| <p>is made possible by:</p> |
| <div class="highlight"><pre><span></span><code><span class="err">--sequence org.apache.lucene.search.Hits</span> |
| <span class="err"> 'length:()I'</span> |
| <span class="err"> 'doc:(I)Lorg/apache/lucene/document/Document;'</span> |
| </code></pre></div> |
| </div> |
| </div> |
| <div id="sidebar"> |
| <h1 id="documentation">Documentation<a class="headerlink" href="#documentation" title="Permanent link">¶</a></h1> |
| <ul> |
| <li><a href="https://www.apache.org/licenses/">License</a></li> |
| <li><a href="/pylucene/jcc/features.html">Features</a></li> |
| <li><a href="/pylucene/jcc/install.html">Install</a></li> |
| </ul> |
| |
| <h1 id="events">Events<a class="headerlink" href="#events" title="Permanent link">¶</a></h1> |
| <ul> |
| <a class="acevent" data-format="square" data-mode="light" data-width="160" data-style="border: 1px solid lightgrey"></a> |
| </ul> |
| |
| <h1 id="asf-links">ASF links<a class="headerlink" href="#asf-links" title="Permanent link">¶</a></h1> |
| <ul> |
| <li><a href="https://www.apache.org">Apache Software Foundation</a></li> |
| <li><a href="https://www.apache.org/foundation/thanks.html">Thanks</a></li> |
| <li><a href="https://www.apache.org/foundation/sponsorship.html">Become a Sponsor</a></li> |
| <li><a href="https://www.apache.org/security/">Security</a></li> |
| </ul> |
| |
| <h1 id="related-projects">Related Projects<a class="headerlink" href="#related-projects" title="Permanent link">¶</a></h1> |
| <ul> |
| <li><a href="http://hadoop.apache.org">Apache Hadoop</a></li> |
| <li><a href="http://manifoldcf.apache.org/">Apache ManifoldCF</a></li> |
| <li><a href="http://lucenenet.apache.org/">Apache Lucene.Net</a></li> |
| <li><a href="http://mahout.apache.org">Apache Mahout</a></li> |
| <li><a href="http://nutch.apache.org">Apache Nutch</a></li> |
| <li><a href="http://opennlp.apache.org/">Apache OpenNLP</a></li> |
| <li><a href="http://tika.apache.org">Apache Tika</a></li> |
| <li><a href="http://zookeeper.apache.org">Apache Zookeeper</a></li> |
| </ul> </div> |
| </div> <!-- End #content-wrap --> |
| |
| <div id="footer"> |
| <div class="copyright"> |
| <p> |
| Copyright © 2011-2024 The Apache Software Foundation, Licensed under |
| the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>. <a href="/privacy.html">Privacy Policy</a> <br/> |
| Apache and the Apache feather logo are trademarks of The Apache Software Foundation. Apache Lucene, Apache Solr and their |
| respective logos are trademarks of the Apache Software Foundation. Please see the <a href="https://www.apache.org/foundation/marks/">Apache Trademark Policy</a> |
| for more information. |
| </p> |
| </div> |
| </div> </div> <!-- End #wrap --> |
| </body> |
| </html> |