/** * * This is MATLAB Server Pages (MSP) Interface. * Dedicated to my grand mother and my love. * MSP allows you to use MATLAB on Web with a easy syntax including Java/JSP/Faces Features. * MSP supports Expression Language, JSTL and Faces Tag Libraries and HTML/JSP Syntax. * MSP is based on Stefan Mueller's JMatLink 1.00, which is used as Java MATLAB Communication Interface. * * @author Ali KIZIL * @link http://msp.sourceforge.net * @version 1.0 * @since Mar 29, 2005 * * MSP Tag Library * --------------- * * Engine: Starts MATLAB engine for computing (Single Use). * SessionStart: Starts MATLAB engine for computing (Multi Use, Session based). * SessionGet: Connects to specified MATLAB session. * SesisonEnd: Closes MATLAB session. * Command: Executes MATLAB commands. * Clean: Deletes all JPG and BMP images in Image directory, removes MAT files in Code dir. * Debug: See where the problem is in MATLAB syntax. * EvalMDL: Executes Simulink Models. * EvalMFile: Executes MATLAB M-Files. * EvalMLSF: Executes MSP Files, which can be a bunch of MATLAB commands. * GetArray: Get MATLAB array (2D) in to Java. Ex: magic(10) * GetVector: Get MATLAB vector (1D) in to Java. Ex: rand(1,10) or rand(10,1) * GetScalar: Get MATLAB scalar in to Java. Ex: sqrt(9), exp(8) etc. * GetCharArray: Get MATLAB string (char) array in to Java. Ex: 'Hello World' * GetParam: Gets HTTP input form. * PlotData: Plots MATLAB figure. * PlotModel: Draws Simulink model. * PlotSim: Plot Simulink result. * Thumbnail: Creates thumbnail for MATLAB figure. * PutArray: Put Java double[][] to MATLAB. * PutVector: Put Java double[] to MATLAB. * PutScalar: Put Java double to MATLAB. * WriteData: Writes MATLAB variable to web page; including array, vector, * scalar, char array, cell and structure. * */ // goOnline is in a package called "line" for future developments. package line; import java.awt.*; // For creating thumbnail import java.awt.image.*; // For creating thumbnail import com.sun.image.codec.jpeg.*; // For creating thumbnail import java.io.*; // For MLSF file processing import rmi.goOnlineRmiInterface; // For RMI import java.rmi.RemoteException; // For RMI import java.rmi.server.UnicastRemoteObject; // For RMI import java.util.ResourceBundle; // For setitng location of Code dir and Image dir. import javax.servlet.jsp.JspWriter; // For writing data to web page. import javax.servlet.http.HttpSession; // For multi usage of MATLAB import javax.servlet.jsp.PageContext; // For interfacing with JSP import jmatlink.JMatLink; // ****************************** goOnline ******************************** /** goOnline is a MATLAB - JSP interface. * * <p>E.g.:<br> * <pre> * * goOnline goOnline = new goOnline(); * </pre> ******************************************************************************/ public class goOnline extends UnicastRemoteObject implements goOnlineRmiInterface { private static final long serialVersionUID = 1640549572470193380L; /** * Constructor * @throws RemoteException */ public goOnline() throws RemoteException { super(); } // Define Stefan Mueller's JMatLink object. See its documentation for usage. private JMatLink javaLink; // Define 2D double Java array (Send Java array to MATLAB, Get MATLAB array to Java) private double[][] array = null; // Define 1D double Java vector (Send Java array to MATLAB, Get MATLAB array to Java) private double[] vector = null; // Define double Java scalar (Send Java scalar to MATLAB, Get MATLAB scalar to Java) private double scalar; // Define Java string array (Send Java string array to MATLAB, Get MATLAB string array to Java) private String[] chararray = null; // Define the path of Code dir private String Code_Dir; // Define the path of Image dir private String Image_Dir; // Define the web link for images. private String link = null; // ********************************* clean ******************************** /** Delete JPG and BMP images from Image dir and remove MAT files from Code dir. * * <p>E.g.:<br> * <pre> * goOnline.Command("save savefile"); * goOnline.clean(); * </pre> ******************************************************************************/ public void clean() { // Deletes all MAT files in Code dir. javaLink.engEvalString("delete *.mat"); // Directs to Image dir. javaLink.engEvalString("cd " + Image_Dir); // Deletes all JPG and BMP files in Image dir. javaLink.engEvalString("delete *.jpg"); javaLink.engEvalString("delete *.bmp"); } // ******************************** command ******************************** /** Executes MATLAB commands * * <p>E.g.:<br> * <pre> * goOnline.command("a=magic(10)"); * </pre> ******************************************************************************/ public void command(String cmd) { // Executes MATLAB Command. javaLink.engEvalString(cmd); } // ********************************* debug ******************************** /** Debug MATLAB syntax errors. If type is Code, it debugs MATLAB command line. * If type is Model, it debugs Simulink model usage. * * <p>E.g.:<br> * <pre> * goOnline.Command("a = magic10)"); * goOnline.debug("Code", JspWriter); * </pre> ******************************************************************************/ public void debug(String type, JspWriter out) { if (type == "Code") { // MATLAB lasterr dispalys the last occured error. javaLink.engEvalString("err = lasterr;"); } if (type == "Model") { // Always a mspsimdebug MAT file is created, // its coded at evalMDL. This creates error, // if any occured. javaLink.engEvalString("load mspsimdebug"); javaLink.engEvalString("error(s)"); javaLink.engEvalString("err = lasterr;"); } try { // Setting the color and display of MATLAB syntax error. out.println("<b><font color=\"#336699\">"); writeData("err", out); out.println("</font></b>"); } catch (IOException e) { System.out.println("MSP Error: "+e.getMessage()); } } // ***************************** engineOpen ******************************** /** Starts a single use MATLAB computing engine. * * <p>E.g.:<br> * <pre> * goOnline.engineOpen(); * </pre> ******************************************************************************/ public void engineOpen() { // Reads MSP settings from Bundle. ResourceBundle rb = ResourceBundle.getBundle("MSP"); // Code Dir is the base for MATLAB M-Files, Simulink Models and // Matlab Server Files. All runnable codes and models must be // there. Code_Dir = rb.getString("Code_directory"); // Image Dir is the base for MATLAB created images. Image_Dir = rb.getString("Image_directory"); // System out out for Java debugger. System.out.println("MATLAB Server Pages Engine"); javaLink = new JMatLink(); // This was the wrong call - it looks like there has been a cnage of interface // javaLink.engOpenSingleUse(); javaLink.engOpen(); // Running MSP at Code Dir. javaLink.engEvalString("cd '" + Code_Dir + "'"); } // ***************************** engineClose ******************************* /** Close MATLAB computing engine. * * <p>E.g.:<br> * <pre> * goOnline.engineClose(); * </pre> ******************************************************************************/ public void engineClose() { // Closes MATLAB. javaLink.engClose(); // Ends thread. javaLink.kill(); } // ****************************** evalMDL ********************************* /** Executes Simulink Model. * * <p>E.g.:<br> * <pre> * goOnline.evalMDL("sim1","loadmat","savemat"); * </pre> * * mspsim: (P-Coded) * ------- * * function s = mspsim(openname,loadname,savename) * * try * open_system(openname); * * if isempty(loadname) == 0 * set_param(openname,'InitFcn',['load ',loadname]) * end * * sim(openname); * save_system(openname); * close_system(openname); * * if isempty(savename) == 0 * save(savename); * end * * s=''; * catch * s = lasterr; * end * * save mspsimdebug s * exit; ******************************************************************************/ public void evalMDL(String modelname, String loadname, String savename) { // Executes mspsim M-File. javaLink.engEvalString("!matlab -nosplash -minimize -r mspsim('" + modelname + "','" + loadname + "','" + savename + "')"); } // ***************************** evalMFile ******************************** /** Executes MATLAB M-File. * * <p>E.g.:<br> * <pre> * goOnline.evalMFile("matlabscript.m"); * </pre> * * matlabscript.m: * --------------- * for i=1:10 * s(i) = i*2; * end * * Mostly for easy typing MATLAB conditionals and loops. ******************************************************************************/ public void evalMFile(String name) { // Evaluates MATLAB M-File. javaLink.engEvalString("eval('" + name + "');"); } // ****************************** evalMLSF ******************************** /** Executes MATLAB Server File. * See input.mlsf and output.mlsf * * <p>E.g.:<br> * <pre> * goOnline.evalMLSF("input","output", JspWriter); * </pre> * * input.mlsf: * ----------- * a = magic(10); * b = pascal(10); * c = a*b; * * output.mlsf: * ------------ * c * ******************************************************************************/ public void evalMLSF(String input, String output, JspWriter out) { try { // Reads Input MLSF. FileReader fr = new FileReader(Code_Dir + input + ".mlsf"); BufferedReader rd = new BufferedReader(fr); String line; while ((line = rd.readLine()) != null) { // Executes every line. javaLink.engEvalString(line); } rd.close(); fr.close(); if (output != null) { // Reads Output MLSF. If null, only Input MLSF is executed. FileReader fr2 = new FileReader(Code_Dir + output + ".mlsf"); BufferedReader rd2 = new BufferedReader(fr2); String line2; while ((line2 = rd2.readLine()) != null) { // Writes every variable mentioned at Output MLSF. writeData(line2, out); } rd2.close(); fr2.close(); } } catch (FileNotFoundException e) { System.out.println("MSP Error: "+e.getMessage()); } catch (IOException e) { System.out.println("MSP Error: "+e.getMessage()); } } // ****************************** getArray ******************************** /** Gets MATLAB 2D array to Java. * * <p>E.g.:<br> * <pre> * goOnline.Command("magic(10)"); * goOnline.getArray(a); * </pre> ******************************************************************************/ public void getArray(String name) { array = javaLink.engGetArray(name); } // ****************************** getVector ******************************* /** Gets MATLAB vector to Java. * * <p>E.g.:<br> * <pre> * goOnline.Command("a=rand(1,10)"); * goOnline.getVector("a"); * </pre> ******************************************************************************/ public void getVector(String name) { double[][] k = javaLink.engGetArray(name); vector = k[0]; } // ****************************** getScalar ******************************** /** Gets MATLAB scalar to Java. * * <p>E.g.:<br> * <pre> * goOnline.Command("s = exp(1)"); * goOnline.getScalar("s"); * </pre> ******************************************************************************/ public void getScalar(String name) { scalar = javaLink.engGetScalar(name); } // ***************************** getCharArray ****************************** /** Get MATLAB string to Java. * * <p>E.g.:<br> * <pre> * goOnline.Command(v = version;); * goOnline.getCharArray("v"); * </pre> ******************************************************************************/ public void getCharArray(String name) { chararray = javaLink.engGetCharArray(name); } /** * @return Returns the array. */ public double[][] getArray() { return array; } /** * @return Returns the chararray. */ public String[] getChararray() { return chararray; } /** * @return Returns the scalar. */ public double getScalar() { return scalar; } /** * @return Returns the vector. */ public double[] getVector() { return vector; } // ******************************* getParam ******************************** /** Executes MATLAB web requests from input forms. * * <p>E.g.:<br> * <pre> * goOnline goOnline = new goOnline(); * goOnline.getParam("webin","input1",goOnline,pageContext); * </pre> ******************************************************************************/ public void getParam(String filename, String parameter, PageContext pageContext) { try { // Creates a MLSF file from text area. PrintWriter textIn = new PrintWriter(new BufferedWriter(new FileWriter(Code_Dir+filename+".mlsf"))); String input = pageContext.getRequest().getParameter(parameter); textIn.println(input); textIn.close(); } catch (IOException e) { System.out.println("MSP Error: "+e.getMessage()); } } public void multiCommand(String text) { command(text.replaceAll("\n","").trim()); } // ****************************** plotData ****************************** /** Plots MATLAB figure. * * <p>E.g.:<br> * <pre> * goOnline.plotData("surf(peaks)","h","image1"); * </pre> *****************************************************************************/ public String plotData(String cmd, String handle, String filename) { if (handle == null) { // Some MATLAB graphics are not runnable with handle. javaLink.engEvalString(cmd); javaLink.engEvalString("saveas(gcf,'" + filename + "','jpg');"); } else { javaLink.engEvalString(handle + "=" + cmd); javaLink.engEvalString("saveas(" + handle + ",'" + filename + "','jpg');"); } // Moves image from code dir to image dir. javaLink.engEvalString("movefile('" + filename + ".jpg','" + Image_Dir + "','f');"); // Creates a hyperlink. link = "<img src=\"../Image/" + filename + ".jpg\">"; return link; } // ****************************** plotModel ****************************** /** Plots MATLAB figure. * * <p>E.g.:<br> * <pre> * goOnline.plotModel("sim1","h","portrait"); * </pre> * * mspmodel: (P-Coded) * --------- * function s = mspmodel(openname,orientation,filename) * * try * open_system(openname); * eval(sprintf('orient(''%s'',''%s'')',openname,orientation)); * eval(sprintf('print -s%s -dbmp16 %s',openname,filename)); * save_system(openname); * close_system(openname); * s=''; * catch * s = lasterr; * end * * save mspsimdebug s * exit; * ******************************************************************************/ public String plotModel(String simname, String orientation, String filename) { // Executes mspmodel M-File. javaLink.engEvalString("!matlab -nosplash -minimize -r mspmodel('" + simname + "','" + orientation + "','" + filename + "')"); javaLink.engEvalString("movefile('" + filename + ".bmp','" + Image_Dir + "','f');"); link = "<img src=\"../Image/" + filename + ".bmp\">"; return link; } // ****************************** plotSim ****************************** /** Plots Simulink result. (In Time Structure Array Type) * * <p>E.g.:<br> * <pre> * goOnline.plotSim("h","simout1","simimage1"); * </pre> *****************************************************************************/ public String plotSim(String handle, String simresult, String filename) { if (handle == null) { javaLink.engEvalString("simplot(" + simresult + ");"); javaLink.engEvalString("saveas(gcf,'" + filename + "','jpg');"); } else { javaLink.engEvalString(handle + "=simplot(" + simresult + ");"); javaLink.engEvalString("saveas(" + handle + ",'" + filename + "','jpg');"); } javaLink.engEvalString("movefile('" + filename + ".jpg','" + Image_Dir + "','f');"); link = "<img src=\"../Image/" + filename + ".jpg\">"; return link; } // ******************************* putArray ****************************** /** Sends Java double[][] to MATLAB. * * <p>E.g.:<br> * <pre> * array = {{1,2,3},{4,5,6}}; * goOnline.putArray("MatlabVariableName",array) * </pre> *****************************************************************************/ public void putArray(String variable) { javaLink.engPutArray(variable, array); } // ******************************* putVector ***************************** /** Sends Java double[] to MATLAB. * * <p>E.g.:<br> * <pre> * vector = {-1,0,1} * goOnline.putVector("MatlabVariableName",vector) * </pre> *****************************************************************************/ public void putVector(String variable) { javaLink.engPutArray(variable, vector); } // ******************************* putScalar ****************************** /** Sends Java double to MATLAB. * * <p>E.g.:<br> * <pre> * scalar = 3; * goOnline.putArray("MatlabVariableName",scalar) * </pre> *****************************************************************************/ public void putScalar(String variable) { javaLink.engPutArray(variable, scalar); } // ***************************** sessionStart ****************************** /** Starts MATLAB for multi use as a session object. * * <p>E.g.:<br> * <pre> * goOnline goOnline = new goOnline(); * goOnline.sessionStart(goOnline, "session1", pageContext); * </pre> *****************************************************************************/ public void sessionStart(goOnline goOnline, String name, PageContext pageContext) { goOnline.engineOpen(); // Sets MATLAB as a session. HttpSession session = pageContext.getSession(); session.setAttribute(name,goOnline); } // ******************************* sessionEnd ****************************** /** Ends MATLAB session. * * <p>E.g.:<br> * <pre> * goOnline goOnline = new goOnline(); * goOnline.sessionEnd(goOnline, "session1", pageContext); * </pre> *****************************************************************************/ public void sessionEnd(goOnline goOnline, String name, PageContext pageContext) { // Gets session HttpSession session = pageContext.getSession(); // Converts object to goOnline. goOnline = (goOnline)session.getAttribute(name); // Closes MATLAB. goOnline.engineClose(); // Removes session variable. session.removeAttribute(name); } // ****************************** sessionGet ****************************** /** Connects to a MATLAB session. * * <p>E.g.:<br> * <pre> * goOnline goOnline = new goOnline(); * goOnline.sessionGet(goOnline, "session1", pageContext); * </pre> *****************************************************************************/ public void sessionGet(goOnline goOnline, String name, PageContext pageContext) { // Gets session. HttpSession session = pageContext.getSession(); goOnline = (goOnline)session.getAttribute(name); // Sets as page attribute. pageContext.setAttribute("goOnline",goOnline); } /** * @param array The array to set. */ public void setArray(double[][] array) { this.array = array; } /** * @param chararray The chararray to set. */ public void setChararray(String[] chararray) { this.chararray = chararray; } /** * @param scalar The scalar to set. */ public void setScalar(double scalar) { this.scalar = scalar; } /** * @param vector The vector to set. */ public void setVector(double[] vector) { this.vector = vector; } // ******************************* thumbnail ****************************** /** Resize MATLAB figures to specified width and height. * * <p>E.g.:<br> * <pre> * goOnline.thumbnail("image1","300","300"); * </pre> *****************************************************************************/ public String thumbnail(String imagename, String width, String height) { // Written by Marco Schmidt // Changed for MSP by Ali KIZIL try { // load image from INFILE Image image = Toolkit.getDefaultToolkit().getImage( Image_Dir + "\\" + imagename + ".jpg"); MediaTracker mediaTracker = new MediaTracker(new Container()); mediaTracker.addImage(image, 0); mediaTracker.waitForID(0); // determine thumbnail size from WIDTH and HEIGHT int thumbWidth = Integer.parseInt(width); int thumbHeight = Integer.parseInt(height); double thumbRatio = (double) thumbWidth / (double) thumbHeight; int imageWidth = image.getWidth(null); int imageHeight = image.getHeight(null); double imageRatio = (double) imageWidth / (double) imageHeight; if (thumbRatio < imageRatio) { thumbHeight = (int) (thumbWidth / imageRatio); } else { thumbWidth = (int) (thumbHeight * imageRatio); } // draw original image to thumbnail image object and // scale it to the new size on-the-fly BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB); Graphics2D graphics2D = thumbImage.createGraphics(); graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null); // save thumbnail image to OUTFILE BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream(Image_Dir + "\\" + imagename + "_tb.jpg")); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param = encoder .getDefaultJPEGEncodeParam(thumbImage); int quality = Integer.parseInt("100"); quality = Math.max(0, Math.min(quality, 100)); param.setQuality((float) quality / 100.0f, false); encoder.setJPEGEncodeParam(param); encoder.encode(thumbImage); out.close(); } catch (NumberFormatException e) { System.out.println("MSP Error: "+e.getMessage()); } catch (FileNotFoundException e) { System.out.println("MSP Error: "+e.getMessage()); } catch (ImageFormatException e) { System.out.println("MSP Error: "+e.getMessage()); } catch (InterruptedException e) { System.out.println("MSP Error: "+e.getMessage()); } catch (IOException e) { System.out.println("MSP Error: "+e.getMessage()); } link = "<img src=\"../Image/" + imagename + "_tb.jpg\">"; return link; } // ******************************* writeData ***************************** /** Writes MATLAB variables to web page. * * <p>E.g.:<br> * <pre> * goOnline.Command("a=magic(10)"); * goOnline.writeData("a",JspWriter); * </pre> *****************************************************************************/ public void writeData(String name, JspWriter out) { String type = null; int key2d = 0; try { // These commands defines the MATLAB variable class and size. javaLink.engEvalString("msp_tmp = whos('" + name + "');"); javaLink.engEvalString("msp_class = msp_tmp.class;"); javaLink.engEvalString("msp_size1 = msp_tmp.size(1);"); javaLink.engEvalString("msp_size2 = msp_tmp.size(2);"); String[] msp_class = javaLink.engGetCharArray("msp_class"); double msp_size1 = javaLink.engGetScalar("msp_size1"); double msp_size2 = javaLink.engGetScalar("msp_size2"); if (((msp_class[0]).equals("double"))) { if ((msp_size1 != 1) & (msp_size2 != 1)) type = "1"; if ((msp_size1 != 1) & (msp_size2 == 1)) { type = "2"; key2d = 0; // Transpoze the vector. // JMatLink only reads line vectors. javaLink.engEvalString(name + "=" + name + "'"); } if ((msp_size1 == 1) & (msp_size2 != 1)) { type = "2"; key2d = 1; } if ((msp_size1 == 1) & (msp_size2 == 1)) type = "3"; } if (((msp_class[0]).equals("char"))) type = "4"; if (((msp_class[0]).equals("cell"))) type = "5"; if (((msp_class[0]).equals("struct"))) type = "6"; } catch (NullPointerException e) { try { out.println("<b><font color=\"#558F05\">"); out.println("Undefined variable: " + name); out.println("</font></b>"); } catch (IOException e1) { System.out.println("MSP Error: "+e.getMessage()); } } try { switch (Integer.parseInt(type)) { case 1: array = javaLink.engGetArray(name); out.println("<table>"); for (int i = 0; i < array.length; i++) { out.println("<tr>"); double[] a; a = array[i]; for (int j = 0; j < a.length; j++) { out.println("<td>"); double b; b = a[j]; out.print(b); out.println("</td>"); } out.println("</tr>"); } out.println("</table>"); break; case 2: double[][] k = javaLink.engGetArray(name); vector = k[0]; out.println("<table>"); if (key2d == 0) { for (int i = 0; i < vector.length; i++) { out.println("<tr><td>" + vector[i] + "</tr></td>"); } } if (key2d == 1) { out.println("<tr>"); for (int i = 0; i < vector.length; i++) { out.println("<td>" + vector[i] + "</td>"); } out.println("</tr>"); } out.println("</table>"); break; case 3: scalar = javaLink.engGetScalar(name); out.print(scalar); break; case 4: chararray = javaLink.engGetCharArray(name); out.print(chararray[0]); break; case 5: // Cell and Structure arrays are not a standart // readable class for JMatLink. So its alternatively // written to a temp file and outputed to page. javaLink .engEvalString("for i=1:size(" + name + ",1), for j=1:size(" + name + ",2), str = " + name + "{i,j}; try, str=mat2str(str), catch, end, try, dlmwrite('msptmp.mlsf',str,'delimiter','','-append') ,catch, str='Avoid using structure or cell array in structure or cell array', dlmwrite('msptmp.mlsf',str,'delimiter','','-append'), end, end, end"); FileReader fr = new FileReader(Code_Dir + "msptmp.mlsf"); BufferedReader rd = new BufferedReader(fr); String line; while ((line = rd.readLine()) != null) { out.println(line); out.println("<br>"); } rd.close(); fr.close(); javaLink.engEvalString("delete msptmp.mlsf"); break; case 6: javaLink.engEvalString("mspdata = struct2cell(" + name + ")"); javaLink .engEvalString("for i=1:size(mspdata,1), for j=1:size(mspdata,2), str = mspdata{i,j}; try, str=mat2str(str), catch, end, try, dlmwrite('msptmp2.mlsf',str,'delimiter','','-append') ,catch, str='Avoid using structure or cell array in structure or cell array', dlmwrite('msptmp2.mlsf',str,'delimiter','','-append'), end, end, end"); FileReader fr2 = new FileReader(Code_Dir + "msptmp2.mlsf"); BufferedReader rd2 = new BufferedReader(fr2); String line2; while ((line2 = rd2.readLine()) != null) { out.println(line2); out.println("<br>"); } rd2.close(); fr2.close(); javaLink.engEvalString("delete msptmp2.mlsf"); break; } } catch (NumberFormatException e) { System.out.println("MSP Error: "+e.getMessage()); } catch (IOException e) { System.out.println("MSP Error: "+e.getMessage()); } } } // end of goOnline class.