blob: e453c37e67d81c15b4621957921a125614dac743 [file] [log] [blame]
<!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">&#39;get:(Ljava/lang/String;)Ljava/lang/String;&#39;</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">&#39;getProperty:(Ljava/lang/String;)Ljava/lang/String;&#39;</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">&#39;length:()I&#39;</span>
<span class="s1">&#39;doc:(I)Lorg/apache/lucene/document/Document;&#39;</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&#39;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">&gt;&gt;&gt;</span> <span class="kn">import</span> <span class="nn">lucene</span>
<span class="o">&gt;&gt;&gt;</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">&gt;&gt;&gt;</span> <span class="kn">import</span> <span class="nn">lucene</span>
<span class="o">&gt;&gt;&gt;</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">&#39;32m&#39;</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</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">&gt;&gt;&gt;</span> <span class="kn">import</span> <span class="nn">lucene</span>
<span class="o">&gt;&gt;&gt;</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">&#39;-Xcheck:jni,-verbose:jni,-verbose:gc&#39;</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">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">lucene</span> <span class="kn">import</span> <span class="o">*</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">initVM</span><span class="p">(</span><span class="n">CLASSPATH</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">findClass</span><span class="p">(</span><span class="s1">&#39;org/apache/lucene/document/Document&#39;</span><span class="p">)</span>
<span class="o">&amp;</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">&amp;</span><span class="n">gt</span><span class="p">;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">Class</span><span class="o">.</span><span class="n">forName</span><span class="p">(</span><span class="s1">&#39;org.apache.lucene.document.Document&#39;</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">&quot;&amp;lt;stdin&amp;gt;&quot;</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">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="n">module</span><span class="o">&amp;</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">&amp;</span><span class="n">gt</span><span class="o">&amp;</span><span class="n">gt</span><span class="o">&amp;</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">&#39;java.lang.Object&#39;</span><span class="p">)</span>
<span class="o">&amp;</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">&amp;</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&lt;Document&gt;</em> instance, has <em>(&lt;type 'Document'&gt;,)</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&lt;E&gt;</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"> &amp;gt&amp;gt&amp;gt a = ArrayList().of_(Document)</span>
<span class="err"> &amp;gt&amp;gt&amp;gt a</span>
<span class="err"> &amp;lt;ArrayList: []&amp;gt;</span>
<span class="err"> &amp;gt&amp;gt&amp;gt a.parameters_</span>
<span class="err"> (&amp;lt;type &#39;Document&#39;&amp;gt;,)</span>
<span class="err"> &gt;&gt;&gt; a.add(Document())</span>
<span class="err"> True</span>
<span class="err"> &gt;&gt;&gt; a.get(0)</span>
<span class="err"> &amp;lt;Document: Document&amp;lt;&amp;gt;&amp;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"> &gt;&gt;&gt; a = ArrayList()</span>
<span class="err"> &gt;&gt;&gt; a</span>
<span class="err"> &amp;lt;ArrayList: []&amp;gt;</span>
<span class="err"> &gt;&gt;&gt; a.parameters_</span>
<span class="err"> (None,)</span>
<span class="err"> &gt;&gt;&gt; a.add(Document())</span>
<span class="err"> True</span>
<span class="err"> &gt;&gt;&gt; a.get(0)</span>
<span class="err"> &amp;lt;Object: Document&amp;lt;&amp;gt;&amp;gt;</span>
<span class="err"> &gt;&gt;&gt; Document.cast_(a.get(0))</span>
<span class="err"> &amp;lt;Document: Document&amp;lt;&amp;gt;&amp;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&lt;T&gt;</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">&gt;&gt;&gt;</span> <span class="nb">array</span> <span class="o">=</span> <span class="n">JArray</span><span class="p">(</span><span class="s1">&#39;int&#39;</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">&gt;&gt;&gt;</span> <span class="nb">array</span> <span class="o">=</span> <span class="n">JArray</span><span class="p">(</span><span class="s1">&#39;int&#39;</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">&gt;&gt;&gt; JArray(&#39;int&#39;).cast_(obj)</span>
<span class="err"># cast obj to an array of Document</span>
<span class="err">&gt;&gt;&gt; JArray(&#39;object&#39;).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">&gt;&gt;&gt;</span> <span class="n">d</span> <span class="o">=</span> <span class="n">JArray</span><span class="p">(</span><span class="err">&#39;</span><span class="n">object</span><span class="err">&#39;</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">&gt;&gt;&gt;</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">&gt;&gt;&gt;</span> <span class="n">d</span>
<span class="n">JArray</span><span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="n">object</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;[</span><span class="o">&amp;</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">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">&gt;&gt;</span><span class="p">]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="o">&amp;</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">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">a</span> <span class="o">=</span> <span class="n">JArray</span><span class="p">(</span><span class="err">&#39;</span><span class="n">object</span><span class="err">&#39;</span><span class="p">)(</span><span class="mi">2</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</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">&gt;&gt;&gt;</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">&#39;</span><span class="kt">int</span><span class="err">&#39;</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">&gt;&gt;&gt;</span> <span class="n">a</span>
<span class="n">JArray</span><span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="n">object</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;[</span><span class="o">&amp;</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">&amp;</span><span class="n">gt</span><span class="p">;,</span> <span class="o">&amp;</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">&amp;</span><span class="n">gt</span><span class="p">;]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="o">&amp;</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">&amp;</span><span class="n">gt</span><span class="p">;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="o">&amp;</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">&amp;</span><span class="n">gt</span><span class="p">;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">JArray</span><span class="p">(</span><span class="err">&#39;</span><span class="n">object</span><span class="err">&#39;</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">&amp;</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">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">JArray</span><span class="p">(</span><span class="err">&#39;</span><span class="n">object</span><span class="err">&#39;</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">&amp;</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">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">JArray</span><span class="p">(</span><span class="err">&#39;</span><span class="kt">int</span><span class="err">&#39;</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">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="kt">int</span><span class="o">&amp;</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">&gt;&gt;&gt;</span> <span class="n">JArray</span><span class="p">(</span><span class="err">&#39;</span><span class="kt">int</span><span class="err">&#39;</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">&#39;s elements of type Object ?</span>
<span class="s1"> &gt;&gt;&gt; JArray(&#39;</span><span class="k">object</span><span class="s1">&#39;).instance_(d)</span>
<span class="s1"> True</span>
<span class="s1"> # can it receive Object instances ?</span>
<span class="s1"> &gt;&gt;&gt; JArray(&#39;</span><span class="k">object</span><span class="s1">&#39;).assignable_(d)</span>
<span class="s1"> False</span>
<span class="s1"> # is it array of Document ? are d&#39;</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">&gt;&gt;&gt;</span> <span class="n">JArray</span><span class="p">(</span><span class="s1">&#39;object&#39;</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">&#39;s elements of type Class ?</span>
<span class="s1"> &gt;&gt;&gt; JArray(&#39;</span><span class="k">object</span><span class="s1">&#39;).instance_(d, Class)</span>
<span class="s1"> False</span>
<span class="s1"> # can it receive Document instances ?</span>
<span class="s1"> &gt;&gt;&gt; JArray(&#39;</span><span class="k">object</span><span class="err">&#39;</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 = [&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;]</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"> &#39;getProperty:(Ljava/lang/String;)Ljava/lang/String;&#39;</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"> &#39;length:()I&#39;</span>
<span class="err"> &#39;doc:(I)Lorg/apache/lucene/document/Document;&#39;</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 &copy; 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>