Was ist ein Workaround?
Zitat aus Wikipedia:
Unter einem Workaround (englisch für: (um etwas) herum arbeiten) versteht man die Umgehung eines bekannten Problems innerhalb eines technischen Systems durch eine Hilfskonstruktion. Es ist eine provisorische Lösung, die die eigentliche Fehlerursache nicht behebt, sondern seine Symptome beseitigt oder zumindest mildert, um so trotzdem sofort zu einem gewünschten Ergebnis zu gelangen. Ein Workaround schafft somit Zeit für eine tiefergehende Ursachenanalyse.
Meine bildliche Definition
Unit-Test mit EasyMock – Parameter-Check
Kürzlich habe ich ein Bugfix in einer Service-Klasse gemacht, der verhindern sollte, daß ein String länger als 64 Zeichen wird. Da es sich an dieser Stelle um ein Label gehandelte, konnte ich es mittels der Apache-Commons-Klasse StringUtils kürzen. Bei der Gelegenheit wollte ich diesen Aspekt im Unit-Test berücksichtigen. Die Frage die sich jedoch stellte: “Wie komme ich an einem im Service erzeugten Parameter mit dem wiederum ein weiterer Service aufgerufen wird?”
Ausschnitt des zu testenden Services:
public UserAccount storeUserAccount(UserContext userContext, UserAccount userAccount){ Assert.notNull(userContext, "userContext != NULL"); Assert.notNull(userAccount, "userAccount != NULL"); . . . // not accessable from outside String x = calcInInternalMethod(); x = StringUtils.abbreviate(username, 64); SpecialOject so = delegatedService .doSomething(userContext, x); . . . return userAccount; }
Ich habe keinen EasyMock-Matcher gefunden der die String-Länge prüft. EasyMock unterstützt mit dem Interface IArgumentMatcher jedoch das man einen eigenen Matcher schreiben kann. Der folgende “Matcher” kann die String-Länge prüfen.
import org.easymock.EasyMock; import org.easymock.IArgumentMatcher; /** * Matcher for max-String-length-check with EasyMock. * * @author blog.analysisfreaks.de */ public class StringLengthMatcher implements IArgumentMatcher{ private int size; private int actualLength; /** * Private Constructor. * @param size */ private StringLengthMatcher(int size) { this.size = size; } /** * Matcher that checks the max-length of a {@link String} * @param size (>0) * @return */ public static String notLongerThan(int size){ EasyMock.reportMatcher(new StringLengthMatcher(size)); return null; } /** * {@inheritDoc} */ public void appendTo(StringBuffer buffer) { buffer.append("notLongerThan(") .append(size).append(") size exceeded with lenght == ") .append(this.actualLength).append("!"); } /** * {@inheritDoc} */ public boolean matches(Object argument) { if(argument==null) return false; actualLength = argument.toString().length(); boolean ok = actualLength<=size; return ok; } }
Der Unit-Test sieht dann wie folgt aus:
@Test(description = "test with normal data") public void testStoreUserAccount() { . . . EasyMock.expect(delegatedService.doSomething( (String)EasyMock.anyObject(), StringLengthMatcher.notLongerThan(64))) .andReturn(null); . . . EasyMock.replay(x,y,z,delegatedService); UserAccount storedUserAccount = benutzerService.storeUserAccount(userContext, userAccount); EasyMock.verify(x,y,z,delegatedService); }
Maven compile mit ausgewählter JVM-Version
Antwort: Der “pom.xml” wird folgender Abschnitt hinzugefügt
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> </plugins> </build>
Stichworte: source level, generics, java version
SVN Befehl zum setzten der SVN-Keywords
svn propset svn:keywords "Id LastChangedBy LastChangedRevision" <file-name>
Die Beschreibung der möglichen Keywords stammt von SVN-Book.
Date
$Date: 2006-07-22 21:42:37 -0700 (Sat, 22 Jul 2006) $
.
It may also be specified as LastChangedDate
.
Revision
$Revision: 144 $
. It may also be specified as LastChangedRevision
or Rev
.
Author
$Author: harry $
. It may also be specified as LastChangedBy
.
HeadURL
$HeadURL: http://svn.collab.net/repos/trunk/README $
. It may be abbreviated as URL
.
Id
$Id: calc.c 148 2006-07-28 21:30:43Z sally $
, and is interpreted to mean that the file calc.c
was last changed in revision 148 on the evening of July 28, 2006 by the user sally
.
Linux convert CRLN -> LN (DOS->Unix)
$ dos2unix myfile.txt
Wie erzeugt man ein Source-Jar mit maven?
Antwort: Der “pom.xml” wird folgender Abschnitt hinzugefügt
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
Auslesen der SVN-Keywords mit Java
Für ein Projekt wollte ich alle Java-Sourcen aus einem Verzeichnisbaum prüfen ob deren SVN-Keywords gesetzt sind.
1. Lösung:
Ich schreibe ein Konsolen-Skript, das mittels dem SVN-Command den Verzeichnisbaum scannt und einen Report erzeugt.
Mit dem folgendem Consolen-Command kann man die SVN-Keywords einer einzelnen Datei abfragen:
svn propget svn:keywords <file-name>
Nachteil: Das Skript wäre nicht OS unabhängig —-> also kein Skript erstellen
2. Lösung:
Ich schreibe ein Java-Programm, das mittels der Open Source Bibliotheken SVNKit und Apache Commons-IO den Verzeichnisbaum scannt und einen Report erzeugt.
ValueSVNPropertyHandler.java :
import org.tmatesoft.svn.core.wc.ISVNPropertyHandler; public interface ValueSVNPropertyHandler extends ISVNPropertyHandler { public String getValue(); }
SVNProp.java :
import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.commons.io.FileUtils; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNPropertyValue; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.internal.util.SVNHashSet; import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions; import org.tmatesoft.svn.core.internal.wc.SVNPath; import org.tmatesoft.svn.core.wc.SVNPropertyData; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNWCClient; import org.tmatesoft.svn.core.wc.SVNWCUtil; public class SVNProp { public static void main(String[] args) throws SVNException { // example for call of getSVNKeywords String targetPath = " <PATH-TO-DIR>"; String svnKeywords = getSVNKeywords(targetPath); String x = "Keywords of %s = %s"; System.out.println(String.format(x, targetPath, svnKeywords)); // example for call of getFilesWithoutSvnKeywords File root = new File(" <PATH-TO-FILE>"); List allFilesWithoutSvnKeywords = getFilesWithoutSvnKeywords( root, new String[] { "java" }); System.out.println("List of svn-files with no svn:keywords"); System.out.println("--------------------------------------"); for (String fileWithNoSVNKeyword : allFilesWithoutSvnKeywords) { System.out.println(fileWithNoSVNKeyword); } String found = "found: %d"; System.out.println(String.format(found,allFilesWithoutSvnKeywords.size())); } @SuppressWarnings("unchecked") public static List getFilesWithoutSvnKeywords(File root, String[] extensions) { boolean recursive = true; // Finds files within a root directory and optionally its // subdirectories which match an array of extensions. Collection files = FileUtils.listFiles(root, extensions, recursive); List listOfFilesWithoutKeywords = new ArrayList(); for (File file : files) { String absolutePath = file.getAbsolutePath(); String keyw = null; try { keyw = SVNProp.getSVNKeywords(absolutePath); } catch (SVNException e) { continue; } if (keyw == null || "".equals(keyw)) { listOfFilesWithoutKeywords.add(absolutePath); } } return listOfFilesWithoutKeywords; } public static String getSVNKeywords(String targetPath) throws SVNException { // desired property-name String propertyName = "svn:keywords"; SVNDepth depth = SVNDepth.EMPTY; SVNHashSet changeLists = new SVNHashSet(); SVNRevision undefined = SVNRevision.UNDEFINED; DefaultSVNOptions options = new DefaultSVNOptions(); // default auth (local filesytem) ISVNAuthenticationManager defaultAuthenticationManager = SVNWCUtil .createDefaultAuthenticationManager(); SVNWCClient client = new SVNWCClient(defaultAuthenticationManager, options); // use given targetPath SVNPath target = new SVNPath(targetPath, true); SVNRevision pegRevision = target.getPegRevision(); // Handler for result-data ValueSVNPropertyHandler handler = new ValueSVNPropertyHandler() { private String value; public void handleProperty(long arg0, SVNPropertyData data) throws SVNException { this.value = getValueStr(data); } public void handleProperty(SVNURL url, SVNPropertyData data) throws SVNException { this.value = getValueStr(data); } public void handleProperty(File f, SVNPropertyData data) throws SVNException { this.value = getValueStr(data); } private String getValueStr(SVNPropertyData data) { if (data == null) return null; SVNPropertyValue svnValue = data.getValue(); if (svnValue == null) return null; return svnValue.toString(); } public String getValue() { return value; } }; // fetching data from subversion client.doGetProperty(target.getFile(), propertyName, pegRevision, undefined, depth, handler, changeLists); // value of svn:keywords return handler.getValue(); } }
Java API für SVN Steuerung
SVNKit:
Da ich dem SVN einige Informationen entlocken wollte bin ich auf auf die Java API SVNKit gestoßen.
SVNKit ist eine Open Source Java API die den Zugriff auf SVN-Repositories ermöglicht.
Im zugehörigen WIKI findet man gut dokumentierte Beispiele:
Interessant ist auch die SVNKit-Knowlegde Base, denn dort findet man schnell Zugriff auf das JavaDoc, Wiki, Anwendungsbeispiele, Entwickler- und Benutzer-Leitfaden und vieles mehr.
Einen Präsentation mit einem Anwendungsbeispiel in Form eines PDFs gibt es unter diesem Link.
Freeware-Tool zur Rettung von Daten defekter CDs
Beschreibung unter: datenrettung-recovery-cd-recovery-toolbox
Freeware Tool zur Dateiwiederherstellung
Beschreibung unter: datenrettung-recovery-recuva