Skip to content

Commit 028b13d

Browse files
author
mgricken
committed
This commit adds many properties for file/directory operations
in the External Process command lines (see the "File" category in the "Insert Variable" dialog). It also adds user-defined variables with nested scopes (but no closures). A variable can be defined using ${var;name="x"; val="123";cmd="...command line using variable x goes here..."}. A variable is mutated using ${var.set;name="x";val="456"} and dereferenced using ${x}. Now that variables are included, I also implemented a ${for} loop that can automatically split a command line into shorter pieces. Executing several processes and piping from one process to another hasn't been implemented yet, though. M src/edu/rice/cs/drjava/config/DrJavaProperty.java A src/edu/rice/cs/drjava/config/VariableProperty.java M src/edu/rice/cs/drjava/config/DrJavaPropertySetup.java M src/edu/rice/cs/drjava/config/PropertyMaps.java M src/edu/rice/cs/drjava/config/RecursiveFileListProperty.java M src/edu/rice/cs/drjava/config/ConstantProperty.java M src/edu/rice/cs/drjava/ui/ExternalProcessPanel.java M src/edu/rice/cs/drjava/ui/ExecuteExternalDialog.java M src/edu/rice/cs/util/FileOps.java M src/edu/rice/cs/util/StringOps.java M src/edu/rice/cs/util/ProcessCreator.java git-svn-id: file:///tmp/test-svn/trunk@4502 fe72c1cf-3628-48e9-8b72-1c46755d3cff
1 parent 7fd2588 commit 028b13d

File tree

11 files changed

+985
-87
lines changed

11 files changed

+985
-87
lines changed

