Salome HOME
Applet's fix. Now the alert shows before starting the SALOME.
[tools/siman.git] / Workspace / Siman / src / org / splat / launcher / ToolbarApplet.java
1 package org.splat.launcher;
2
3 import java.awt.Color;
4 import java.awt.ComponentOrientation;
5 import java.awt.GridLayout;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
8 import java.io.BufferedReader;
9 import java.io.File;
10 import java.io.IOException;
11 import java.io.InputStreamReader;
12 import java.io.ObjectInputStream;
13 import java.io.UnsupportedEncodingException;
14 import java.net.MalformedURLException;
15 import java.net.URL;
16 import java.net.URLConnection;
17 import java.net.URLEncoder;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.List;
21
22 /**
23  * Applet providing a set of buttons. Each button is defined by three parameters:<BR>
24  * <ul>
25  * <li><i>icon&lt;i&gt;</i></li>
26  * <li><i>tool&lt;i&gt;</i></li>
27  * <li><i>file&lt;i&gt;</i></li> - may be null
28  * </ul>
29  * where i is an index beginning from zero.
30  */
31 public class ToolbarApplet extends java.applet.Applet implements ActionListener {
32
33         /**
34          * Serialization version id.
35          */
36         private static final long serialVersionUID = 3243053622061086715L;
37
38         /**
39          * The name of the script to run Salome.
40          */
41         private static final String RUN_SALOME_SCRIPT = "run_salome_siman";
42         /**
43          * Possible script extensions.
44          */
45         private static final String[] SCRIPT_EXT = { "", ".sh", ".bat", ".cmd" };
46         /**
47          * The response key string: '<i>"canCheckout"</i> :'.
48          */
49         public static final String CHECKOUT_RES = "\"canCheckout\" :";
50
51         // ==============================================================================================================================
52         // Overridden functions
53         // ==============================================================================================================================
54
55         /**
56          * {@inheritDoc}
57          * 
58          * @see java.applet.Applet#init()
59          */
60         @Override
61         public void init() {
62                 URL appurl = getCodeBase();
63                 int hgap = 6; // Gap between icons
64                 int ntools;
65
66                 int width = getSize().width;
67                 int height = getSize().height;
68                 for (ntools = 0; ntools < (width + hgap) / (height + hgap); ntools++) {
69                         String icon = this.getParameter("icon" + ntools);
70                         String tool = this.getParameter("tool" + ntools);
71                         String file = this.getParameter("file" + ntools); // May be null
72                         if (icon != null && tool != null) {
73                                 ToolButton button = new ToolButton(height, getImage(appurl,
74                                                 "../skin/" + icon), tool, file);
75                                 add(button); // For displaying the button
76                                 button.addActionListener(this);
77                         }
78                 }
79                 setLayout(new GridLayout(1, ntools, hgap, 0)); // 1 row, {ntools} buttons
80                 setBackground(Color.decode("#D2E7FF"));
81                 applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
82         }
83
84         /**
85          * {@inheritDoc}
86          * 
87          * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
88          */
89         public void actionPerformed(final ActionEvent event) {
90                 if (event.getSource() instanceof ToolButton) {
91                         ToolButton clicked = (ToolButton) event.getSource();
92                         String module = clicked.getTool();
93                         String target = clicked.getTarget();
94                         launch(module, target);
95                 }
96         }
97
98         // ==============================================================================================================================
99         // Public member functions
100         // ==============================================================================================================================
101
102         /**
103          * Launch an appropriate application for the given file.
104          * 
105          * @param name
106          *            module name
107          * @param filename
108          *            file name
109          */
110         public void launch(final String name, final String filename) {
111                 String module = name;
112                 try {
113
114                         // Opening a Web page in a new tab
115                         if (module.startsWith("http")) {
116                                 getAppletContext().showDocument(new URL(module), "_blank");
117                         } else
118
119                         // Opening a Web module in a new tab
120                         if (module.startsWith("../") || module.startsWith("/")) {
121                                 module = getCodeBase().toString() + module;
122                                 if (filename != null) {
123                                         module = module + "?open=" + filename;
124                                 }
125                                 getAppletContext().showDocument(new URL(module), "_blank");
126                         } else
127
128                         // Opening an application on the local machine
129
130                         if ("runSalome".equals(module)) {
131                                 salomeCheckout(filename);
132                         } else
133
134                         if (module.endsWith(".exe") || module.endsWith(".EXE")) {
135                                 String applikey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Applications\\"
136                                                 + module;
137                                 String valkey = ""; // Default application and file keys
138
139                                 module = WindowsRegistry.readValue(applikey
140                                                 + "\\shell\\open\\command", valkey);
141                                 if (module == null) {
142                                         module = WindowsRegistry.readValue(applikey
143                                                         + "\\shell\\edit\\command", valkey);
144                                 }
145                                 // if (module == null) module = "\"C:\\Program Files (x86)\\Microsoft Office\\Office14\\WINWORD.EXE\"";
146                                 if (module == null) {
147                                         module = getCodeBase().toString()
148                                                         + "error.jsp?message=launch&value=" + name;
149                                         getAppletContext().showDocument(new URL(module));
150                                 } else {
151                                         String[] parse = module.split("/");
152                                         String command = parse[0]; // Removing eventual options
153                                         if (filename != null) {
154                                                 String path = "";
155                                                 // Opening the application with a server side existing file
156                                                 if (filename.startsWith("http")) {
157                                                         path = " \"" + filename + "\"";
158                                                 }
159                                                 // Opening the application with a file previously created by the server
160                                                 else if (filename.startsWith("/jsp")) { // Document created through a JSP
161                                                         URL my = getDocumentBase();
162                                                         String http = "http://" + my.getHost() + ":"
163                                                                         + my.getPort() + "/";
164                                                         String[] jsppath = my.getPath().split("/"); // Parses "/webapp/..."
165                                                         String location = http + jsppath[1] + filename;
166
167                                                         URLConnection connection = new URL(location)
168                                                                         .openConnection();
169                                                         ObjectInputStream fromservlet = new ObjectInputStream(
170                                                                         connection.getInputStream());
171                                                         URL docurl = (URL) fromservlet.readObject();
172
173                                                         fromservlet.close();
174                                                         if (docurl != null) {
175                                                                 path = " " + docurl.toString();
176                                                         }
177                                                 }
178                                                 command = command + path;
179                                         }
180                                         Runtime.getRuntime().exec(command);
181                                 }
182                         }
183                 } catch (Exception error) {
184                         error.printStackTrace(); // RKV: NOPMD: Applet output
185                 }
186         }
187         
188         /**
189          * The class that reads output of the process passed in constructor in a separate thread.
190          * (a quick fix to the problem that we need to read bash script
191          * output in order for it to proceed correctly).
192          */
193         class ScriptOutputReader implements Runnable {
194
195                 /**
196                  * A quick fix to the problem that we need to read bash script output in order for it to proceed correctly.
197                  */
198                 Process _proc;
199
200                 /**
201                  * Constructor from process to take output from.
202                  * @param proc
203                  *              the process to read from.
204                  */
205                 public ScriptOutputReader(final Process proc) {
206                         _proc = proc;
207                 }
208
209                 /** 
210                  * {@inheritDoc}
211                  * @see java.lang.Runnable#run()
212                  */
213                 @Override
214                 public void run() {
215                         try {
216                                 BufferedReader bri = new BufferedReader(new InputStreamReader(
217                                                 _proc.getInputStream()));
218                                 BufferedReader bre = new BufferedReader(new InputStreamReader(
219                                                 _proc.getErrorStream()));
220                                 String line = bri.readLine();
221                                 while (line != null) {
222                                         System.out.println(line); // RKV: NOPMD: Applet output
223                                         line = bri.readLine();
224                                 }
225                                 bri.close();
226                                 line = bre.readLine();
227                                 while (line != null) {
228                                         System.err.println(line); // RKV: NOPMD: Applet output
229                                         line = bre.readLine();
230                                 }
231                                 bre.close();
232                         } catch(Exception e) {
233                                 // NOPMD: empty catch block - nothing really to do here.
234                         }
235                 }
236         }
237
238         /**
239          * Checkout a scenario and start Salome with it.
240          * 
241          * @param params
242          *            Salome parameters
243          * @throws IOException
244          *             if URL connection opening/reading is failed
245          * @throws ConfigurationException
246          *             if SALOME_ROOT_DIR environment variable is not defined or Salome launcher script is not found
247          */
248         private void salomeCheckout(final String params)
249                         throws ConfigurationException, IOException {
250                 // Run SALOME
251                 // To get the SALOME_HOME environment variable
252                 String SALOME_HOME = System.getenv("SALOME_ROOT_DIR");
253                 // If SALOME_ROOT_DIR does not exist the SALOME_HOME equals to null.
254                 if (SALOME_HOME == null) {
255                         showError("SALOME_ROOT_DIR environment variable is not defined.");
256                         throw new ConfigurationException(
257                                         "SALOME_ROOT_DIR nevironment variable is not defined.");
258                 } else if (!SALOME_HOME.endsWith(File.separator)) {
259                         SALOME_HOME += File.separator;
260                 }
261                 String pathToScript = SALOME_HOME + File.separator + RUN_SALOME_SCRIPT;
262                 File script = new File(pathToScript);
263                 String extensions = "";
264                 // Look for the launching script in the file system
265                 for (String ext : SCRIPT_EXT) {
266                         script = new File(pathToScript + ext); // RKV: NOPMD: There are not so much extensions
267                         if (script.exists()) {
268                                 break;
269                         }
270                         extensions += "|" + ext;
271                 }
272
273                 if (script.exists()) {
274
275                         // Call to the Siman server to checkout the scenario
276                         URL checkoutUrl = new URL(getCodeBase().toString()
277                                         + "checkout.action?"
278                                         + params.replaceAll("--siman-", "&").replaceAll("\\s", ""));
279
280                         BufferedReader buffer = new BufferedReader(new InputStreamReader(
281                                         checkoutUrl.openStream()));
282
283                         // Read the response of the Siman server
284                         boolean isOk = false;
285                         String response = buffer.readLine();
286                         while ((response != null)) {
287                                 if (response.contains(CHECKOUT_RES)) {
288                                         isOk = response.contains(CHECKOUT_RES + " \"true\"");
289                                         break;
290                                 }
291                                 response = buffer.readLine();
292                         }
293                         buffer.close();
294
295                         if (isOk) {
296                                 // Execute the runSalome script.
297                                 // filename here indeed a string containing parameters for runSalome.
298                                 List<String> cmd = new ArrayList<String>(Arrays.asList(params
299                                                 .split("\\s")));
300                                 cmd.add(0, script.getAbsolutePath());
301                                 Process proc = Runtime.getRuntime().exec(
302                                                 cmd.toArray(new String[] {}), null,
303                                                 new File(SALOME_HOME));
304                                 
305                                 // Read script's output in separate thread.
306                                 ScriptOutputReader appletOutputReader = new ScriptOutputReader(proc);
307                                 Thread thread = new Thread(appletOutputReader);
308                                 thread.start();
309                         } else {
310                                 // Checkout of the scenario is failed at the beginning.
311                                 if (response != null) {
312                                         response = response.substring(
313                                                         response.indexOf(CHECKOUT_RES)
314                                                                         + CHECKOUT_RES.length()).replace('}', ' ')
315                                                         .replace('"', ' ');
316                                         showError(response);
317                                 }
318                         }
319                         
320                         // Refresh the current scenario view
321                         getAppletContext().showDocument(
322                                         new URL(this.getParameter("refresh")));
323                 } else {
324                         extensions = "[" + extensions.replaceAll("\\|\\|", "") + "]";
325                         showError("SALOME module is not found: " + pathToScript
326                                         + extensions);
327                         throw new ConfigurationException("SALOME module is not found: "
328                                         + pathToScript + extensions);
329                 }
330         }
331
332         /**
333          * Show error message in the new window.
334          * 
335          * @param message
336          *            the error message
337          * @throws MalformedURLException
338          *             if built URL is incorrect
339          * @throws UnsupportedEncodingException
340          *             if UTF-8 encoding is not supported
341          */
342         private void showError(final String message) throws MalformedURLException,
343                         UnsupportedEncodingException {
344                 getAppletContext().showDocument(
345                                 new URL(getCodeBase().toString() + "../error.jsp?error="
346                                                 + URLEncoder.encode(message, "UTF-8")), "_blank");
347         }
348 }