Commit 4dd689795a6fc63baef1cb14a6fc4716c26fcbb9
1 parent
a7aff3e3
Exists in
master
Improve Exception management and display better error messages for the user.
Showing
9 changed files
with
208 additions
and
95 deletions
Show diff stats
src/main/java/eu/omp/irap/vespa/epntapclient/controller/EpnTapController.java
@@ -16,15 +16,12 @@ | @@ -16,15 +16,12 @@ | ||
16 | 16 | ||
17 | package eu.omp.irap.vespa.epntapclient.controller; | 17 | package eu.omp.irap.vespa.epntapclient.controller; |
18 | 18 | ||
19 | -import java.io.IOException; | ||
20 | - | ||
21 | -import org.xml.sax.SAXException; | ||
22 | - | ||
23 | import eu.omp.irap.vespa.epntapclient.utils.Const; | 19 | import eu.omp.irap.vespa.epntapclient.utils.Const; |
24 | import eu.omp.irap.vespa.epntapclient.utils.Log; | 20 | import eu.omp.irap.vespa.epntapclient.utils.Log; |
25 | import eu.omp.irap.vespa.epntapclient.utils.Queries; | 21 | import eu.omp.irap.vespa.epntapclient.utils.Queries; |
26 | import eu.omp.irap.vespa.epntapclient.view.EpnTapMainView; | 22 | import eu.omp.irap.vespa.epntapclient.view.EpnTapMainView; |
27 | import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableController; | 23 | import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableController; |
24 | +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException; | ||
28 | import eu.omp.irap.vespa.epntapclient.votable.view.VOTableView; | 25 | import eu.omp.irap.vespa.epntapclient.votable.view.VOTableView; |
29 | 26 | ||
30 | /** | 27 | /** |
@@ -94,10 +91,9 @@ public class EpnTapController { | @@ -94,10 +91,9 @@ public class EpnTapController { | ||
94 | 91 | ||
95 | /** | 92 | /** |
96 | * @param query The query to send to the selected service. | 93 | * @param query The query to send to the selected service. |
97 | - * @throws SAXException Can not change the VOTable schema location. | ||
98 | - * @throws IOException If VOTable can not be parsed or there is more than one VOTable. | 94 | + * @throws VOTableException Can not fill the Table |
99 | */ | 95 | */ |
100 | - public void sendQuery(String query) throws IOException, SAXException { | 96 | + public void sendQuery(String query) throws VOTableException { |
101 | Log.LOGGER.info("Sending query: " + query + " on " + selectedServiceURL); | 97 | Log.LOGGER.info("Sending query: " + query + " on " + selectedServiceURL); |
102 | resultsController.fillTable(selectedServiceURL, "ADQL", query); | 98 | resultsController.fillTable(selectedServiceURL, "ADQL", query); |
103 | } | 99 | } |
src/main/java/eu/omp/irap/vespa/epntapclient/utils/Log.java
@@ -37,6 +37,9 @@ public class Log { | @@ -37,6 +37,9 @@ public class Log { | ||
37 | /** The logger. */ | 37 | /** The logger. */ |
38 | public static final Logger LOGGER = Logger.getAnonymousLogger(); | 38 | public static final Logger LOGGER = Logger.getAnonymousLogger(); |
39 | 39 | ||
40 | + /** The log message displayed when errors appends. */ | ||
41 | + public static String ERROR_MSG = "-- error --\n%1s\nbecause:\n%2s\n-- end of error --\n"; | ||
42 | + | ||
40 | /** Constructor to hide the implicit public one. */ | 43 | /** Constructor to hide the implicit public one. */ |
41 | private Log() { | 44 | private Log() { |
42 | } | 45 | } |
src/main/java/eu/omp/irap/vespa/epntapclient/view/RequestView.java
@@ -19,7 +19,6 @@ package eu.omp.irap.vespa.epntapclient.view; | @@ -19,7 +19,6 @@ package eu.omp.irap.vespa.epntapclient.view; | ||
19 | import java.awt.BorderLayout; | 19 | import java.awt.BorderLayout; |
20 | import java.awt.event.ActionEvent; | 20 | import java.awt.event.ActionEvent; |
21 | import java.awt.event.ActionListener; | 21 | import java.awt.event.ActionListener; |
22 | -import java.util.logging.Level; | ||
23 | 22 | ||
24 | import javax.swing.JButton; | 23 | import javax.swing.JButton; |
25 | import javax.swing.JLabel; | 24 | import javax.swing.JLabel; |
@@ -28,6 +27,7 @@ import javax.swing.JTextArea; | @@ -28,6 +27,7 @@ import javax.swing.JTextArea; | ||
28 | 27 | ||
29 | import eu.omp.irap.vespa.epntapclient.utils.Log; | 28 | import eu.omp.irap.vespa.epntapclient.utils.Log; |
30 | import eu.omp.irap.vespa.epntapclient.utils.Queries; | 29 | import eu.omp.irap.vespa.epntapclient.utils.Queries; |
30 | +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException; | ||
31 | 31 | ||
32 | /** | 32 | /** |
33 | * @author N. Jourdane | 33 | * @author N. Jourdane |
@@ -68,8 +68,9 @@ public class RequestView extends JPanel implements ActionListener { | @@ -68,8 +68,9 @@ public class RequestView extends JPanel implements ActionListener { | ||
68 | if (((JButton) evt.getSource()).getName() == "btnSend") { | 68 | if (((JButton) evt.getSource()).getName() == "btnSend") { |
69 | try { | 69 | try { |
70 | mainView.getController().sendQuery(queryArea.getText()); | 70 | mainView.getController().sendQuery(queryArea.getText()); |
71 | - } catch (Exception e) { | ||
72 | - Log.LOGGER.log(Level.SEVERE, "Can not send query after clicking on the button.", e); | 71 | + } catch (VOTableException e) { |
72 | + Log.LOGGER.warning( | ||
73 | + "Can not send query when clicking on the send button:\n" + e.getMessage()); | ||
73 | } | 74 | } |
74 | } | 75 | } |
75 | } | 76 | } |
src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableConnection.java
@@ -24,7 +24,6 @@ import java.io.PrintWriter; | @@ -24,7 +24,6 @@ import java.io.PrintWriter; | ||
24 | import java.io.UnsupportedEncodingException; | 24 | import java.io.UnsupportedEncodingException; |
25 | import java.net.HttpURLConnection; | 25 | import java.net.HttpURLConnection; |
26 | import java.net.MalformedURLException; | 26 | import java.net.MalformedURLException; |
27 | -import java.net.ProtocolException; | ||
28 | import java.net.URL; | 27 | import java.net.URL; |
29 | import java.net.URLEncoder; | 28 | import java.net.URLEncoder; |
30 | import java.text.SimpleDateFormat; | 29 | import java.text.SimpleDateFormat; |
@@ -32,6 +31,8 @@ import java.util.Date; | @@ -32,6 +31,8 @@ import java.util.Date; | ||
32 | 31 | ||
33 | import eu.omp.irap.vespa.epntapclient.utils.Const; | 32 | import eu.omp.irap.vespa.epntapclient.utils.Const; |
34 | import eu.omp.irap.vespa.epntapclient.utils.Log; | 33 | import eu.omp.irap.vespa.epntapclient.utils.Log; |
34 | +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.BadRequestException; | ||
35 | +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.HTTPRequestException; | ||
35 | 36 | ||
36 | /** | 37 | /** |
37 | * This class provide HTTP connection support to send requests through POST / GET protocols. | 38 | * This class provide HTTP connection support to send requests through POST / GET protocols. |
@@ -50,26 +51,28 @@ public final class VOTableConnection { | @@ -50,26 +51,28 @@ public final class VOTableConnection { | ||
50 | * @param targetURL The url of the registry to communicate (ie. "http://reg.g-vo.org"). | 51 | * @param targetURL The url of the registry to communicate (ie. "http://reg.g-vo.org"). |
51 | * @param queryLanguage The language used for the queries (ie. "ADQL"). | 52 | * @param queryLanguage The language used for the queries (ie. "ADQL"). |
52 | * @param query The query to ask to the registry. | 53 | * @param query The query to ask to the registry. |
53 | - * @throws IOException If the query can not be sent or got a bad response code. | 54 | + * @throws HTTPRequestException Can not send the query. |
55 | + * @throws BadRequestException The response code is not 200. | ||
54 | * @return The path of the temporary XML file containing the http response. | 56 | * @return The path of the temporary XML file containing the http response. |
55 | */ | 57 | */ |
56 | public static String sendQuery(String targetURL, String queryLanguage, | 58 | public static String sendQuery(String targetURL, String queryLanguage, |
57 | - String query) throws IOException { | 59 | + String query) throws HTTPRequestException, BadRequestException { |
58 | 60 | ||
59 | - SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd_hhmmss_S"); | 61 | + SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd_hhmmss_SSS"); |
60 | String voTablePath = Const.TMP_DIR + "/votable" + ft.format(new Date()) + ".xml"; | 62 | String voTablePath = Const.TMP_DIR + "/votable" + ft.format(new Date()) + ".xml"; |
61 | 63 | ||
62 | String uri = targetURL + "/sync"; | 64 | String uri = targetURL + "/sync"; |
63 | String parameters = "REQUEST=doQuery&LANG=" + queryLanguage + "&QUERY="; | 65 | String parameters = "REQUEST=doQuery&LANG=" + queryLanguage + "&QUERY="; |
64 | - parameters += URLEncoder.encode(query, Const.CHARACTER_SET).replace("+", "%20") | ||
65 | - .replace(".", "%2E").replace("-", "%2D").replace("*", "%2A").replace("_", "%5F"); | 66 | + try { |
67 | + parameters += URLEncoder.encode(query, Const.CHARACTER_SET).replace("+", "%20") | ||
68 | + .replace(".", "%2E").replace("-", "%2D").replace("*", "%2A") | ||
69 | + .replace("_", "%5F"); | ||
70 | + } catch (UnsupportedEncodingException e) { | ||
71 | + throw new HTTPRequestException("Can not encode URI " + uri, e); | ||
72 | + } | ||
66 | 73 | ||
67 | Log.LOGGER.info("request: " + uri + "?" + parameters); | 74 | Log.LOGGER.info("request: " + uri + "?" + parameters); |
68 | - int responseCode = VOTableConnection.sendGet(uri, parameters, voTablePath); | ||
69 | - if (responseCode != HttpURLConnection.HTTP_OK) { | ||
70 | - throw new IOException( | ||
71 | - "The query:\n" + query + "\n got a bad response code: " + responseCode); | ||
72 | - } | 75 | + VOTableConnection.sendGet(uri, parameters, voTablePath); |
73 | 76 | ||
74 | return voTablePath; | 77 | return voTablePath; |
75 | } | 78 | } |
@@ -78,51 +81,72 @@ public final class VOTableConnection { | @@ -78,51 +81,72 @@ public final class VOTableConnection { | ||
78 | * @param url The target URL of the request. | 81 | * @param url The target URL of the request. |
79 | * @param urlParameters The parameters of the request. | 82 | * @param urlParameters The parameters of the request. |
80 | * @param resultFileName The name of the file where the request response content is writed. | 83 | * @param resultFileName The name of the file where the request response content is writed. |
81 | - * @return The response code of the request (200 if successful). | ||
82 | - * @throws IOException Can not connect to the specified URL. | ||
83 | - * @throws IllegalArgumentException Can not send the specified request. | 84 | + * @throws HTTPRequestException Can not send the request. |
85 | + * @throws BadRequestException If the | ||
84 | */ | 86 | */ |
85 | - private static int sendGet(String url, String urlParameters, String resultFileName) | ||
86 | - throws IOException { | 87 | + private static void sendGet(String url, String urlParameters, String resultFileName) |
88 | + throws HTTPRequestException, BadRequestException { | ||
87 | String inputLine; | 89 | String inputLine; |
88 | StringBuilder response = new StringBuilder(); | 90 | StringBuilder response = new StringBuilder(); |
89 | URL obj; | 91 | URL obj; |
92 | + String uri = url + "?" + urlParameters; | ||
93 | + | ||
90 | try { | 94 | try { |
91 | - obj = new URL(url + "?" + urlParameters); | 95 | + obj = new URL(uri); |
92 | } catch (MalformedURLException e) { | 96 | } catch (MalformedURLException e) { |
93 | - Log.LOGGER.severe("The URL is not correctly formated: " + e.getMessage()); | ||
94 | - throw e; | 97 | + throw new HTTPRequestException("The uri " + uri + "is not correctly formated", e); |
95 | } | 98 | } |
96 | 99 | ||
97 | HttpURLConnection con; | 100 | HttpURLConnection con; |
98 | - // TODO: Get the error message of the VOTableTable (VOTABLE/RESOURCE/INFO) | ||
99 | 101 | ||
100 | try { | 102 | try { |
101 | con = (HttpURLConnection) obj.openConnection(); | 103 | con = (HttpURLConnection) obj.openConnection(); |
104 | + con.setRequestMethod("GET"); | ||
102 | } catch (IOException e) { | 105 | } catch (IOException e) { |
103 | - Log.LOGGER.severe("Can not connect to the specified URL: " + e.getMessage()); | ||
104 | - throw e; | 106 | + throw new HTTPRequestException("Can not open HTTP GET connection with uri " + uri, e); |
105 | } | 107 | } |
106 | 108 | ||
109 | + con.setRequestProperty("User-Agent", USER_AGENT); | ||
110 | + int code = -1; | ||
111 | + | ||
107 | try { | 112 | try { |
108 | - con.setRequestMethod("GET"); | ||
109 | - } catch (ProtocolException e) { | ||
110 | - Log.LOGGER.severe("Not a valid HTTP method: " + e.getMessage()); | ||
111 | - throw e; | 113 | + code = con.getResponseCode(); |
114 | + } catch (IOException e) { | ||
115 | + throw new HTTPRequestException("Can not get the HTTP response code", e); | ||
112 | } | 116 | } |
113 | 117 | ||
114 | - con.setRequestProperty("User-Agent", USER_AGENT); | ||
115 | - int responseCode = con.getResponseCode(); | ||
116 | - BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); | 118 | + if (code != HttpURLConnection.HTTP_OK |
119 | + && code != HttpURLConnection.HTTP_BAD_REQUEST) { | ||
120 | + throw new HTTPRequestException("The server returned a bad response code: " + code); | ||
121 | + } | ||
117 | 122 | ||
118 | - while ((inputLine = in.readLine()) != null) { | ||
119 | - response.append(inputLine); | 123 | + try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) { |
124 | + while ((inputLine = in.readLine()) != null) { | ||
125 | + response.append(inputLine); | ||
126 | + } | ||
127 | + in.close(); | ||
128 | + } catch (IOException e1) { | ||
129 | + try (BufferedReader in = new BufferedReader( | ||
130 | + new InputStreamReader(con.getErrorStream()))) { | ||
131 | + while ((inputLine = in.readLine()) != null) { | ||
132 | + response.append(inputLine); | ||
133 | + } | ||
134 | + in.close(); | ||
135 | + } catch (IOException e2) { | ||
136 | + throw new HTTPRequestException("Can not get the error stream.", e2); | ||
137 | + } | ||
138 | + if (code != HttpURLConnection.HTTP_BAD_REQUEST) { | ||
139 | + throw new HTTPRequestException( | ||
140 | + "The server returned a bad response code (not 200 neither 400).", e1); | ||
141 | + } | ||
120 | } | 142 | } |
121 | - new BufferedReader(new InputStreamReader(con.getInputStream())).close(); | ||
122 | 143 | ||
123 | - printRequestResult(response, resultFileName); | 144 | + try { |
145 | + printRequestResult(response, resultFileName); | ||
146 | + } catch (IOException e) { | ||
147 | + throw new HTTPRequestException("Can not print the result in a file.", e); | ||
148 | + } | ||
124 | 149 | ||
125 | - return responseCode; | ||
126 | } | 150 | } |
127 | 151 | ||
128 | /** | 152 | /** |
src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableController.java
@@ -17,11 +17,9 @@ | @@ -17,11 +17,9 @@ | ||
17 | package eu.omp.irap.vespa.epntapclient.votable.controller; | 17 | package eu.omp.irap.vespa.epntapclient.votable.controller; |
18 | 18 | ||
19 | import java.io.IOException; | 19 | import java.io.IOException; |
20 | -import java.util.logging.Level; | ||
21 | - | ||
22 | -import org.xml.sax.SAXException; | ||
23 | 20 | ||
24 | import eu.omp.irap.vespa.epntapclient.utils.Log; | 21 | import eu.omp.irap.vespa.epntapclient.utils.Log; |
22 | +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.VOTableParsingException; | ||
25 | import eu.omp.irap.vespa.epntapclient.votable.model.Table; | 23 | import eu.omp.irap.vespa.epntapclient.votable.model.Table; |
26 | import eu.omp.irap.vespa.epntapclient.votable.model.VOTABLE; | 24 | import eu.omp.irap.vespa.epntapclient.votable.model.VOTABLE; |
27 | import eu.omp.irap.vespa.epntapclient.votable.view.VOTableView; | 25 | import eu.omp.irap.vespa.epntapclient.votable.view.VOTableView; |
@@ -51,13 +49,10 @@ public class VOTableController { | @@ -51,13 +49,10 @@ public class VOTableController { | ||
51 | */ | 49 | */ |
52 | public VOTableController(String voTablePath) { | 50 | public VOTableController(String voTablePath) { |
53 | view = new VOTableView(); | 51 | view = new VOTableView(); |
54 | - | ||
55 | try { | 52 | try { |
56 | fillTable(voTablePath); | 53 | fillTable(voTablePath); |
57 | - } catch (Exception e) { | ||
58 | - view.displayError("VOTable can not be displayed.\nReason:\n", e.getMessage()); | ||
59 | - Log.LOGGER.log(Level.SEVERE, "VOTable can not be displayed.", e); | ||
60 | - | 54 | + } catch (VOTableException e) { |
55 | + view.displayError("Can not fil the VOTable.", e); | ||
61 | } | 56 | } |
62 | } | 57 | } |
63 | 58 | ||
@@ -73,9 +68,8 @@ public class VOTableController { | @@ -73,9 +68,8 @@ public class VOTableController { | ||
73 | 68 | ||
74 | try { | 69 | try { |
75 | fillTable(VOTableConnection.sendQuery(targetURL, queryLanguage, query)); | 70 | fillTable(VOTableConnection.sendQuery(targetURL, queryLanguage, query)); |
76 | - } catch (Exception e) { | ||
77 | - view.displayError("VOTable can not be displayed.\nReason:\n", e.getMessage()); | ||
78 | - Log.LOGGER.log(Level.SEVERE, "VOTable can not be displayed.", e); | 71 | + } catch (VOTableException e) { |
72 | + Log.LOGGER.info("VOTableController error: " + e.getMessage()); | ||
79 | } | 73 | } |
80 | } | 74 | } |
81 | 75 | ||
@@ -83,52 +77,52 @@ public class VOTableController { | @@ -83,52 +77,52 @@ public class VOTableController { | ||
83 | * @param targetURL The url of the registry to communicate (ie. "http://reg.g-vo.org"). | 77 | * @param targetURL The url of the registry to communicate (ie. "http://reg.g-vo.org"). |
84 | * @param queryLanguage The language used for the queries (ie. "ADQL"). | 78 | * @param queryLanguage The language used for the queries (ie. "ADQL"). |
85 | * @param query The query to ask to the registry. | 79 | * @param query The query to ask to the registry. |
86 | - * @throws IOException If VOTable can not be parsed or there is more than one VOTable. | ||
87 | - * @throws SAXException Can not change the VOTable schema location. | 80 | + * @throws VOTableException Can not send the query or VOTable can not be parsed or can not fill |
81 | + * the JTable. | ||
88 | */ | 82 | */ |
89 | public void fillTable(String targetURL, String queryLanguage, String query) | 83 | public void fillTable(String targetURL, String queryLanguage, String query) |
90 | - throws IOException, SAXException { | 84 | + throws VOTableException { |
91 | fillTable(VOTableConnection.sendQuery(targetURL, queryLanguage, query)); | 85 | fillTable(VOTableConnection.sendQuery(targetURL, queryLanguage, query)); |
92 | } | 86 | } |
93 | 87 | ||
94 | /** | 88 | /** |
95 | * @param voTablePath The path of the VOTable file. | 89 | * @param voTablePath The path of the VOTable file. |
96 | - * @throws IOException If VOTable can not be parsed or there is more than one VOTable. | ||
97 | - * @throws SAXException Can not change the VOTable schema location. | 90 | + * @throws VOTableException Can not fill the VOTable data in the JTable. |
98 | */ | 91 | */ |
99 | - public void fillTable(String voTablePath) throws IOException, SAXException { | 92 | + public void fillTable(String voTablePath) throws VOTableException { |
93 | + | ||
100 | try { | 94 | try { |
101 | voTable = VOTableParser.parseVOTable(voTablePath); | 95 | voTable = VOTableParser.parseVOTable(voTablePath); |
102 | - } catch (IOException e) { | ||
103 | - view.displayError("Can not parse the VOTable", "Can not parse the VOTable.\nReason:\n" + | ||
104 | - e.getMessage()); | ||
105 | - Log.LOGGER.log(Level.SEVERE, "Can not parse the VOTable.", e); | ||
106 | - } catch (SAXException e) { | ||
107 | - view.displayError("Can not change the VOTable schema location", | ||
108 | - "Can not change the VOTable schema location.\nReason:\n" + e.getMessage()); | ||
109 | - Log.LOGGER.log(Level.SEVERE, "Can not change the VOTable schema location.", e); | 96 | + } catch (VOTableParsingException e1) { |
97 | + view.displayError("Can not parse the VOTable.", e1); | ||
110 | } | 98 | } |
111 | 99 | ||
112 | // TODO: Handle the case when there are more than 1 resource or table. | 100 | // TODO: Handle the case when there are more than 1 resource or table. |
113 | if (voTable.getRESOURCE().size() > 1) { | 101 | if (voTable.getRESOURCE().size() > 1) { |
114 | - view.displayError("Several resources", | ||
115 | - "VOTable with more than one resource are not yet supported.\n" | ||
116 | - + "See VOTable file for debug:\n" + voTablePath); | 102 | + view.displayError("VOTable with more than one resource are not yet supported.\n" |
103 | + + "See VOTable file for more informations: " + voTablePath); | ||
104 | + return; | ||
117 | } | 105 | } |
118 | - // TODO: Iterate over all potential errors | 106 | + // TODO: Iterate over all potential ERROR tags |
119 | if ("ERROR".equals(voTable.getRESOURCE().get(0).getINFO().get(0).getValueAttribute())) { | 107 | if ("ERROR".equals(voTable.getRESOURCE().get(0).getINFO().get(0).getValueAttribute())) { |
120 | - view.displayError("Bad query", "There is an error on the query:\n" | ||
121 | - + voTable.getRESOURCE().get(0).getINFO().get(0).getValue()); | 108 | + String errorInfo = voTable.getRESOURCE().get(0).getINFO().get(0).getValue(); |
109 | + view.displayError("The query is not valid.\n" + errorInfo); | ||
110 | + return; | ||
122 | } | 111 | } |
123 | if (voTable.getRESOURCE().get(0).getLINKAndTABLEOrRESOURCE().size() > 1) { | 112 | if (voTable.getRESOURCE().get(0).getLINKAndTABLEOrRESOURCE().size() > 1) { |
124 | - view.displayError("Several tables", | ||
125 | - "VOTable with more than one table are not yet supported. See VOTable file for debug:\n" | ||
126 | - + voTablePath); | 113 | + view.displayError("VOTable with more than one table are not yet supported.\n" |
114 | + + "See VOTable file for more informations: " + voTablePath); | ||
115 | + return; | ||
127 | } | 116 | } |
128 | Table table = (Table) (voTable.getRESOURCE().get(0).getLINKAndTABLEOrRESOURCE().get(0)); | 117 | Table table = (Table) (voTable.getRESOURCE().get(0).getLINKAndTABLEOrRESOURCE().get(0)); |
129 | 118 | ||
130 | - VOTableDataParser dataParser = new VOTableDataParser(table); | ||
131 | - view.fillTable(dataParser.getColumnsName(), dataParser.getDataArray()); | 119 | + VOTableDataParser dataParser; |
120 | + try { | ||
121 | + dataParser = new VOTableDataParser(table); | ||
122 | + view.fillTable(dataParser.getColumnsName(), dataParser.getDataArray()); | ||
123 | + } catch (IOException e) { | ||
124 | + throw new VOTableException("Can not fill the VOTable data in the JTable.", e); | ||
125 | + } | ||
132 | } | 126 | } |
133 | 127 | ||
134 | /** | 128 | /** |
src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableDataParser.java
@@ -73,7 +73,7 @@ public class VOTableDataParser { | @@ -73,7 +73,7 @@ public class VOTableDataParser { | ||
73 | for (int i = 0; i < fields.size(); i++) { | 73 | for (int i = 0; i < fields.size(); i++) { |
74 | columnsName[i] = fields.get(i).getName(); | 74 | columnsName[i] = fields.get(i).getName(); |
75 | } | 75 | } |
76 | - Log.LOGGER.info("Columns name: \n " + new Gson().toJson(columnsName)); | 76 | + Log.LOGGER.info("Columns name: " + new Gson().toJson(columnsName)); |
77 | 77 | ||
78 | data = new ArrayList<>(); | 78 | data = new ArrayList<>(); |
79 | 79 | ||
@@ -185,7 +185,8 @@ public class VOTableDataParser { | @@ -185,7 +185,8 @@ public class VOTableDataParser { | ||
185 | Object[] row = new Object[columnsName.length]; | 185 | Object[] row = new Object[columnsName.length]; |
186 | 186 | ||
187 | Log.clearFile(); | 187 | Log.clearFile(); |
188 | - for (int nValue = 0; cursor < bytes.length; nValue++) { | 188 | + int nValue = 0; |
189 | + while (cursor < bytes.length) { | ||
189 | int nColumn = nValue % columnsName.length; | 190 | int nColumn = nValue % columnsName.length; |
190 | Field column = fields.get(nColumn); | 191 | Field column = fields.get(nColumn); |
191 | DataType dataType = column.getDatatype(); | 192 | DataType dataType = column.getDatatype(); |
@@ -247,6 +248,7 @@ public class VOTableDataParser { | @@ -247,6 +248,7 @@ public class VOTableDataParser { | ||
247 | if (nColumn == columnsName.length - 1) { | 248 | if (nColumn == columnsName.length - 1) { |
248 | data.add(row); | 249 | data.add(row); |
249 | } | 250 | } |
251 | + nValue++; | ||
250 | } | 252 | } |
251 | 253 | ||
252 | } | 254 | } |
src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableException.java
0 โ 100644
@@ -0,0 +1,76 @@ | @@ -0,0 +1,76 @@ | ||
1 | +/* | ||
2 | + * This file is a part of EpnTAPClient. | ||
3 | + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. | ||
4 | + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 | ||
5 | + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planรฉtologie. | ||
6 | + * | ||
7 | + * This program is free software: you can | ||
8 | + * redistribute it and/or modify it under the terms of the GNU General Public License as published | ||
9 | + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later | ||
10 | + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
11 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | ||
12 | + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of | ||
13 | + * the GNU General Public License along with this program. If not, see | ||
14 | + * <http://www.gnu.org/licenses/>. | ||
15 | + */ | ||
16 | + | ||
17 | +package eu.omp.irap.vespa.epntapclient.votable.controller; | ||
18 | + | ||
19 | +import java.util.logging.Level; | ||
20 | + | ||
21 | +import eu.omp.irap.vespa.epntapclient.utils.Log; | ||
22 | + | ||
23 | +/** | ||
24 | + * VOTable Exception class. | ||
25 | + * | ||
26 | + * @author N. Jourdane | ||
27 | + */ | ||
28 | +@SuppressWarnings({ "javadoc", "serial" }) | ||
29 | +public class VOTableException extends Exception { | ||
30 | + public VOTableException() { | ||
31 | + Log.LOGGER.log(Level.SEVERE, "A VOTable error occured."); | ||
32 | + } | ||
33 | + | ||
34 | + public VOTableException(String message) { | ||
35 | + Log.LOGGER.log(Level.SEVERE, message); | ||
36 | + } | ||
37 | + | ||
38 | + public VOTableException(String message, Exception e) { | ||
39 | + Log.LOGGER.log(Level.SEVERE, String.format(Log.ERROR_MSG, message, e.getMessage())); | ||
40 | + } | ||
41 | + | ||
42 | + public VOTableException(Exception e) { | ||
43 | + Log.LOGGER.log(Level.SEVERE, e.getMessage()); | ||
44 | + } | ||
45 | + | ||
46 | + public static class HTTPRequestException extends VOTableException { | ||
47 | + public HTTPRequestException(String message) { | ||
48 | + Log.LOGGER.log(Level.SEVERE, message); | ||
49 | + } | ||
50 | + | ||
51 | + public HTTPRequestException(String message, Exception e) { | ||
52 | + Log.LOGGER.log(Level.SEVERE, String.format(Log.ERROR_MSG, message, e.getMessage())); | ||
53 | + } | ||
54 | + } | ||
55 | + | ||
56 | + public static class VOTableParsingException extends VOTableException { | ||
57 | + public VOTableParsingException(String message, Exception e) { | ||
58 | + Log.LOGGER.log(Level.SEVERE, String.format(Log.ERROR_MSG, message, e.getMessage())); | ||
59 | + } | ||
60 | + } | ||
61 | + | ||
62 | + public static class BadRequestException extends VOTableException { | ||
63 | + private String info; | ||
64 | + | ||
65 | + public BadRequestException(String message, String info) { | ||
66 | + super(message); | ||
67 | + this.info = info; | ||
68 | + Log.LOGGER.log(Level.WARNING, message + "\nDetails: " + info); | ||
69 | + } | ||
70 | + | ||
71 | + public String getInfo() { | ||
72 | + return info; | ||
73 | + } | ||
74 | + } | ||
75 | + | ||
76 | +} |
src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java
@@ -20,6 +20,7 @@ import java.io.File; | @@ -20,6 +20,7 @@ import java.io.File; | ||
20 | import java.io.IOException; | 20 | import java.io.IOException; |
21 | 21 | ||
22 | import javax.xml.bind.JAXBContext; | 22 | import javax.xml.bind.JAXBContext; |
23 | +import javax.xml.bind.JAXBException; | ||
23 | import javax.xml.bind.Unmarshaller; | 24 | import javax.xml.bind.Unmarshaller; |
24 | import javax.xml.parsers.DocumentBuilder; | 25 | import javax.xml.parsers.DocumentBuilder; |
25 | import javax.xml.parsers.DocumentBuilderFactory; | 26 | import javax.xml.parsers.DocumentBuilderFactory; |
@@ -35,6 +36,7 @@ import org.w3c.dom.NamedNodeMap; | @@ -35,6 +36,7 @@ import org.w3c.dom.NamedNodeMap; | ||
35 | import org.xml.sax.SAXException; | 36 | import org.xml.sax.SAXException; |
36 | 37 | ||
37 | import eu.omp.irap.vespa.epntapclient.utils.Log; | 38 | import eu.omp.irap.vespa.epntapclient.utils.Log; |
39 | +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.VOTableParsingException; | ||
38 | import eu.omp.irap.vespa.epntapclient.votable.model.VOTABLE; | 40 | import eu.omp.irap.vespa.epntapclient.votable.model.VOTABLE; |
39 | 41 | ||
40 | /** | 42 | /** |
@@ -61,23 +63,24 @@ public final class VOTableParser { | @@ -61,23 +63,24 @@ public final class VOTableParser { | ||
61 | /** | 63 | /** |
62 | * @param voTablePath The path of the VOTable. | 64 | * @param voTablePath The path of the VOTable. |
63 | * @return The VOTable resulting of the XML document. | 65 | * @return The VOTable resulting of the XML document. |
64 | - * @throws IOException Can not parse the VOTable. | ||
65 | - * @throws SAXException Can not change the VOTable schema location. | 66 | + * @throws VOTableParsingException Can not parse the VOTable. |
66 | */ | 67 | */ |
67 | - public static VOTABLE parseVOTable(String voTablePath) throws IOException, SAXException { | 68 | + public static VOTABLE parseVOTable(String voTablePath) throws VOTableParsingException { |
68 | try { | 69 | try { |
69 | changeVOTableSchemaLocation(voTablePath); | 70 | changeVOTableSchemaLocation(voTablePath); |
70 | - } catch (Exception e1) { | ||
71 | - throw new IOException("Can not change the VOTable schema location.", e1); | 71 | + } catch (IOException e1) { |
72 | + throw new VOTableParsingException("Can not change the VOTable schema location.", e1); | ||
72 | } | 73 | } |
74 | + | ||
73 | // TODO: Change the name of the 2nd INFO tag instead of editing the XSD file. | 75 | // TODO: Change the name of the 2nd INFO tag instead of editing the XSD file. |
74 | VOTABLE voTable; | 76 | VOTABLE voTable; |
77 | + JAXBContext jc; | ||
75 | try { | 78 | try { |
76 | - JAXBContext jc = JAXBContext.newInstance(VOTABLE_MODEL_PACKAGE); | 79 | + jc = JAXBContext.newInstance(VOTABLE_MODEL_PACKAGE); |
77 | Unmarshaller unmarshaller = jc.createUnmarshaller(); | 80 | Unmarshaller unmarshaller = jc.createUnmarshaller(); |
78 | voTable = (VOTABLE) unmarshaller.unmarshal(new File(voTablePath)); | 81 | voTable = (VOTABLE) unmarshaller.unmarshal(new File(voTablePath)); |
79 | - } catch (Exception e) { | ||
80 | - throw new SAXException("Can not parse the VOTable.", e); | 82 | + } catch (JAXBException e) { |
83 | + throw new VOTableParsingException("Can not change the VOTable schema location.", e); | ||
81 | } | 84 | } |
82 | 85 | ||
83 | return voTable; | 86 | return voTable; |
src/main/java/eu/omp/irap/vespa/epntapclient/votable/view/VOTableView.java
@@ -18,6 +18,7 @@ package eu.omp.irap.vespa.epntapclient.votable.view; | @@ -18,6 +18,7 @@ package eu.omp.irap.vespa.epntapclient.votable.view; | ||
18 | 18 | ||
19 | import java.awt.BorderLayout; | 19 | import java.awt.BorderLayout; |
20 | import java.util.List; | 20 | import java.util.List; |
21 | +import java.util.logging.Level; | ||
21 | 22 | ||
22 | import javax.swing.JOptionPane; | 23 | import javax.swing.JOptionPane; |
23 | import javax.swing.JPanel; | 24 | import javax.swing.JPanel; |
@@ -28,13 +29,15 @@ import javax.swing.event.TableModelEvent; | @@ -28,13 +29,15 @@ import javax.swing.event.TableModelEvent; | ||
28 | import javax.swing.event.TableModelListener; | 29 | import javax.swing.event.TableModelListener; |
29 | import javax.swing.table.DefaultTableModel; | 30 | import javax.swing.table.DefaultTableModel; |
30 | 31 | ||
32 | +import eu.omp.irap.vespa.epntapclient.utils.Log; | ||
33 | + | ||
31 | /** | 34 | /** |
32 | * The main class of the View of the application. | 35 | * The main class of the View of the application. |
33 | * | 36 | * |
34 | * @author N. Jourdane | 37 | * @author N. Jourdane |
35 | */ | 38 | */ |
36 | public class VOTableView extends JPanel implements TableModelListener { | 39 | public class VOTableView extends JPanel implements TableModelListener { |
37 | - | 40 | + // TODO: Create classes VOTableGUI and VOTableCLI which implements an interface VOTableView |
38 | /** The serial version UID (affected with a random number). */ | 41 | /** The serial version UID (affected with a random number). */ |
39 | private static final long serialVersionUID = -6131752938586134234L; | 42 | private static final long serialVersionUID = -6131752938586134234L; |
40 | 43 | ||
@@ -99,11 +102,22 @@ public class VOTableView extends JPanel implements TableModelListener { | @@ -99,11 +102,22 @@ public class VOTableView extends JPanel implements TableModelListener { | ||
99 | /** | 102 | /** |
100 | * Display an error. | 103 | * Display an error. |
101 | * | 104 | * |
102 | - * @param title The title of the window. | ||
103 | - * @param message The error message to display. | 105 | + * @param message The error message displayed in the window. |
106 | + */ | ||
107 | + public void displayError(String message) { | ||
108 | + JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE); | ||
109 | + Log.LOGGER.log(Level.WARNING, message); | ||
110 | + } | ||
111 | + | ||
112 | + /** | ||
113 | + * Display an error. | ||
114 | + * | ||
115 | + * @param message The error message displayed in the window. | ||
116 | + * @param e The exception displayed in the log for debug. | ||
104 | */ | 117 | */ |
105 | - public void displayError(String title, String message) { | ||
106 | - JOptionPane.showMessageDialog(this, message, title, JOptionPane.ERROR_MESSAGE); | 118 | + public void displayError(String message, Exception e) { |
119 | + JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE); | ||
120 | + Log.LOGGER.log(Level.SEVERE, String.format(Log.ERROR_MSG, message, e.getMessage())); | ||
107 | } | 121 | } |
108 | 122 | ||
109 | @Override | 123 | @Override |