Fix JVM segv on null pointers
[yaz4j-moved-to-github.git] / src / main / java / org / yaz4j / Connection.java
1 package org.yaz4j;
2
3 import java.io.Closeable;
4 import org.yaz4j.exception.ZoomException;
5 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_connection_p;
6 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_query_p;
7 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_resultset_p;
8 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_scanset_p;
9 import org.yaz4j.jni.yaz4jlib;
10
11 /**
12  * Class representing an on-going communication with an IR server.
13  *
14  * Creating an instance of this class does not automatically connect (e.g open
15  * a socket) to the remote server as the programmer may want to specify options
16  * on the object before establishing the actual connection.
17  *
18  * The work-flow for synchronous (the only addressed) operation when using this
19  * class should be as follows (in pseudocode):
20  *
21  * <blockquote><pre>
22  *
23  * try {
24  *  c = new Connection(...)
25  *  //possibly set some options
26  *  c.connect //establishes connection
27  *  c.search //or other operation
28  *  //possibly retrieve records
29  * catch (ZoomException e) {
30  *  //handle any protocol- or network-level errors
31  * } finally {
32  *  c.close //close the socket
33  * }
34  *
35  * </pre></blockquote>
36  * @see <a href="http://www.indexdata.com/yaz/doc/zoom.html#zoom-connections">YAZ ZOOM Connection</a>
37  * @author jakub
38  */
39 public class Connection implements Closeable {
40   private final String host;
41   private final int port;
42   protected SWIGTYPE_p_ZOOM_connection_p zoomConnection;
43   //connection is initially closed
44   protected boolean closed = true;
45   private boolean disposed = false;
46
47   public enum QueryType {
48
49     CQLQuery, PrefixQuery
50   };
51
52   static {
53     // on Linux   'yaz4j' maps to 'libyaz4j.so' (i.e. 'lib' prefix & '.so'  extension)
54     // on Windows 'yaz4j' maps to 'yaz4j.dll'   (i.e.                '.dll' extension)
55     String libName = "yaz4j";
56     System.loadLibrary(libName);
57   }
58
59   /**
60    * Create new connection object without physically opening a connection to the
61    * remote server.
62    * @param host host name of the server
63    * @param port port of the server
64    */
65   public Connection(String host, int port) {
66     if (host == null)
67       throw new NullPointerException("host cannot be null");
68     this.host = host;
69     this.port = port;
70     zoomConnection = yaz4jlib.ZOOM_connection_create(null);
71   }
72
73   public void finalize() {
74     _dispose();
75   }
76
77   /**
78    * Performs a search operation (submits the query to the server, waits for
79    * response and creates a new result set that allows to retrieve particular
80    * results)
81    * @deprecated Does not allow specifying sort criteria prior to search
82    * use {@link #search(org.yaz4j.Query) search(Query)} instead.
83    * @param query search query
84    * @param queryType type of the query (e.g RPN. CQL)
85    * @return result set containing records (hits)
86    * @throws ZoomException protocol or network-level error
87    */
88   @Deprecated
89   public ResultSet search(String query, QueryType queryType) throws
90     ZoomException {
91     if (query == null)
92       throw new NullPointerException("query cannot be null");
93     if (queryType == null)
94       throw new NullPointerException("queryType cannot be null");
95     if (closed)
96       throw new IllegalStateException("Connection is closed.");
97     SWIGTYPE_p_ZOOM_query_p yazQuery = null;
98     if (queryType == QueryType.CQLQuery) {
99       yazQuery = yaz4jlib.ZOOM_query_create();
100       yaz4jlib.ZOOM_query_cql(yazQuery, query);
101     } else if (queryType == QueryType.PrefixQuery) {
102       yazQuery = yaz4jlib.ZOOM_query_create();
103       yaz4jlib.ZOOM_query_prefix(yazQuery, query);
104     }
105     SWIGTYPE_p_ZOOM_resultset_p yazResultSet = yaz4jlib.ZOOM_connection_search(
106       zoomConnection, yazQuery);
107     yaz4jlib.ZOOM_query_destroy(yazQuery);
108     ZoomException err = ExceptionUtil.getError(zoomConnection, host,
109       port);
110     if (err != null) {
111       yaz4jlib.ZOOM_resultset_destroy(yazResultSet);
112       throw err;
113     }
114     return new ResultSet(yazResultSet, this);
115   }
116   
117     /**
118    * Performs a search operation (submits the query to the server, waits for
119    * response and creates a new result set that allows to retrieve particular
120    * results). Sort criteria may be specified prior to the search, directly
121    * on the query object.
122    * @param query search query of any type supported by YAZ.
123    * @return result set containing records (hits)
124    * @throws ZoomException protocol or network-level error
125    */
126   public ResultSet search(Query query) throws ZoomException {
127     if (query == null)
128       throw new NullPointerException("query cannot be null");
129     if (closed)
130       throw new IllegalStateException("Connection is closed.");
131     SWIGTYPE_p_ZOOM_resultset_p yazResultSet = yaz4jlib.ZOOM_connection_search(
132       zoomConnection, query.query);
133     ZoomException err = ExceptionUtil.getError(zoomConnection, host,
134       port);
135     if (err != null) {
136       yaz4jlib.ZOOM_resultset_destroy(yazResultSet);
137       throw err;
138     }
139     return new ResultSet(yazResultSet, this);
140   }
141
142   /**
143    * Performs a scan operation (obtains a list of candidate search terms against
144    * a particular access point). 
145    * @deprecated Only allows PQF scan queries, use {@link #scan(org.yaz4j.Query) scan(Query)} instead
146    * @param query query for scanning
147    * @return a scan set with the terms
148    * @throws ZoomException a protocol or network-level error
149    */
150   @Deprecated
151   public ScanSet scan(String query) throws ZoomException {
152     if (query == null)
153       throw new NullPointerException("query cannot be null");
154     if (closed)
155       throw new IllegalStateException("Connection is closed.");
156     SWIGTYPE_p_ZOOM_scanset_p yazScanSet = yaz4jlib.ZOOM_connection_scan(
157       zoomConnection, query);
158     ZoomException err = ExceptionUtil.getError(zoomConnection, host, port);
159     if (err != null) {
160       yaz4jlib.ZOOM_scanset_destroy(yazScanSet);
161       throw err;
162     }
163     ScanSet scanSet = new ScanSet(yazScanSet, this);
164     return scanSet;
165   }
166   
167     /**
168    * Performs a scan operation (obtains a list of candidate search terms against
169    * a particular access point). Allows to use both CQL and PQF for Scan.
170    * @see <a href="http://www.indexdata.com/yaz/doc/zoom.scan.html">ZOOM-API Scan</a>
171    * @param query scan query of type supported by YAZ
172    * @return a scan set with the terms
173    * @throws ZoomException a protocol or network-level error
174    */
175   public ScanSet scan(Query query) throws ZoomException {
176     if (query == null)
177       throw new NullPointerException("query cannot be null");
178     if (closed)
179       throw new IllegalStateException("Connection is closed.");
180     SWIGTYPE_p_ZOOM_scanset_p yazScanSet = yaz4jlib.ZOOM_connection_scan1(
181       zoomConnection, query.query);
182     ZoomException err = ExceptionUtil.getError(zoomConnection, host, port);
183     if (err != null) {
184       yaz4jlib.ZOOM_scanset_destroy(yazScanSet);
185       throw err;
186     }
187     ScanSet scanSet = new ScanSet(yazScanSet, this);
188     return scanSet;
189   }
190
191   /**
192    * Establishes a connection to the remote server.
193    * @throws ZoomException any (possibly network-level) errors that may occurr
194    */
195   public void connect() throws ZoomException {
196     yaz4jlib.ZOOM_connection_connect(zoomConnection, host, port);
197     ZoomException err = ExceptionUtil.getError(zoomConnection, host, port);
198     if (err != null) {
199       throw err;
200     }
201     closed = false;
202   }
203
204   /**
205    * Closes the connection.
206    */
207   @Override
208   public void close() {
209     yaz4jlib.ZOOM_connection_close(zoomConnection);
210     closed = true;
211   }
212   
213   /**
214    * Return exception type from current connection
215    *
216    * @return null if no error
217    */
218   ZoomException getZoomException() {
219     ZoomException err = ExceptionUtil.getError(zoomConnection, host, port);
220     return err;
221   }
222
223   /**
224    * Write option with a given name.
225    * @param name option name
226    * @param value option value
227    * @return connection (self) for chainability
228    */
229   public Connection option(String name, String value) {
230     if (name == null)
231       throw new NullPointerException("option name cannot be null");
232     yaz4jlib.ZOOM_connection_option_set(zoomConnection, name, value);
233     return this;
234   }
235
236   /**
237    * Read option with a given name
238    * @param name option name
239    * @return option value
240    */
241   public String option(String name) {
242     if (name == null)
243       throw new NullPointerException("option name cannot be null");
244     return yaz4jlib.ZOOM_connection_option_get(zoomConnection, name);
245   }
246
247   /**
248    * Same as option("preferredRecordSyntax")
249    * @return value of preferred record syntax
250    */
251   public String getSyntax() {
252     return option("preferredRecordSyntax");
253   }
254
255   /**
256    * Same as option("preferredRecordSyntax", value)
257    * @param value value of preferred record syntax
258    */
259   public void setSyntax(String value) {
260     option("preferredRecordSyntax", value);
261   }
262
263   /**
264    * Same as option("databaseName")
265    * @return value of databaseName
266    */
267   public String getDatabaseName() {
268     return option("databaseName");
269   }
270
271   /**
272    * Same as option("databaseName", value)
273    * @param value value of databaseName
274    */
275   public void setDatabaseName(String value) {
276     option("databaseName", value);
277   }
278
279   /**
280    * Same as option("user")
281    * @return value of user
282    */
283   public String getUsername() {
284     return option("user");
285   }
286
287   /**
288    * Same as option("user", value)
289    * @param value value of user
290    */
291   public void setUsername(String value) {
292     option("user", value);
293   }
294
295   /**
296    * Same as option("password")
297    * @return value of password
298    */
299   public String getPassword() {
300     return option("password");
301   }
302
303   /**
304    * Same as option("password", value)
305    * @param value
306    */
307   public void setPassword(String value) {
308     option("password", value);
309   }
310
311   /**
312    * INTERNAL, GC-ONLY
313    */
314   void _dispose() {
315     if (!disposed) {
316       yaz4jlib.ZOOM_connection_destroy(zoomConnection);
317       zoomConnection = null;
318       disposed = true;
319     }
320   }
321 }