forked from playframework/play1
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[playframework#674] improves speed when looking for new / removed cla…
…sses in test-mode by caching the regexp-result for each file until the file has changed on disk.
- Loading branch information
Showing
2 changed files
with
105 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
99 changes: 99 additions & 0 deletions
99
framework/src/play/classloading/hash/ClassStateHashCreator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package play.classloading.hash; | ||
|
||
import play.vfs.VirtualFile; | ||
|
||
import java.io.File; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
public class ClassStateHashCreator { | ||
|
||
private final Pattern classDefFinderPattern = Pattern.compile("\\s+class\\s([a-zA-Z0-9_]+)\\s+"); | ||
|
||
private static class FileWithClassDefs { | ||
private final File file; | ||
private final long size; | ||
private final long lastModified; | ||
private final String classDefs; | ||
|
||
private FileWithClassDefs(File file, String classDefs) { | ||
this.file = file; | ||
this.classDefs = classDefs; | ||
|
||
// store size and time for this file.. | ||
size = file.length(); | ||
lastModified = file.lastModified(); | ||
} | ||
|
||
/** | ||
* @return true if file has changed on disk | ||
*/ | ||
public boolean fileNotChanges( ) { | ||
return size == file.length() && lastModified == file.lastModified(); | ||
} | ||
|
||
public String getClassDefs() { | ||
return classDefs; | ||
} | ||
} | ||
|
||
private final Map<File, FileWithClassDefs> classDefsInFileCache = new HashMap<File, FileWithClassDefs>(); | ||
|
||
public synchronized int computePathHash(List<VirtualFile> paths) { | ||
StringBuffer buf = new StringBuffer(); | ||
for (VirtualFile virtualFile : paths) { | ||
scan(buf, virtualFile); | ||
} | ||
// TODO: should use better hashing-algorithm.. MD5? SHA1? | ||
// I think hashCode() has too many collisions.. | ||
return buf.toString().hashCode(); | ||
} | ||
|
||
private void scan(StringBuffer buf, VirtualFile current) { | ||
if (!current.isDirectory()) { | ||
if (current.getName().endsWith(".java")) { | ||
buf.append( getClassDefsForFile(current)); | ||
} | ||
} else if (!current.getName().startsWith(".")) { | ||
// TODO: we could later optimizie it further if we check if the entire folder is unchanged | ||
for (VirtualFile virtualFile : current.list()) { | ||
scan(buf, virtualFile); | ||
} | ||
} | ||
} | ||
|
||
private String getClassDefsForFile( VirtualFile current ) { | ||
|
||
File realFile = current.getRealFile(); | ||
// first we look in cache | ||
|
||
FileWithClassDefs fileWithClassDefs = classDefsInFileCache.get( realFile ); | ||
if( fileWithClassDefs != null && fileWithClassDefs.fileNotChanges() ) { | ||
// found the file in cache and it has not changed on disk | ||
return fileWithClassDefs.getClassDefs(); | ||
} | ||
|
||
// didn't find it or it has changed on disk | ||
// we must re-parse it | ||
|
||
StringBuilder buf = new StringBuilder(); | ||
Matcher matcher = classDefFinderPattern.matcher(current.contentAsString()); | ||
buf.append(current.getName()); | ||
buf.append("("); | ||
while (matcher.find()) { | ||
buf.append(matcher.group(1)); | ||
buf.append(","); | ||
} | ||
buf.append(")"); | ||
String classDefs = buf.toString(); | ||
|
||
// store it in cache | ||
classDefsInFileCache.put( realFile, new FileWithClassDefs(realFile, classDefs)); | ||
return classDefs; | ||
} | ||
|
||
|
||
} |