4A Server -  2.0
 All Classes Namespaces Files Functions Variables Enumerator
SECAPIInterface.java
Go to the documentation of this file.
1 /*
2  * Project: Server for annotations sharing
3  * Author: Ing. Jaroslav Dytrych idytrych@fit.vutbr.cz
4  * File: SECAPIInterface.java
5  * Description: Interface for call of SEC API (locally as a daemon)
6  */
7 
8 /**
9  * @file SECAPIInterface.java
10  *
11  * @brief Interface for call of SEC API (locally as a daemon)
12  */
13 
14 package cz.vutbr.fit.knot.annotations.modules.suggestionManager;
15 
18 import java.io.BufferedReader;
19 import java.io.BufferedWriter;
20 import java.io.File;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.InputStreamReader;
24 import java.io.OutputStream;
25 import java.io.OutputStreamWriter;
26 import java.util.List;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29 
30 /**
31  * Interface for call of SEC API as external program (deamon)
32  *
33  * Note: If SEC API is started locally it will also provide interface on some
34  * port (8082 on default installation but if it is used, 8084 is recommended).
35  * So there is no need to start other instance if we need to provide SEC API
36  * network interface to others. SEC API can also provide services not only
37  * to local Annotation Server but also to other annotation servers which
38  * has acces to appropriate port.
39  *
40  * @brief Interface for call of SEC API as external program (deamon)
41  * @author Marek Kopecky
42  */
43 public class SECAPIInterface {
44 
45  /**
46  * Default command for external program
47  */
48  public static final String SEC_API_COMMAND = "/var/sec/SEC_API/sec_api.py";
49 
50  /**
51  * Default path for external program
52  */
53  public static final String SEC_API_PATH = "/var/sec/SEC_API/";
54 
55  /**
56  * Name of setting of command for external program
57  */
58  public static final String SEC_API_SETTING_NAME = "secCommand";
59 
60  /**
61  * Name of setting of command for external program
62  */
63  public static final String SEC_API_PATH_SETTING_NAME = "secPath";
64 
65  /**
66  * Standard input of external program
67  */
68  OutputStream stdin = null;
69 
70  /**
71  * Standard error output of external program
72  */
73  InputStream stderr = null;
74 
75  /**
76  * Standard output of external program
77  */
78  InputStream stdout = null;
79 
80  /**
81  * Process builder information
82  */
83  ProcessBuilder processBuilder;
84 
85  /**
86  * Process information
87  */
88  Process processVar;
89 
90  /**
91  * Buffered writer for stdin
92  */
93  BufferedWriter brStdIn;
94 
95  /**
96  * Buffered reader for stdout
97  */
98  BufferedReader brStdOut;
99 
100  /**
101  * Buffered reader for stderr
102  */
103  BufferedReader brStdErrOut;
104 
105  /**
106  * true - proces was initialized, false proces was not initialized
107  */
108  boolean wasInitialized = false;
109 
110  /**
111  * Initialize process
112  *
113  * @return true - process was created, false - process was not created
114  */
115  public synchronized boolean init() {
116  if (wasInitialized) {
117  return false;
118  }
119 
120  String secApiCommand = SEC_API_COMMAND;
121  String nerPath = SEC_API_PATH;
122 
123  // Load command from DB
124  Object[] params = {"name",SEC_API_SETTING_NAME};
125  @SuppressWarnings("unchecked")
126  List<ServerSetting> settingsList = AppBean.getPersistenceManager().queryDB("ServerSetting.findByName",params);
127  if(settingsList != null && !settingsList.isEmpty()){
128  secApiCommand = settingsList.get(0).getSettingValue();
129  }
130  // Load path from DB
131  Object[] paramsP = {"name",SEC_API_PATH_SETTING_NAME};
132  @SuppressWarnings("unchecked")
133  List<ServerSetting> settingsListP = AppBean.getPersistenceManager().queryDB("ServerSetting.findByName",paramsP);
134  if(settingsListP != null && !settingsListP.isEmpty()){
135  nerPath = settingsListP.get(0).getSettingValue();
136  }
137 
138  // create process
139  try {
140  processBuilder = new ProcessBuilder (secApiCommand,"-d");
141  processBuilder.directory(new File(nerPath));
142  processBuilder.redirectErrorStream(true);
143  processVar = processBuilder.start();
144  } catch (IOException e) {
145  return false;
146  }
147 
148  stdin = processVar.getOutputStream ();
149  stderr = processVar.getErrorStream ();
150  stdout = processVar.getInputStream ();
151  brStdIn = new BufferedWriter(new OutputStreamWriter(stdin));
152  brStdOut = new BufferedReader(new InputStreamReader(stdout));
153  brStdErrOut = new BufferedReader(new InputStreamReader(stdout));
154 
155  wasInitialized = true;
156  return true;
157  }
158 
159  /**
160  * Returns if SEC API command is empty in database.
161  *
162  * @return If SEC API command is empty in database, returns true, false otherwise.
163  */
164  public static boolean isSecCommandEmpty() {
165  // Load command from DB
166  Object[] params = {"name",SEC_API_SETTING_NAME};
167  @SuppressWarnings("unchecked")
168  List<ServerSetting> settingsList = AppBean.getPersistenceManager().queryDB("ServerSetting.findByName",params);
169  if(settingsList != null && !settingsList.isEmpty()){
170  String secApiCommand = settingsList.get(0).getSettingValue();
171  if (secApiCommand.isEmpty()) {
172  return true;
173  }
174  }
175  return false;
176  }
177 
178  /**
179  * Send message to process and return response.
180  *
181  * @param s Message
182  * @return Response
183  * @throws Exception, when proces was terminated
184  */
185  public synchronized String makeRequest(String s) throws Exception {
186  StringBuilder output = new StringBuilder();
187  try {
188  brStdIn.write(s);
189  brStdIn.flush();
190 
191  int counter = 0;
192  boolean processEnd = false;
193  char ch;
194  do {
195  ch = (char) brStdOut.read();
196  output.append(ch);
197  try {
198  processVar.exitValue();
199  // exitValue return a value
200  processEnd = true;
201  } catch (Exception e) { // process hasn't finished yet
202  }
203  if (output.length() == 10
204  && (output.substring(0, 9).equalsIgnoreCase("Exception") || output.substring(1, 10).equalsIgnoreCase("Exception"))) {
205  Logger.getLogger(NERInterface.class.getName()).log(Level.SEVERE, "SEC API failed. It returned exception.");
206  processEnd = true;
207  }
208  if (processEnd) {
209  throw new Exception("Process was terminated");
210  }
211  if (ch == '{') {
212  counter++;
213  }
214  if (ch == '}') {
215  counter--;
216  }
217  } while (!(ch == '}' && counter <= 0));
218  } catch (IOException e) {
219  try {
220  StringBuilder erStr = new StringBuilder("");
221  String row = brStdErrOut.readLine();
222  while (row != null) {
223  erStr.append(row);
224  row = brStdErrOut.readLine();
225  }
226  Logger.getLogger(NERInterface.class.getName()).log(Level.SEVERE, "SEC API terminated! Error stream: " + erStr.toString());
227  } catch (Exception exc) {
228  }
229  throw new Exception("Process was terminated");
230  }
231  return output.toString();
232  }
233 
234  /**
235  * Destroy process and close streams
236  */
237  public void close() {
238  try {
239  wasInitialized = false;
240  try {
241  stdin.flush();
242  } catch (Exception exception) {
243  }
244  stdin.close();
245  brStdOut.close();
246  // clean up if any output in stderr
247  BufferedReader brCleanUp = new BufferedReader(new InputStreamReader(stderr));
248  while (brCleanUp.readLine() != null) {
249  }
250  brCleanUp.close();
251  stdout.close();
252  stderr.close();
253  processVar.destroy();
254  } catch (IOException e) {}
255  }
256 
257 } // public class SECAPIInterface
Class representing parameter of server settings.
Singleton for storing global variables.
Definition: AppBean.java:47
Interface for call of SEC API as external program (deamon)