Author: olamy Date: Thu May 28 23:02:38 2009 New Revision: 779790 URL: http://svn.apache.org/viewvc?rev=779790&view=rev Log: [SCM-474] Make class ChangeSet thread-safe Submitted by Andrei Solntsev
Added: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/FilenameUtils.java (with props) maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/ThreadSafeDateFormat.java (with props) maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/util/ maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/util/FilenameUtilsTest.java (with props) Modified: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/ChangeSet.java maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/ScmFileSet.java maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ChangeFileTest.java maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ChangeSetTest.java maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ScmFileSetTest.java Modified: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/ChangeSet.java URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/ChangeSet.java?rev=779790&r1=779789&r2=779790&view=diff ============================================================================== --- maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/ChangeSet.java (original) +++ maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/ChangeSet.java Thu May 28 23:02:38 2009 @@ -19,9 +19,6 @@ * under the License. */ -import org.apache.maven.scm.provider.ScmProviderRepository; -import org.codehaus.plexus.util.StringUtils; - import java.io.Serializable; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -30,6 +27,11 @@ import java.util.Iterator; import java.util.List; +import org.apache.maven.scm.provider.ScmProviderRepository; +import org.apache.maven.scm.util.FilenameUtils; +import org.apache.maven.scm.util.ThreadSafeDateFormat; +import org.codehaus.plexus.util.StringUtils; + /** * @author <a href="mailto:eveni...@apache.org">Emmanuel Venisse</a> * @version $Id$ @@ -72,25 +74,25 @@ /** * Formatter used by the getDateFormatted method. */ - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat( DATE_PATTERN ); + private static final ThreadSafeDateFormat DATE_FORMAT = new ThreadSafeDateFormat( DATE_PATTERN ); private static final String TIME_PATTERN = "HH:mm:ss"; /** * Formatter used by the getTimeFormatted method. */ - private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat( TIME_PATTERN ); + private static final ThreadSafeDateFormat TIME_FORMAT = new ThreadSafeDateFormat( TIME_PATTERN ); /** * Formatter used to parse date/timestamp. */ - private static final SimpleDateFormat TIMESTAMP_FORMAT_1 = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss" ); + private static final ThreadSafeDateFormat TIMESTAMP_FORMAT_1 = new ThreadSafeDateFormat( "yyyy/MM/dd HH:mm:ss" ); - private static final SimpleDateFormat TIMESTAMP_FORMAT_2 = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ); + private static final ThreadSafeDateFormat TIMESTAMP_FORMAT_2 = new ThreadSafeDateFormat( "yyyy-MM-dd HH:mm:ss" ); - private static final SimpleDateFormat TIMESTAMP_FORMAT_3 = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss z" ); + private static final ThreadSafeDateFormat TIMESTAMP_FORMAT_3 = new ThreadSafeDateFormat( "yyyy/MM/dd HH:mm:ss z" ); - private static final SimpleDateFormat TIMESTAMP_FORMAT_4 = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss z" ); + private static final ThreadSafeDateFormat TIMESTAMP_FORMAT_4 = new ThreadSafeDateFormat( "yyyy-MM-dd HH:mm:ss z" ); /** * Date the changes were committed @@ -185,15 +187,26 @@ files.add( file ); } + /** + * @deprecated Use method {...@link #containsFilename(String)} + * @param filename + * @param repository NOT USED + * @return + */ public boolean containsFilename( String filename, ScmProviderRepository repository ) { + return containsFilename( filename ); + } + + public boolean containsFilename( String filename ) + { if ( files != null ) { for ( Iterator i = files.iterator(); i.hasNext(); ) { ChangeFile file = (ChangeFile) i.next(); - String f1 = StringUtils.replace( StringUtils.replace( file.getName(), "\\", "/" ), "//", "/" ); - String f2 = StringUtils.replace( StringUtils.replace( filename, "\\", "/" ), "//", "/" ); + String f1 = FilenameUtils.normalizeFilename( file.getName() ); + String f2 = FilenameUtils.normalizeFilename( filename ); if ( f1.indexOf( f2 ) >= 0 ) { return true; @@ -368,7 +381,7 @@ /** * @return date in yyyy-mm-dd format */ - public synchronized String getDateFormatted() + public String getDateFormatted() { return DATE_FORMAT.format( getDate() ); } @@ -376,7 +389,7 @@ /** * @return time in HH:mm:ss format */ - public synchronized String getTimeFormatted() + public String getTimeFormatted() { return TIME_FORMAT.format( getDate() ); } @@ -384,21 +397,21 @@ /** {...@inheritdoc} */ public String toString() { - String result = author + "\n" + date + "\n"; - + StringBuffer result = new StringBuffer( author == null ? " null " : author ); + result.append( "\n" ).append( date == null ? "null " : date.toString() ).append( "\n" ); if ( files != null ) { for ( Iterator i = files.iterator(); i.hasNext(); ) { ChangeFile file = (ChangeFile) i.next(); - result += file + "\n"; + result.append( file == null ? " null " : file.toString() ).append( "\n" ); } } - result += comment; + result.append( comment == null ? " null " : comment ); - return result; + return result.toString(); } /** @@ -524,8 +537,8 @@ break; case'\'': buffer.replace( i, i + 1, APOSTROPHE_ENTITY ); - size += 4; - i += 4; + size += 5; + i += 5; break; case'\"': buffer.replace( i, i + 1, QUOTE_ENTITY ); Modified: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/ScmFileSet.java URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/ScmFileSet.java?rev=779790&r1=779789&r2=779790&view=diff ============================================================================== --- maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/ScmFileSet.java (original) +++ maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/ScmFileSet.java Thu May 28 23:02:38 2009 @@ -19,10 +19,6 @@ * under the License. */ -import org.codehaus.plexus.util.DirectoryScanner; -import org.codehaus.plexus.util.FileUtils; -import org.codehaus.plexus.util.StringUtils; - import java.io.File; import java.io.IOException; import java.io.Serializable; @@ -30,6 +26,10 @@ import java.util.Arrays; import java.util.List; +import org.codehaus.plexus.util.DirectoryScanner; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.StringUtils; + /** * Set of files used for SCM operations. * Consists of the base directory of the files and a list of files relative to that directory. @@ -42,10 +42,12 @@ { private static final long serialVersionUID = -5978597349974797556L; + private static final String DELIMITER = ","; + /** @see DirectoryScanner#DEFAULTEXCLUDES */ - private static final String DEFAULT_EXCLUDES = StringUtils.join( DirectoryScanner.DEFAULTEXCLUDES, "," ); + private static final String DEFAULT_EXCLUDES = StringUtils.join( DirectoryScanner.DEFAULTEXCLUDES, DELIMITER ); - private File basedir; + private final File basedir; private String includes; @@ -54,7 +56,7 @@ /** * List of File objects, all relative to the basedir. */ - private List files = new ArrayList( 0 ); + private final List files; /** * Create a file set with no files, only the base directory. @@ -94,7 +96,7 @@ if ( excludes != null && excludes.length() > 0 ) { - excludes += "," + DEFAULT_EXCLUDES; + excludes += DELIMITER + DEFAULT_EXCLUDES; } else { Added: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/FilenameUtils.java URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/FilenameUtils.java?rev=779790&view=auto ============================================================================== --- maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/FilenameUtils.java (added) +++ maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/FilenameUtils.java Thu May 28 23:02:38 2009 @@ -0,0 +1,43 @@ +package org.apache.maven.scm.util; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.File; + +import org.codehaus.plexus.util.StringUtils; + +public class FilenameUtils +{ + public static String normalizeFilename( File file ) + { + return normalizeFilename( file.getName() ); + } + + /** + * Replace duplicated [back]slash to slash. + * + * @param filename + * @return + */ + public static String normalizeFilename( String filename ) + { + return StringUtils.replace( StringUtils.replace( filename, "\\", "/" ), "//", "/" ); + } +} Propchange: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/FilenameUtils.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/FilenameUtils.java ------------------------------------------------------------------------------ svn:keywords = Author Date Revision Id Added: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/ThreadSafeDateFormat.java URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/ThreadSafeDateFormat.java?rev=779790&view=auto ============================================================================== --- maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/ThreadSafeDateFormat.java (added) +++ maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/ThreadSafeDateFormat.java Thu May 28 23:02:38 2009 @@ -0,0 +1,76 @@ +package org.apache.maven.scm.util; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.lang.ref.SoftReference; +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Thread-safe version of java.text.DateFormat. + * You can declare it as a static final variable: + * <code> + * private static final ThreadSafeDateFormat DATE_FORMAT = new ThreadSafeDateFormat( DATE_PATTERN ); + * </code> + */ +public class ThreadSafeDateFormat extends DateFormat +{ + private static final long serialVersionUID = 3786090697869963812L; + + private final String m_sDateFormat; + + public ThreadSafeDateFormat(String sDateFormat) + { + m_sDateFormat = sDateFormat; + } + + private final ThreadLocal m_formatCache = new ThreadLocal() + { + public Object get() + { + SoftReference softRef = (SoftReference) super.get(); + if (softRef == null || softRef.get() == null) + { + softRef = new SoftReference( new SimpleDateFormat(m_sDateFormat) ); + super.set(softRef); + } + return softRef; + } + }; + + private DateFormat getDateFormat() + { + return (DateFormat) ((SoftReference)m_formatCache.get()).get(); + } + + public StringBuffer format(Date date, StringBuffer toAppendTo, + FieldPosition fieldPosition) + { + return getDateFormat().format(date, toAppendTo, fieldPosition); + } + + public Date parse(String source, ParsePosition pos) + { + return getDateFormat().parse(source, pos); + } +} Propchange: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/ThreadSafeDateFormat.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/util/ThreadSafeDateFormat.java ------------------------------------------------------------------------------ svn:keywords = Author Date Revision Id Modified: maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ChangeFileTest.java URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ChangeFileTest.java?rev=779790&r1=779789&r2=779790&view=diff ============================================================================== --- maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ChangeFileTest.java (original) +++ maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ChangeFileTest.java Thu May 28 23:02:38 2009 @@ -37,6 +37,14 @@ assertEquals( "test.java", f.toString() ); } + public void testNewFileRevision() + { + ChangeFile f = new ChangeFile( "test.java", "1.2.3" ); + assertEquals( "test.java", f.getName() ); + assertEquals( "1.2.3", f.getRevision() ); + assertEquals( "test.java, 1.2.3", f.toString() ); + } + public void testNewRevisionFile() { ChangeFile f = new ChangeFile( "test.java", "revision1" ); Modified: maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ChangeSetTest.java URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ChangeSetTest.java?rev=779790&r1=779789&r2=779790&view=diff ============================================================================== --- maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ChangeSetTest.java (original) +++ maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ChangeSetTest.java Thu May 28 23:02:38 2009 @@ -43,10 +43,16 @@ */ public void setUp() { - instance = new ChangeSet(); + instance = createInstance(); + } + + private static ChangeSet createInstance() + { + ChangeSet instance = new ChangeSet(); instance.setAuthor( "dion" ); instance.setComment( "comment" ); instance.setDate( "2002/04/01 00:00:00" ); + return instance; } /** @@ -57,6 +63,12 @@ ChangeFile file = new ChangeFile( "maven:dummy" ); instance.addFile( file ); assertTrue( "File name not found in list", instance.toString().indexOf( "maven:dummy" ) != -1 ); + + assertTrue( instance.containsFilename("maven:") ); + assertTrue( instance.containsFilename(":dummy") ); + assertTrue( instance.containsFilename(":") ); + assertTrue( instance.containsFilename("maven:dummy") ); + assertFalse( instance.containsFilename("dammy") ); } /** @@ -124,6 +136,7 @@ assertEquals( "Date value not set correctly", date, instance.getDate() ); } + /** * Test of setDate method with String */ @@ -158,4 +171,66 @@ return cal.getTime(); } + + public void testEscapeValue() + { + assertEquals( "", ChangeSet.escapeValue("") ); + assertEquals( "'", ChangeSet.escapeValue("'") ); + assertEquals( "a", ChangeSet.escapeValue("a") ); + assertEquals( "a'", ChangeSet.escapeValue("a'") ); + assertEquals( "'a'", ChangeSet.escapeValue("'a'") ); + + assertEquals( "a<b>c", ChangeSet.escapeValue("a<b>c") ); + assertEquals( "'&;<>"", ChangeSet.escapeValue("'&;<>\"") ); + } + + public void testEquals() + { + ChangeSet instance2 = createInstance(); + assertEquals(instance, instance2); + + instance2.setComment("another comment"); + assertFalse(instance2.equals(instance)); + + instance2.setComment("comment"); + assertEquals(instance, instance2); + } + + public void testHashCode() + { + int hashCode1 = instance.hashCode(); + instance.setAuthor("anotherAuthor"); + + assertFalse( hashCode1 == instance.hashCode() ); + instance.setAuthor( "dion" ); + assertEquals( hashCode1, instance.hashCode() ); + } + + public void testToXml() + { + String sXml = instance.toXML(); + assertNotNull(sXml); + + assertTrue(sXml.indexOf("<changelog-entry>") > -1); + assertTrue(sXml.indexOf("</changelog-entry>") > -1); + } + + public void testToXmlWithFiles() + { + instance.addFile( new ChangeFile( "maven1:dummy" ) ); + instance.addFile( new ChangeFile( "maven2:dummy2" ) ); + + String sXml = instance.toXML(); + assertNotNull(sXml); + + assertTrue(sXml.indexOf("<changelog-entry>") > -1); + assertTrue(sXml.indexOf("</changelog-entry>") > -1); + + assertTrue(sXml.indexOf("<file>") > -1); + assertTrue(sXml.indexOf("<name>maven1:dummy</name>") > -1); + assertTrue(sXml.indexOf("<name>maven2:dummy2</name>") > -1); + + + } + } Modified: maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ScmFileSetTest.java URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ScmFileSetTest.java?rev=779790&r1=779789&r2=779790&view=diff ============================================================================== --- maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ScmFileSetTest.java (original) +++ maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/ScmFileSetTest.java Thu May 28 23:02:38 2009 @@ -19,13 +19,13 @@ * under the License. */ -import junit.framework.TestCase; - import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.List; +import junit.framework.TestCase; + /** * @author dtran */ @@ -56,6 +56,24 @@ return filename.substring( getBasedir().length(), filename.length() ); } + public void testFilesList() + throws IOException + { + ScmFileSet fileSet = new ScmFileSet( new File( getBasedir(), "src" ), "**/**" ); + assertEquals( "src", fileSet.getBasedir().getName() ); + assertEquals( "**/**", fileSet.getIncludes() ); + // assertEquals( ScmFileSet.DEFAULT_EXCLUDES, fileSet.getExcludes() ); + assertTrue( "List of files should be longer than 10 elements, but received: " + fileSet.getFileList().size(), + fileSet.getFileList().size() > 10 ); + } + + public void testFilesListWithoutIncludesResultsEmptyList() + throws IOException + { + ScmFileSet fileSet = new ScmFileSet( new File( getBasedir(), "src" ) ); + assertEquals( 0, fileSet.getFileList().size() ); + } + public void testFilesListExcludes() throws IOException { Added: maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/util/FilenameUtilsTest.java URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/util/FilenameUtilsTest.java?rev=779790&view=auto ============================================================================== --- maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/util/FilenameUtilsTest.java (added) +++ maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/util/FilenameUtilsTest.java Thu May 28 23:02:38 2009 @@ -0,0 +1,40 @@ +package org.apache.maven.scm.util; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import junit.framework.TestCase; + +public class FilenameUtilsTest + extends TestCase +{ + + public void testNormalize() + { + assertNull( FilenameUtils.normalizeFilename( (String) null ) ); + assertEquals( "", FilenameUtils.normalizeFilename( "" ) ); + + assertEquals( "c:", FilenameUtils.normalizeFilename( "c:" ) ); + assertEquals( "c:/", FilenameUtils.normalizeFilename( "c:\\" ) ); + assertEquals( "c:/", FilenameUtils.normalizeFilename( "c:/" ) ); + assertEquals( "c:/", FilenameUtils.normalizeFilename( "c://" ) ); + + assertEquals( "c:/", FilenameUtils.normalizeFilename( "c:\\/" ) ); + } +} Propchange: maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/util/FilenameUtilsTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/scm/trunk/maven-scm-api/src/test/java/org/apache/maven/scm/util/FilenameUtilsTest.java ------------------------------------------------------------------------------ svn:keywords = Author Date Revision Id