There is no question here (though discussion of the code is welcome).
/ Update 1 /
Now available as a stand alone or webstart app.! The STBC (see the web page*) has its own web page and has been improved to allow the user to browse to a tools.jar if one is not found on the runtime classpath, or in the JRE running the code. See http://pscode.org/stbc/.
/ End: Update 1 /
This simple example of using the JavaCompiler made available in Java 1.6 might be of use to check that your SSCCE is actually what it claims to be!
If an SSCCE claims to display a runtime problem, it should compile cleanly when pasted into the text area above the *Compile button. For a compilation problem, the code should show the same output errors seen in your own editor (at least until the last line of the output in the text area).
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.EventQueue;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;
import java.util.ArrayList;
import java.net.URI;
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler;
import javax.tools.SimpleJavaFileObject;
/** A simple Java compiler with a GUI. Java 1.6+.
@author Andrew Thompson
@version 2008-06-13
*/
publicclass GuiCompiler extends JPanel {
/** Instance of the compiler used for all compilations. */
JavaCompiler compiler;
/** The name of the public class. For 'HelloWorld.java',
this would be 'HelloWorld'. */
JTextField name;
/** The source code to be compiled. */
JTextArea sourceCode;
/** Errors and messages from the compiler. */
JTextArea output;
JButton compile;
staticint pad = 5;
GuiCompiler() {
super( new BorderLayout(pad,pad) );
setBorder( new EmptyBorder(7,4,7,4) );
}
/** A worker to perform each compilation. Disables
the GUI input elements during the work. */
class SourceCompilation extends SwingWorker<String, Object> {
@Override
public String doInBackground() {
return compileCode();
}
@Override
protectedvoid done() {
try {
enableComponents(true);
} catch (Exception ignore) {
}
}
}
/** Construct the GUI. */
publicvoid initGui() {
JPanel input = new JPanel( new BorderLayout(pad,pad) );
Font outputFont = new Font("Monospaced",Font.PLAIN,12);
sourceCode = new JTextArea("Paste code here..", 15, 60);
sourceCode.setFont( outputFont );
input.add( new JScrollPane( sourceCode ),
BorderLayout.CENTER );
sourceCode.select(0,sourceCode.getText().length());
JPanel namePanel = new JPanel(new BorderLayout(pad,pad));
name = new JTextField(15);
name.setToolTipText("Name of the public class");
namePanel.add( name, BorderLayout.CENTER );
namePanel.add( new JLabel("Class name"), BorderLayout.WEST );
input.add( namePanel, BorderLayout.NORTH );
compile = new JButton( "Compile" );
compile.addActionListener( new ActionListener() {
publicvoid actionPerformed(ActionEvent ae) {
(new SourceCompilation()).execute();
}
} );
input.add( compile, BorderLayout.SOUTH );
this.add( input, BorderLayout.CENTER );
output = new JTextArea("", 5, 40);
output.setFont( outputFont );
output.setEditable(false);
this.add( new JScrollPane( output ), BorderLayout.SOUTH );
}
/** Compile the code in the source input area. */
public String compileCode() {
output.setText( "Compiling.." );
enableComponents(false);
String compResult = null;
if (compiler==null) {
compiler = ToolProvider.getSystemJavaCompiler();
}
if ( compiler!=null ) {
String code = sourceCode.getText();
String sourceName = name.getText().trim();
if ( sourceName.toLowerCase().endsWith(".java") ) {
sourceName = sourceName.substring(
0,sourceName.length()-5 );
}
JavaSourceFromString javaString = new JavaSourceFromString(
sourceName,
code);
ArrayList<JavaSourceFromString> al =
new ArrayList<JavaSourceFromString>();
al.add( javaString );
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter osw = new OutputStreamWriter( baos );
JavaCompiler.CompilationTask task = compiler.getTask(
osw,
null,
null,
null,
null,
al);
boolean success = task.call();
output.setText( baos.toString().replaceAll("\t", " ") );
compResult = "Compiled without errors: " + success;
output.append( compResult );
output.setCaretPosition(0);
} else {
output.setText( "No compilation possible - sorry!" );
JOptionPane.showMessageDialog(this,
"No compiler is available to this runtime!",
"Compiler not found",
JOptionPane.ERROR_MESSAGE
);
System.exit(-1);
}
return compResult;
}
/** Set the main GUI input components enabled
according to the enable flag. */
publicvoid enableComponents(boolean enable) {
compile.setEnabled(enable);
name.setEnabled(enable);
sourceCode.setEnabled(enable);
}
publicstaticvoid main(String[] args) throws Exception {
Runnable r = new Runnable() {
publicvoid run() {
JFrame f = new JFrame("SSCCE text based compiler");
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
GuiCompiler compilerPane = new GuiCompiler();
compilerPane.initGui();
f.getContentPane().add(compilerPane);
f.pack();
f.setMinimumSize( f.getSize() );
f.setLocationRelativeTo(null);
f.setVisible(true);
}
};
EventQueue.invokeLater(r);
}
}
/**
* A file object used to represent source coming from a string.
* This example is from the JavaDocs for JavaCompiler.
*/
class JavaSourceFromString extends SimpleJavaFileObject {
/**
* The source code of this "file".
*/
final String code;
/**
* Constructs a new JavaSourceFromString.
* @param name the name of the compilation unit represented
by this file object
* @param code the source code for the compilation unit
represented by this file object
*/
JavaSourceFromString(String name, String code) {
super(URI.create(
"string:///" +
name.replace('.','/') +
Kind.SOURCE.extension),
Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
Edit 1:
Added..
f.setMinimumSize( f.getSize() );
Edited by: AndrewThompson64 on Jun 13, 2008 12:24 PM
Edited by: AndrewThompson64 on Jun 23, 2008 5:54 AM
Re: Example code for java compiler with a simple GUI
Jun 26, 2008 5:15 AM
(reply 2
of 11) (In reply to
#1 )
The latest code/source and build file (used for the current binary and web page) can be downloaded in the Download Development Files section of the page.
Any ..
- bug reports?
- suggestions?
- corrections?
Re: Example code for java compiler with a simple GUI
Jun 26, 2008 5:23 AM
(reply 3
of 11) (In reply to
#2 )
AndrewThompson64 wrote:
The latest code/source and build file (used for the current binary and web page) can be downloaded in the Download Development Files section of the page.
Any ..
- bug reports?
- suggestions?
- corrections?
Yes, don't post your source code here. Use SDN Share if you want to share code, or sourceforge .
Re: Example code for java compiler with a simple GUI
Jun 26, 2008 6:06 AM
(reply 6
of 11) (In reply to
#5 )
JoachimSauer wrote:
{quote:title=AndrewThompson64 wrote:}
Any ..
- suggestions?
Include the Eclipse Java Compiler to be completely free of the requirement for configuring the JDK path, or even requiring the JDK.{quote}
This tool is mostly aimed at Java developers who need to post code examples for others, either privately in email, or onto web forums or usenet. I am guessing most of them would have an SDK, so I will most probably leave this code as is.
I am curious though.
1) Is the Eclipse compiler freely distributable?
2) How big is it?
3) Would it work with the original code (using the JavaCompiler interface)?
( 4) and if three is 'no', would it work in pre 1.6? )
Re: Example code for java compiler with a simple GUI
Jun 26, 2008 6:16 AM
(reply 7
of 11) (In reply to
#6 )
AndrewThompson64 wrote:
This tool is mostly aimed at Java developers who need to post code examples for others, either privately in email, or onto web forums or usenet. I am guessing most of them would have an SDK, so I will most probably leave this code as is.
I understand, I think requiring the SDK would not be a problem, but having to configure the location sounds tiresome (I've not actually tried it, to be honest).
I am curious though.
1) Is the Eclipse compiler freely distributable?
It's probably under the EPL, which allows pretty free usage.
2) How big is it?
The jar file I've got locally for the standalone compiler is 1.2MB. I don't know if all of that is necessary.
3) Would it work with the original code (using the JavaCompiler interface)?
I don't think so.
( 4) and if three is 'no', would it work in pre 1.6? )
It will definitely work in 1.5. It might even work in 1.4, but I'm not sure.
1. A button to run the code, to see that it demonstrates the problem that you wish for the forum to solve...
2. Line numbering, and/or a line counter so you can see how much scrolling you're going to be imposing on the forum readers.
Re: Example code for java compiler with a simple GUI
Jun 26, 2008 6:23 AM
(reply 9
of 11) (In reply to
#3 )
kajbj wrote:
{quote:title=AndrewThompson64 wrote:}
The latest code/source and build file
...
Any ..
- bug reports?
- suggestions?
...
Yes, don't post your source code here. Use SDN Share if you want to share code, or sourceforge .{quote}
I do not believe SourceForge is appropriate for these type of examples, but SDNShare looks interesting, I will definitely be posting some examples over there. Thanks for the tip - I had not heard of SDNShare before this.
Pity they do not have the very pretty code formatting available on these forums, but if the 'pilot' is anything to go by, it might happen in the future.
On the other hand, for this thread, I was remiss in not asking a specific question on the original post. It was a cute and (perhaps) good little example, but I had only begun to appreciate the intricacies of using the JavaCompiler, and could perhaps have shortcut the learning curve by soliciting broader advice on compilation in 1.6.
Re: Example code for java compiler with a simple GUI
Jun 28, 2008 1:43 AM
(reply 10
of 11) (In reply to
#8 )
kevjava wrote:
Some things that I think would be useful:
Suggestions reordered to suit my reply..
kevjava wrote:
2. Line numbering, and/or a line counter so you can see how much scrolling you're going to be imposing on the forum readers.
Good idea, and since the line count is only a handful of lines of code to implement, I took that option. See the line count section of the (new) STBC Help page for more details. (Insert plaintiff whining about the arbitrary limits set - here).
I considered adding line length checking, but the Text Width Checker ('sold separately') already has that covered, and I would prefer to keep this tool more specific to compilation, which leads me to..
kevjava wrote:
1. A button to run the code, to see that it demonstrates the problem that you wish for the forum to solve...
Interesting idea, but I think that is better suited to a more full blown (but still relatively simple) GUId compiler. I am not fully decided that running a class is unsuited to STBC, but I am more likely to implement a clickable list of compilation errors, than a 'run' button.
On the other hand I am thinking the clickable error list is also better suited to an altogether more abled compiler, so don't hold your breath to see either in the STBC.
You might note I have not bothered to update the screenshots to show the line count label. That is because I am still considering error lists and running code, and open to further suggestion (not because I am just slack!). If the screenshots update to include the line count but nothing else, take that as a sign. ;-)
Thanks for your ideas. The line count alone is worth a few Dukes.
Re: Example code for java compiler with a simple GUI
Jun 28, 2008 2:05 AM
(reply 11
of 11) (In reply to
#7 )
AndrewThompson64 wrote:
This tool is mostly aimed at Java developers who need to post code examples for others, either privately in email, or onto web forums or usenet. I am guessing most of them would have an SDK, so I will most probably leave this code as is.
JoachimSauer wrote:
I understand, I think requiring the SDK would not be a problem, but having to configure the location sounds tiresome (I've not actually tried it, to be honest).
I was hoping to get some feedback on that aspect. Configuration is always a pain, but I have attempted to make it as easy as practical by opening a JFileChooser pointing to java.home. I figure that should get the user to very near where a JDK lives - probably just by selecting the parent directory, then selecting the JDK they (hopefully) already have. But of course, what seems intuitively simple to me, might turn out to be complicated and unworkable for others.
(snip details on using Eclipse compiler)
JoachimSauer wrote:
..
It will definitely work in 1.5. It might even work in 1.4, but I'm not sure.
Thanks for those details. From your description it seems the Eclipse option deserves mention as a 'See Also' (..mutters though I might try getting Roedy to add it to the links in his On-The-Fly compilation page - I note he has already linked to this thread!).