001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.ui;
038:
039: import edu.rice.cs.drjava.model.OpenDefinitionsDocument;
040: import edu.rice.cs.drjava.model.GlobalModel;
041: import edu.rice.cs.drjava.model.definitions.InvalidPackageException;
042: import edu.rice.cs.util.UnexpectedException;
043: import edu.rice.cs.util.jar.JarBuilder;
044: import edu.rice.cs.util.jar.ManifestWriter;
045: import edu.rice.cs.util.swing.FileChooser;
046: import edu.rice.cs.util.swing.FileSelectorStringComponent;
047: import edu.rice.cs.util.swing.FileSelectorComponent;
048: import edu.rice.cs.util.swing.SwingWorker;
049: import edu.rice.cs.util.swing.Utilities;
050: import edu.rice.cs.util.newjvm.ExecJVM;
051: import edu.rice.cs.util.StreamRedirectThread;
052:
053: import javax.swing.*;
054: import javax.swing.border.EmptyBorder;
055: import javax.swing.event.DocumentEvent;
056: import javax.swing.event.DocumentListener;
057: import javax.swing.filechooser.FileFilter;
058: import java.awt.*;
059: import java.awt.event.ActionEvent;
060: import java.io.File;
061: import java.io.IOException;
062: import java.util.Iterator;
063: import java.util.List;
064: import java.util.StringTokenizer;
065: import java.util.NoSuchElementException;
066:
067: public class JarOptionsDialog extends JFrame {
068: /** Class to save the frame state, i.e. location. */
069: public static class FrameState {
070: private Point _loc;
071:
072: public FrameState(Point l) {
073: _loc = l;
074: }
075:
076: public FrameState(String s) {
077: StringTokenizer tok = new StringTokenizer(s);
078: try {
079: int x = Integer.valueOf(tok.nextToken());
080: int y = Integer.valueOf(tok.nextToken());
081: _loc = new Point(x, y);
082: } catch (NoSuchElementException nsee) {
083: throw new IllegalArgumentException(
084: "Wrong FrameState string: " + nsee);
085: } catch (NumberFormatException nfe) {
086: throw new IllegalArgumentException(
087: "Wrong FrameState string: " + nfe);
088: }
089: }
090:
091: public FrameState(JarOptionsDialog comp) {
092: _loc = comp.getLocation();
093: }
094:
095: public String toString() {
096: final StringBuilder sb = new StringBuilder();
097: sb.append(_loc.x);
098: sb.append(' ');
099: sb.append(_loc.y);
100: return sb.toString();
101: }
102:
103: public Point getLocation() {
104: return _loc;
105: }
106: }
107:
108: /** Bitflags for default selection. */
109: public static final int JAR_CLASSES = 1;
110: public static final int JAR_SOURCES = 2;
111: public static final int MAKE_EXECUTABLE = 4;
112:
113: /** Determines whether class files should be jar-ed. */
114: private JCheckBox _jarClasses;
115: /** Determines whether source files should be jar-ed. */
116: private JCheckBox _jarSources;
117: /** Determines whether the jar file should be made executable. */
118: private JCheckBox _makeExecutable;
119: /** File selector for the jar output file. */
120: private FileSelectorComponent _jarFileSelector;
121: /** Text field for the main class. */
122: private FileSelectorStringComponent _mainClassField;
123: /** Label for main class. */
124: private JLabel _mainClassLabel;
125: /** OK button. */
126: private JButton _okButton;
127: /** Cancel button. */
128: private JButton _cancelButton;
129: /** Main frame. */
130: private MainFrame _mainFrame;
131: /** Model. */
132: private GlobalModel _model;
133: /** Label explaining why classes can't be jar-ed. */
134: private JLabel _cantJarClassesLabel;
135: /** Root of the chooser. */
136: private File _rootFile;
137: /** Processing dialog. */
138: private ProcessingFrame _processingFrame;
139: /** Last frame state. It can be stored and restored. */
140: private FrameState _lastState = null;
141:
142: /** Returns the last state of the frame, i.e. the location and dimension.
143: * @return frame state
144: */
145: public FrameState getFrameState() {
146: return _lastState;
147: }
148:
149: /** Sets state of the frame, i.e. the location and dimension of the frame for the next use.
150: * @param ds State to update to, or {@code null} to reset
151: */
152: public void setFrameState(FrameState ds) {
153: _lastState = ds;
154: if (_lastState != null) {
155: setLocation(_lastState.getLocation());
156: validate();
157: }
158: }
159:
160: /** Sets state of the frame, i.e. the location and dimension of the frame for the next use.
161: * @param s State to update to, or {@code null} to reset
162: */
163: public void setFrameState(String s) {
164: try {
165: _lastState = new FrameState(s);
166: } catch (IllegalArgumentException e) {
167: _lastState = null;
168: }
169: if (_lastState != null)
170: setLocation(_lastState.getLocation());
171: else
172: MainFrame.setPopupLoc(this , _mainFrame);
173: validate();
174: }
175:
176: /** Frame that gets displayed when the program is processing data. */
177: private static class ProcessingFrame extends JFrame {
178: private Component _parent;
179:
180: public ProcessingFrame(Component parent, String title,
181: String label) {
182: super (title);
183: _parent = parent;
184: setSize(350, 150);
185: MainFrame.setPopupLoc(this , parent);
186: JLabel waitLabel = new JLabel(label, SwingConstants.CENTER);
187: getRootPane().setLayout(new BorderLayout());
188: getRootPane().add(waitLabel, BorderLayout.CENTER);
189: }
190:
191: public void setVisible(boolean vis) {
192: MainFrame.setPopupLoc(this , _parent);
193: super .setVisible(vis);
194: }
195: }
196:
197: /** Create a configuration diaglog
198: * @param mf the instance of mainframe to query into the project
199: */
200: public JarOptionsDialog(MainFrame mf) {
201: super ("Create Jar File from Project");
202: _mainFrame = mf;
203: _model = mf.getModel();
204: initComponents();
205: }
206:
207: /** Load the initial state from the previous files or with defaults. */
208: private void _loadSettings() {
209: int f = _model.getCreateJarFlags();
210: _jarClasses.setSelected(((f & JAR_CLASSES) != 0));
211: _jarSources.setSelected(((f & JAR_SOURCES) != 0));
212: _makeExecutable.setSelected(((f & MAKE_EXECUTABLE) != 0));
213:
214: boolean outOfSync = true;
215: if (_model.getBuildDirectory() != null) {
216: outOfSync = _model.hasOutOfSyncDocuments();
217: }
218: if ((_model.getBuildDirectory() == null) || (outOfSync)) {
219: _jarClasses.setSelected(false);
220: _jarClasses.setEnabled(false);
221: String s;
222: if ((_model.getBuildDirectory() == null) && (outOfSync)) {
223: s = "<html><center>A build directory must be specified in order to jar class files,<br>and the project needs to be compiled.</center></html>";
224: } else if (_model.getBuildDirectory() == null) {
225: s = "<html>A build directory must be specified in order to jar class files.</html>";
226: } else {
227: s = "<html>The project needs to be compiled.</html>";
228: }
229: _cantJarClassesLabel.setText(s);
230: } else {
231: _jarClasses.setEnabled(true);
232: _cantJarClassesLabel.setText(" ");
233:
234: // Main class
235: _rootFile = _model.getBuildDirectory();
236: try {
237: _rootFile = _rootFile.getCanonicalFile();
238: } catch (IOException e) {
239: }
240:
241: final File mc = _model.getMainClass();
242: if (mc == null)
243: _mainClassField.setText("");
244: else {
245: try {
246: OpenDefinitionsDocument mcDoc = _model
247: .getDocumentForFile(mc);
248: _mainClassField.setText(mcDoc
249: .getQualifiedClassName());
250: } catch (IOException ioe) {
251: _mainClassField.setText("");
252: } catch (edu.rice.cs.drjava.model.definitions.ClassNameNotFoundException e) {
253: _mainClassField.setText("");
254: }
255: }
256: }
257:
258: _jarFileSelector.setFileField(_model.getCreateJarFile());
259:
260: _okButton.setEnabled(_jarSources.isSelected()
261: || _jarClasses.isSelected());
262: _setEnableExecutable(_jarClasses.isSelected());
263: }
264:
265: /** Build the dialog. */
266: private void initComponents() {
267: JPanel main = _makePanel();
268: super .getContentPane().setLayout(new BorderLayout());
269: super .getContentPane().add(main, BorderLayout.NORTH);
270:
271: Action okAction = new AbstractAction("OK") {
272: public void actionPerformed(ActionEvent e) {
273: _ok();
274: }
275: };
276: _okButton = new JButton(okAction);
277:
278: Action cancelAction = new AbstractAction("Cancel") {
279: public void actionPerformed(ActionEvent e) {
280: _cancel();
281: }
282: };
283: _cancelButton = new JButton(cancelAction);
284:
285: // Add buttons
286: JPanel bottom = new JPanel();
287: bottom.setBorder(new EmptyBorder(5, 5, 5, 5));
288: bottom.setLayout(new BoxLayout(bottom, BoxLayout.X_AXIS));
289: bottom.add(Box.createHorizontalGlue());
290: bottom.add(_okButton);
291: bottom.add(_cancelButton);
292: bottom.add(Box.createHorizontalGlue());
293:
294: super .getContentPane().add(bottom, BorderLayout.SOUTH);
295: super .setResizable(false);
296: pack();
297:
298: MainFrame.setPopupLoc(this , _mainFrame);
299: }
300:
301: /** Make the options panel.
302: * @return The panel with the options for jarring a project
303: */
304: private JPanel _makePanel() {
305: JPanel panel = new JPanel();
306: GridBagLayout gridbag = new GridBagLayout();
307: GridBagConstraints c = new GridBagConstraints();
308: panel.setLayout(gridbag);
309: c.fill = GridBagConstraints.HORIZONTAL;
310: Insets labelInsets = new Insets(5, 10, 0, 10);
311: c.weightx = 0.0;
312: c.gridwidth = 1;
313: c.insets = labelInsets;
314:
315: // Jar class files
316: c.weightx = 1.0;
317: c.gridwidth = GridBagConstraints.REMAINDER;
318: c.insets = labelInsets;
319: c.fill = GridBagConstraints.HORIZONTAL;
320:
321: JPanel jarClassesPanel = _makeClassesPanel();
322: gridbag.setConstraints(jarClassesPanel, c);
323: panel.add(jarClassesPanel);
324:
325: _cantJarClassesLabel = new JLabel(
326: "<html><center>A build directory must be specified in order to jar class files,<br>and the project needs to be compiled.</center></html>",
327: SwingConstants.CENTER);
328: c.gridx = 0;
329: c.anchor = GridBagConstraints.WEST;
330: c.fill = GridBagConstraints.HORIZONTAL;
331: gridbag.setConstraints(jarClassesPanel, c);
332: panel.add(_cantJarClassesLabel);
333:
334: // Jar Sources
335: _jarSources = new JCheckBox(new AbstractAction(
336: "Jar source files") {
337: public void actionPerformed(ActionEvent e) {
338: _okButton.setEnabled(_jarSources.isSelected()
339: || _jarClasses.isSelected());
340: }
341: });
342:
343: c.weightx = 0.0;
344: c.gridwidth = 1;
345: c.insets = labelInsets;
346:
347: gridbag.setConstraints(_jarSources, c);
348: panel.add(_jarSources);
349:
350: // Output file
351: c.gridx = 0;
352: c.gridwidth = 1;
353: c.insets = labelInsets;
354: JLabel label = new JLabel("Jar File");
355: label
356: .setToolTipText("The file that the jar should be written to.");
357: gridbag.setConstraints(label, c);
358: panel.add(label);
359:
360: c.weightx = 1.0;
361: c.gridx = 0;
362: c.gridwidth = GridBagConstraints.REMAINDER;
363: c.insets = labelInsets;
364:
365: JPanel jarFilePanel = _makeJarFileSelector();
366: gridbag.setConstraints(jarFilePanel, c);
367: panel.add(jarFilePanel);
368:
369: return panel;
370: }
371:
372: /** Make the panel that is enabled when you are going to jar class files
373: * @return the panel containing the sub-options to the jarring classes option
374: */
375: private JPanel _makeClassesPanel() {
376: JPanel panel = new JPanel();
377: GridBagConstraints gridBagConstraints;
378: panel.setLayout(new GridBagLayout());
379:
380: _jarClasses = new JCheckBox(new AbstractAction("Jar classes") {
381: public void actionPerformed(ActionEvent e) {
382: _toggleClassOptions();
383: _okButton.setEnabled(_jarSources.isSelected()
384: || _jarClasses.isSelected());
385: }
386: });
387: gridBagConstraints = new GridBagConstraints();
388: gridBagConstraints.gridx = 0;
389: gridBagConstraints.weightx = 1.0;
390: gridBagConstraints.anchor = GridBagConstraints.WEST;
391: panel.add(_jarClasses, gridBagConstraints);
392:
393: JPanel addclasses = new JPanel();
394: addclasses.setLayout(new GridBagLayout());
395: _makeExecutable = new JCheckBox(new AbstractAction(
396: "Make executable") {
397: public void actionPerformed(ActionEvent e) {
398: _toggleMainClass();
399: }
400: });
401: gridBagConstraints = new GridBagConstraints();
402: gridBagConstraints.anchor = GridBagConstraints.WEST;
403: addclasses.add(_makeExecutable, gridBagConstraints);
404:
405: gridBagConstraints = new GridBagConstraints();
406: gridBagConstraints.gridx = 0;
407: gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
408: gridBagConstraints.insets = new Insets(0, 20, 0, 0);
409: addclasses.add(_makeMainClassSelectorPanel(),
410: gridBagConstraints);
411:
412: gridBagConstraints = new GridBagConstraints();
413: gridBagConstraints.gridx = 0;
414: gridBagConstraints.anchor = GridBagConstraints.WEST;
415: gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
416: gridBagConstraints.insets = new Insets(0, 25, 0, 0);
417: panel.add(addclasses, gridBagConstraints);
418:
419: return panel;
420: }
421:
422: /** Make the panel that lets you select the jar's main class.
423: * @return the panel containing the label and the selector for the main class.
424: */
425: private JPanel _makeMainClassSelectorPanel() {
426:
427: FileChooser chooser = new FileChooser(_rootFile);
428: chooser.setDialogTitle("Select Main Class");
429: // chooser.setTopMessage("Select the main class for the executable jar file:");
430: chooser.setApproveButtonText("Select");
431: FileFilter filter = new FileFilter() {
432: public boolean accept(File f) {
433: String name = f.getName();
434: return !f.isDirectory() && name.endsWith(".class");
435: }
436:
437: public String getDescription() {
438: return "Class Files (*.class)";
439: }
440: };
441: chooser.addChoosableFileFilter(filter);
442:
443: _mainClassField = new FileSelectorStringComponent(this ,
444: chooser, 20, 12f) {
445: public File convertStringToFile(String s) {
446: s = s.trim().replace('.', java.io.File.separatorChar)
447: + ".class";
448: if (s.equals(""))
449: return null;
450: else
451: return new File(_rootFile, s);
452: }
453:
454: public String convertFileToString(File f) {
455: if (f == null)
456: return "";
457: else {
458: try {
459: String s = edu.rice.cs.util.FileOps
460: .makeRelativeTo(f, _rootFile)
461: .toString();
462: s = s.substring(0, s.lastIndexOf(".class"));
463: s = s.replace(java.io.File.separatorChar, '.')
464: .replace('$', '.');
465: int pos = 0;
466: boolean ok = true;
467: while ((pos = s.indexOf('.', pos)) >= 0) {
468: if ((s.length() <= pos + 1)
469: || (Character.isDigit(s
470: .charAt(pos + 1)))) {
471: ok = false;
472: break;
473: }
474: ++pos;
475: }
476: if (ok)
477: return s;
478: return "";
479: } catch (Exception e) {
480: return "";
481: }
482: }
483: }
484: };
485: _mainClassField.getTextField().getDocument()
486: .addDocumentListener(new DocumentListener() {
487: public void insertUpdate(DocumentEvent e) {
488: setEnabled();
489: }
490:
491: public void removeUpdate(DocumentEvent e) {
492: setEnabled();
493: }
494:
495: public void changedUpdate(DocumentEvent e) {
496: setEnabled();
497: }
498:
499: private void setEnabled() {
500: Utilities.invokeLater(new Runnable() {
501: public void run() {
502: _okButton.setEnabled(true);
503: }
504: });
505: }
506: });
507: JPanel p = new JPanel();
508: p.setLayout(new BorderLayout());
509: _mainClassLabel = new JLabel("Main class: ");
510: _mainClassLabel.setLabelFor(_mainClassField);
511: p.add(_mainClassLabel, BorderLayout.WEST);
512: p.add(_mainClassField, BorderLayout.CENTER);
513: return p;
514: }
515:
516: /** Create a file selector to select the output jar file
517: * @return The JPanel that contains the selector
518: */
519: private JPanel _makeJarFileSelector() {
520: JFileChooser fileChooser = new JFileChooser(_model
521: .getBuildDirectory());
522: fileChooser.setDialogTitle("Select Jar Output File");
523: fileChooser.setApproveButtonText("Select");
524: fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
525: fileChooser.setMultiSelectionEnabled(false);
526: fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
527:
528: _jarFileSelector = new FileSelectorComponent(this , fileChooser,
529: 20, 12f, false);
530: _jarFileSelector.setFileFilter(new FileFilter() {
531: public boolean accept(File f) {
532: return f.getName().endsWith(".jar") || f.isDirectory();
533: }
534:
535: public String getDescription() {
536: return "Java Archive Files (*.jar)";
537: }
538: });
539:
540: return _jarFileSelector;
541: }
542:
543: /** Modifies state for when the executable check box is selected */
544: private void _setEnableExecutable(boolean b) {
545: _makeExecutable.setEnabled(b);
546: _toggleMainClass();
547: }
548:
549: /** Method to run when the jar class file is selected */
550: private void _toggleClassOptions() {
551: _setEnableExecutable(_jarClasses.isSelected());
552: }
553:
554: /** Method to call when the 'Make Executable' check box is clicked. */
555: private void _toggleMainClass() {
556: _mainClassField.setEnabled(_makeExecutable.isSelected()
557: && _jarClasses.isSelected());
558: _mainClassLabel.setEnabled(_makeExecutable.isSelected()
559: && _jarClasses.isSelected());
560: }
561:
562: /** Method that handels the Cancel button */
563: private void _cancel() {
564: _lastState = new FrameState(this );
565: this .setVisible(false);
566: }
567:
568: /** Do the Jar. */
569: private void _ok() {
570: // Always apply and save settings
571: _saveSettings();
572:
573: File jarOut = _jarFileSelector.getFileFromField();
574: if (jarOut == null) {
575: JOptionPane.showMessageDialog(JarOptionsDialog.this ,
576: "You must specify an output file",
577: "Error: No File Specified",
578: JOptionPane.ERROR_MESSAGE);
579: return;
580: } else if (jarOut.exists()) {
581: if (JOptionPane.showConfirmDialog(JarOptionsDialog.this ,
582: "Are you sure you want to overwrite the file '"
583: + jarOut.getPath() + "'?",
584: "Overwrite file?", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
585: // I want to focus back to the dialog
586: return;
587: }
588: }
589:
590: setEnabled(false);
591: _processingFrame = new ProcessingFrame(this ,
592: "Creating Jar File", "Processing, please wait.");
593: _processingFrame.setVisible(true);
594: SwingWorker worker = new SwingWorker() {
595: boolean _success = false;
596:
597: /**
598: * Takes input of a file which is a directory and compresses all the class files in it
599: * into a jar file
600: *
601: * @param dir the File object representing the directory
602: * @param jarFile the JarBuilder that the data should be written to
603: * @return true on success, false on failure
604: */
605: private boolean jarBuildDirectory(File dir,
606: JarBuilder jarFile) throws IOException {
607: java.io.FileFilter classFilter = new java.io.FileFilter() {
608: public boolean accept(File f) {
609: return f.isDirectory()
610: || f.getName().endsWith(".class");
611: }
612: };
613:
614: File[] files = dir.listFiles(classFilter);
615: if (files != null) { // listFiles may return null if there's an IO error
616: for (int i = 0; i < files.length; i++) {
617: if (files[i].isDirectory()) {
618: jarFile.addDirectoryRecursive(files[i],
619: files[i].getName(), classFilter);
620: } else {
621: jarFile.addFile(files[i], "", files[i]
622: .getName());
623: }
624: }
625: }
626: return true;
627: }
628:
629: /**
630: * Takes the model and the jar and writes all the sources to the jar
631: *
632: * @param model the GlobalModel that the files are to come out of
633: * @param jar the JarBuilder that the data should be written to
634: * @return true on success, false on failure
635: */
636: private boolean jarSources(GlobalModel model, JarBuilder jar) {
637: List<OpenDefinitionsDocument> srcs = model
638: .getProjectDocuments();
639:
640: Iterator<OpenDefinitionsDocument> iter = srcs
641: .iterator();
642: while (iter.hasNext()) {
643: OpenDefinitionsDocument doc = iter.next();
644: if (doc.inProject() && !doc.isAuxiliaryFile()) {
645: try {
646: // Since the file compiled without any errors, this shouldn't have any problems
647: jar.addFile(doc.getFile(),
648: packageNameToPath(doc
649: .getPackageName()), doc
650: .getFileName());
651: } catch (IOException e) {
652: e.printStackTrace();
653: throw new UnexpectedException(e);
654: }
655: }
656: }
657: return true;
658: }
659:
660: /** Helper function to convert a package name to its path form
661: * @param packageName the name of the package
662: * @return the String which is should be the directory that it should be contained within
663: */
664: private String packageNameToPath(String packageName) {
665: return packageName.replaceAll("\\.", System
666: .getProperty("file.separator").replaceAll(
667: "\\\\", "\\\\\\\\"));
668: }
669:
670: /** The method to perform the work
671: * @return null
672: */
673: public Object construct() {
674: try {
675: File jarOut = _jarFileSelector.getFileFromField();
676: if (!jarOut.exists()) {
677: jarOut.createNewFile();
678: }
679:
680: if (_jarClasses.isSelected()
681: && _jarSources.isSelected()) {
682: JarBuilder mainJar = null;
683: if (_makeExecutable.isSelected()) {
684: ManifestWriter mw = new ManifestWriter();
685: mw.setMainClass(_mainClassField.getText());
686: mainJar = new JarBuilder(jarOut, mw
687: .getManifest());
688: } else {
689: mainJar = new JarBuilder(jarOut);
690: }
691:
692: jarBuildDirectory(_model.getBuildDirectory(),
693: mainJar);
694:
695: File sourceJarFile = File.createTempFile(_model
696: .getBuildDirectory().getName(), ".jar");
697: JarBuilder sourceJar = new JarBuilder(
698: sourceJarFile);
699: jarSources(_model, sourceJar);
700: sourceJar.close();
701: mainJar
702: .addFile(sourceJarFile, "",
703: "source.jar");
704:
705: mainJar.close();
706: sourceJarFile.delete();
707: } else if (_jarClasses.isSelected()) {
708: JarBuilder jb;
709: if (_makeExecutable.isSelected()) {
710: ManifestWriter mw = new ManifestWriter();
711: mw.setMainClass(_mainClassField.getText());
712: jb = new JarBuilder(jarOut, mw
713: .getManifest());
714: } else {
715: jb = new JarBuilder(jarOut);
716: }
717: jarBuildDirectory(_model.getBuildDirectory(),
718: jb);
719: jb.close();
720: } else {
721: JarBuilder jb = new JarBuilder(jarOut);
722: jarSources(_model, jb);
723: jb.close();
724: }
725: _success = true;
726: } catch (Exception e) {
727: e.printStackTrace();
728: }
729: return null;
730: }
731:
732: public void finished() {
733: _processingFrame.setVisible(false);
734: _processingFrame.dispose();
735: JarOptionsDialog.this .setEnabled(true);
736: if (_success) {
737: if (_makeExecutable.isSelected()) {
738: Object[] options = { "OK", "Run" };
739: int res = JOptionPane.showOptionDialog(
740: JarOptionsDialog.this ,
741: "Jar file successfully written to '"
742: + _jarFileSelector
743: .getFileFromField()
744: .getName() + "'",
745: "Jar Creation Successful",
746: JOptionPane.DEFAULT_OPTION,
747: JOptionPane.INFORMATION_MESSAGE, null,
748: options, options[0]);
749: JarOptionsDialog.this .setVisible(false);
750: if (1 == res) {
751: SwingWorker jarRunner = new SwingWorker() {
752: public Object construct() {
753: try {
754: Process jarFileProcess = ExecJVM
755: .runJVM(
756: _mainClassField
757: .getText(), // mainClass
758: new String[] {}, // classParams,
759: new String[] { _jarFileSelector
760: .getFileFromField()
761: .getAbsolutePath() }, // classPath,
762: new String[] {}, // jvmParams,
763: _jarFileSelector
764: .getFileFromField()
765: .getParentFile());
766:
767: StreamRedirectThread errThread = new StreamRedirectThread(
768: "error reader",
769: jarFileProcess
770: .getErrorStream(),
771: System.err);
772: StreamRedirectThread outThread = new StreamRedirectThread(
773: "output reader",
774: jarFileProcess
775: .getInputStream(),
776: System.out);
777: errThread.start();
778: outThread.start();
779: boolean notDead = true;
780: while (notDead) {
781: try {
782: errThread.join();
783: outThread.join();
784: notDead = false;
785: } catch (InterruptedException exc) {
786: // ignore, we don't interrupt
787: }
788: }
789: jarFileProcess.waitFor();
790: JOptionPane
791: .showMessageDialog(
792: JarOptionsDialog.this ,
793: "Execution of jar file terminated (exit value = "
794: + jarFileProcess
795: .exitValue()
796: + ")",
797: "Execution terminated.",
798: JOptionPane.INFORMATION_MESSAGE);
799: } catch (Exception e) {
800: JOptionPane
801: .showMessageDialog(
802: JarOptionsDialog.this ,
803: "An error occured while running the jar file: \n"
804: + e,
805: "Error",
806: JOptionPane.ERROR_MESSAGE);
807: } finally {
808: JarOptionsDialog.this
809: .setVisible(false);
810: }
811: return null;
812: }
813: };
814: jarRunner.start();
815: }
816: } else {
817: JOptionPane.showMessageDialog(
818: JarOptionsDialog.this ,
819: "Jar file successfully written to '"
820: + _jarFileSelector
821: .getFileFromField()
822: .getName() + "'",
823: "Jar Creation Successful",
824: JOptionPane.INFORMATION_MESSAGE);
825: JarOptionsDialog.this .setVisible(false);
826: }
827: } else {
828: JOptionPane
829: .showMessageDialog(
830: JarOptionsDialog.this ,
831: "An error occured while creating the jar file. This could be because the file that you are writing to or the file you are reading from could not be opened.",
832: "Error: File Access",
833: JOptionPane.ERROR_MESSAGE);
834: JarOptionsDialog.this .setVisible(false);
835: }
836: _model.refreshActiveDocument();
837: }
838: };
839: worker.start();
840: }
841:
842: /** Save the settings for this dialog. */
843: private boolean _saveSettings() {
844: _lastState = new FrameState(this );
845: if ((_model.getCreateJarFile() == null)
846: || (!_model.getCreateJarFile().getName().equals(
847: _jarFileSelector.getFileFromField().getName()))) {
848: _model
849: .setCreateJarFile(_jarFileSelector
850: .getFileFromField());
851: }
852: int f = 0;
853: if (_jarClasses.isSelected())
854: f |= JAR_CLASSES;
855: if (_jarSources.isSelected())
856: f |= JAR_SOURCES;
857: if (_makeExecutable.isSelected())
858: f |= MAKE_EXECUTABLE;
859: if (f != _model.getCreateJarFlags()) {
860: _model.setCreateJarFlags(f);
861: }
862: return true;
863: }
864:
865: /** Toggle visibility of this frame. Warning, it behaves like a modal dialog. */
866: public void setVisible(boolean vis) {
867: assert EventQueue.isDispatchThread();
868: validate();
869: if (vis) {
870: _mainFrame.hourglassOn();
871: ProcessingFrame pf = new ProcessingFrame(this ,
872: "Checking class files", "Processing, please wait.");
873: pf.setVisible(true);
874: _loadSettings();
875: pf.setVisible(false);
876: pf.dispose();
877: } else {
878: _mainFrame.hourglassOff();
879: _mainFrame.toFront();
880: }
881: super.setVisible(vis);
882: }
883: }
|