drjava/src/edu/rice/cs/drjava/config/ConstantProperty.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public void invalidate() {
7979
/** @return true if the specified property is equal to this one. */
8080
public boolean equals(Object other) {
8181
if (other == null || other.getClass() != this.getClass()) return false;
82-
EagerProperty o = (EagerProperty)other;
82+
ConstantProperty o = (ConstantProperty)other;
8383
return _name.equals(o._name) && (_isCurrent == o._isCurrent) && _value.equals(o._value);
8484
}
8585

drjava/src/edu/rice/cs/drjava/config/DrJavaProperty.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public DrJavaProperty(String name, String value, String help) {
8585

8686
/** Return the value of the property. If it is not current, update first. */
8787
public String getCurrent() {
88-
if (!_isCurrent) {
88+
if (!isCurrent()) {
8989
update();
9090
if (_value==null) { throw new IllegalArgumentException("DrJavaProperty value is null"); }
9191
_isCurrent = true;
@@ -113,6 +113,19 @@ public void setAttribute(String key, String value) {
113113
_attributes.put(key, value);
114114
}
115115

116+
/** Set all attribute values. The attributes must already exist in the table.
117+
* @param attrs attribute key-value pairs
118+
* @param replaceLambda lambda that can be used to replace the variables in a value
119+
* @throws IllegalArgumentException if an attribute with a specified key does not already exist in table
120+
*/
121+
public void setAttributes(HashMap<String,String> attrs, edu.rice.cs.util.Lambda<String,String> replaceLambda) {
122+
String value;
123+
for(String key: attrs.keySet()) {
124+
value = attrs.get(key);
125+
setAttribute(key, replaceLambda.apply(value));
126+
}
127+
}
128+
116129
/** Return an attribute's value.
117130
* @param key name of the attribute
118131
* @throws IllegalArgumentException if attribute with specified key does not already exist in table
@@ -168,7 +181,7 @@ public int compareTo(DrJavaProperty o) {
168181
public boolean equals(Object other) {
169182
if (other == null || other.getClass() != this.getClass()) return false;
170183
DrJavaProperty o = (DrJavaProperty)other;
171-
return _name.equals(o._name) && (_isCurrent == o._isCurrent) && _value.equals(o._value);
184+
return _name.equals(o._name) && (isCurrent() == o.isCurrent()) && _value.equals(o._value);
172185
}
173186

174187
/** @return the hash code. */

drjava/src/edu/rice/cs/drjava/config/DrJavaPropertySetup.java

Lines changed: 676 additions & 13 deletions
Large diffs are not rendered by default.

drjava/src/edu/rice/cs/drjava/config/PropertyMaps.java

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,35 @@ public class PropertyMaps {
7272
public PropertyMaps() { }
7373

7474
/** Return the property requested, or null if not found.
75+
* @param category name of the category
76+
* @param name name of the property
77+
* @return property, or null if not found
7578
* @throws IllegalArgumentException if category is not known. */
7679
public DrJavaProperty getProperty(String category, String name) {
7780
Map<String,DrJavaProperty> m = _props.get(category);
7881
if (m==null) { throw new IllegalArgumentException("DrJavaProperty category unknown."); }
7982
return m.get(name);
8083
}
8184

85+
/** Search through all categories and return the property requested, or null if not found.
86+
* @param key key of the property
87+
* @return property, or null if not found */
88+
public DrJavaProperty getProperty(String key) {
89+
for(String category: _props.keySet()) {
90+
DrJavaProperty p = getProperty(category, key);
91+
if (p!=null) { return p; }
92+
}
93+
return null;
94+
}
95+
96+
/** Remove the specified property.
97+
* @param p property to remove */
98+
public void removeProperty(DrJavaProperty p) {
99+
for(String category: _props.keySet()) {
100+
_props.get(category).remove(p);
101+
}
102+
}
103+
82104
/** Add a property. */
83105
public DrJavaProperty setProperty(String category, DrJavaProperty p) {
84106
Map<String,DrJavaProperty> m = _props.get(category);
@@ -87,6 +109,11 @@ public DrJavaProperty setProperty(String category, DrJavaProperty p) {
87109
return p;
88110
}
89111

112+
/** Clear the specified category. */
113+
public void clearCategory(String category) {
114+
_props.remove(category);
115+
}
116+
90117
/** Return the set of categories. */
91118
public Set<String> getCategories() { return _props.keySet(); }
92119

@@ -105,6 +132,69 @@ public Map<String, DrJavaProperty> getProperties(String category) {
105132

106133
/** A lambda to use the getCurrent() method, which forces an update. */
107134
public static final Lambda<String,DrJavaProperty> GET_CURRENT = new Lambda<String,DrJavaProperty>() {
108-
public String apply(DrJavaProperty p) { return p.getCurrent(); /* might be stale */ }
135+
public String apply(DrJavaProperty p) { return p.getCurrent(); }
109136
};
137+
138+
protected HashMap<String,Stack<VariableProperty>> _variables = new HashMap<String,Stack<VariableProperty>>();
139+
140+
// name of the category for variables
141+
protected static final String VARIABLES_CATEGORY = "$Variables$";
142+
143+
/** Clear all user-defined variables. */
144+
public void clearVariables() {
145+
_props.remove(VARIABLES_CATEGORY);
146+
}
147+
148+
/** Add a variable with the specified name and value, shadowing previous definitions of the variable.
149+
* @param name name of the variable
150+
* @param value value of the variable
151+
* @throws IllegalArgumentException if the name is already used for a built-in property */
152+
public void addVariable(String name, String value) {
153+
for(String category: _props.keySet()) {
154+
if (category.equals(VARIABLES_CATEGORY)) continue;
155+
if (getProperty(category, name)!=null) {
156+
throw new IllegalArgumentException("Variable "+name+" already used for a built-in property");
157+
}
158+
}
159+
// name not used by built-in
160+
VariableProperty p = new VariableProperty(name, value);
161+
setProperty(VARIABLES_CATEGORY, p);
162+
Stack<VariableProperty> varStack = _variables.get(name);
163+
if (varStack==null) { varStack = new Stack<VariableProperty>(); _variables.put(name,varStack); }
164+
varStack.push(p);
165+
}
166+
167+
/** Mutate the value of a variable with the specified name.
168+
* @param name name of the variable
169+
* @param value new value of the variable
170+
* @throws IllegalArgumentException if a variable with name does not exist */
171+
public void setVariable(String name, String value) {
172+
Stack<VariableProperty> varStack = _variables.get(name);
173+
if ((varStack==null) ||
174+
(varStack.empty())) { throw new IllegalArgumentException("Variable "+name+" does not exist."); }
175+
VariableProperty p = varStack.peek();
176+
p.setValue(value);
177+
}
178+
179+
/** Remove the variable with the specified name, unshadowing previous definitions of the variable.
180+
* @param name of the variable
181+
* @throws IllegalArgumentException if no variable with that name exists */
182+
public void removeVariable(String name) {
183+
Stack<VariableProperty> varStack = _variables.get(name);
184+
if ((varStack==null) ||
185+
(varStack.empty())) { throw new IllegalArgumentException("Variable "+name+" does not exist."); }
186+
VariableProperty p = varStack.pop();
187+
if (varStack.empty()) {
188+
// no shadowed variables
189+
// remove the stack from the hash map of variables
190+
_variables.remove(varStack);
191+
// remove the property
192+
removeProperty(p);
193+
}
194+
else {
195+
// previously shadowed variable(s) exist
196+
// set unshadowed variable as new value of property
197+
setProperty(VARIABLES_CATEGORY, varStack.peek());
198+
}
199+
}
110200
}

drjava/src/edu/rice/cs/drjava/config/RecursiveFileListProperty.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.util.Iterator;
4343
import java.util.List;
4444
import java.util.ArrayList;
45+
import java.util.HashSet;
4546
import java.io.*;
4647
import java.util.regex.Pattern;
4748
import edu.rice.cs.util.StringOps;
@@ -71,11 +72,24 @@ public boolean accept(File pathname) {
7172
}
7273
}
7374
public static class FileMaskFilter extends RegexFilter {
75+
private HashSet<File> _include = new HashSet<File>();
76+
private HashSet<File> _exclude = new HashSet<File>();
7477
public FileMaskFilter(String mask) {
7578
super(TextUtil.regexEscape(mask)
7679
.replaceAll("\\\\\\*",".*") // turn \* into .*
7780
.replaceAll("\\\\\\?",".")); // turn \? into .
7881
}
82+
public boolean accept(File pathname) {
83+
if (_include.contains(pathname)) { return true; }
84+
if (_exclude.contains(pathname)) { return false; }
85+
return super.accept(pathname);
86+
}
87+
public void addIncludedFile(File f) { _include.add(f); }
88+
public void removeIncludedFile(File f) { _include.remove(f); }
89+
public void clearIncludedFile() { _include.clear(); }
90+
public void addExcludedFile(File f) { _exclude.add(f); }
91+
public void removeExcludedFile(File f) { _exclude.remove(f); }
92+
public void clearExcludedFile() { _exclude.clear(); }
7993
}
8094

8195
/** Abstract factory method specifying the list. */
@@ -84,7 +98,10 @@ protected List<File> getList() {
8498
FileMaskFilter fDirFilter = new FileMaskFilter(_attributes.get("dirfilter"));
8599
String start = StringOps.replaceVariables(_attributes.get("dir"), PropertyMaps.ONLY, PropertyMaps.GET_CURRENT);
86100
start = StringOps.unescapeSpacesWith1bHex(start);
87-
Iterable<File> it = edu.rice.cs.plt.io.IOUtil.listFilesRecursively(new File(start), fFilter, fDirFilter);
101+
File fStart = new File(start);
102+
// if the specified starting point is a directory, allow that directory
103+
if (fStart.isDirectory()) { fDirFilter.addIncludedFile(fStart); }
104+
Iterable<File> it = edu.rice.cs.plt.io.IOUtil.listFilesRecursively(fStart, fFilter, fDirFilter);
88105
StringBuilder sb = new StringBuilder();
89106
ArrayList<File> l = new ArrayList<File>();
90107
for(File f: it) {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*BEGIN_COPYRIGHT_BLOCK
2+
*
3+
* Copyright (c) 2001-2008, JavaPLT group at Rice University (drjava@rice.edu)
4+
* All rights reserved.
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions are met:
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in the
12+
* documentation and/or other materials provided with the distribution.
13+
* * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
14+
* names of its contributors may be used to endorse or promote products
15+
* derived from this software without specific prior written permission.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
*
29+
* This software is Open Source Initiative approved Open Source Software.
30+
* Open Source Initative Approved is a trademark of the Open Source Initiative.
31+
*
32+
* This file is part of DrJava. Download the current version of this project
33+
* from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
34+
*
35+
* END_COPYRIGHT_BLOCK*/
36+
37+
package edu.rice.cs.drjava.config;
38+
39+
import edu.rice.cs.drjava.DrJava;
40+
import java.util.HashSet;
41+
import java.util.Iterator;
42+
43+
/** Class representing user-defined variables that can be inserted as variables in external processes.
44+
* @version $Id$
45+
*/
46+
public class VariableProperty extends ConstantProperty {
47+
/** Create a variable property. */
48+
public VariableProperty(String name, String value) {
49+
super(name, value, "User-defined variable.");
50+
}
51+
52+
/** Set the value of the variable.
53+
* @param value new value */
54+
public void setValue(String value) {
55+
_value = value;
56+
}
57+
58+
/** @return true if the specified property is equal to this one. */
59+
public boolean equals(Object other) {
60+
if (other == null || other.getClass() != this.getClass()) return false;
61+
VariableProperty o = (VariableProperty)other;
62+
return _name.equals(o._name) && (_isCurrent == o._isCurrent) && _value.equals(o._value);
63+
}
64+
}

drjava/src/edu/rice/cs/drjava/ui/ExecuteExternalDialog.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,7 @@ private boolean _saveSettings() {
14421442

14431443
/** Insert a variable into the command line. */
14441444
private void _insertVariableCommand() {
1445+
PropertyMaps.ONLY.clearVariables();
14451446
_mainFrame.removeModalWindowAdapter(this);
14461447
_insertVarDialogMonitor.reset();
14471448
_insertVarDialog.setVisible(true);

drjava/src/edu/rice/cs/drjava/ui/ExternalProcessPanel.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ public void mouseReleased(MouseEvent e) { }
125125
protected void initThread(ProcessCreator pc) {
126126
// MainFrame.LOG.log("\tProcessPanel ctor");
127127
try {
128+
PropertyMaps.ONLY.clearVariables();
128129
_pc = pc;
129130
_readThread = new Thread(new Runnable() {
130131
public void run() {
@@ -428,8 +429,6 @@ protected void readText(final boolean finish) {
428429
_sb.append(new String(_buf, 0, _red));
429430
if (finish) { _changeCount = 1; } else { ++_changeCount; }
430431
}
431-
if (_is==null) { _sb.append("\nInput stream suddenly became null."); }
432-
if (_erris==null) { _sb.append("\nError input stream suddenly became null."); }
433432
while((_changeCount<=BUFFER_READS_PER_TIMER) &&
434433
(_erris!=null) &&
435434
((_errred = _erris.read(_errbuf))>=0)) {
@@ -445,6 +444,28 @@ protected void readText(final boolean finish) {
445444
_sb.append(new String(_errbuf, 0, _errred));
446445
if (finish) { _changeCount = 1; } else { ++_changeCount; }
447446
}
447+
if ((_p!=null) && (_is==null)) {
448+
try {
449+
// try to get exitValue() to see if process has terminated; exit value is not otherwise important
450+
int ignored = _p.exitValue();
451+
// if no exception is thrown, then the process has finished, and the stream may be null
452+
}
453+
catch(IllegalThreadStateException e) {
454+
// process has NOT finished yet, but the stream is null; this is a problem
455+
_sb.append("\nInput stream suddenly became null.");
456+
}
457+
}
458+
if ((_p!=null) && (_erris==null)) {
459+
try {
460+
// try to get exitValue() to see if process has terminated; exit value is not otherwise important
461+
int ignored = _p.exitValue();
462+
// if no exception is thrown, then the process has finished, and the stream may be null
463+
}
464+
catch(IllegalThreadStateException e) {
465+
// process has NOT finished yet, but the stream is null; this is a problem
466+
_sb.append("\nError input stream suddenly became null.");
467+
}
468+
}
448469
}
449470
catch(IOException ioe) {
450471
// MainFrame.LOG.log("\taborted");

drjava/src/edu/rice/cs/util/FileOps.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,4 +965,30 @@ public static boolean makeWritable(File roFile) throws IOException {
965965
}
966966
}
967967
}
968+
969+
/** Move f to n, recursively if necessary.
970+
* @param f file or directory to move
971+
* @param n new location and name for the file or directory
972+
* @return true if successful */
973+
public static boolean moveRecursively(File f, File n) {
974+
boolean res = true;
975+
try {
976+
if (!f.exists()) { return false; }
977+
if (f.isFile()) { return edu.rice.cs.plt.io.IOUtil.attemptMove(f,n); }
978+
else {
979+
// recursively move directory
980+
// first create the target directory
981+
if (!n.mkdir()) { return false; }
982+
// now process children
983+
for(String child: f.list()) {
984+
File oldChild = new File(f, child);
985+
File newChild = new File(n, child);
986+
res = res && moveRecursively(oldChild, newChild);
987+
}
988+
if (!f.delete()) { return false; }
989+
}
990+
}
991+
catch(Exception e) { return false; }
992+
return res;
993+
}
968994
}

drjava/src/edu/rice/cs/util/ProcessCreator.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
*/
5252

5353
public class ProcessCreator {
54+
/** Separator used between processes. */
55+
public static final String PROCESS_SEPARATOR = (File.pathSeparatorChar==':')?";":":";
56+
5457
protected String _cmdline;
5558
protected String _workdir;
5659
protected Map<String,String> _env;

0 commit comments

Comments
 (0)