Skip to content

Commit 05b1968

Browse files
committed
o Made two "ls" forks parallel
1 parent 0b1473e commit 05b1968

File tree

4 files changed

+371
-241
lines changed

4 files changed

+371
-241
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<dependency>
2828
<groupId>org.codehaus.plexus</groupId>
2929
<artifactId>plexus-utils</artifactId>
30-
<version>2.0.5</version>
30+
<version>3.0</version>
3131
</dependency>
3232
<dependency>
3333
<groupId>org.codehaus.plexus</groupId>
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
package org.codehaus.plexus.components.io.attributes;
2+
3+
/*
4+
* Copyright 2011 The Codehaus Foundation.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import java.text.ParseException;
20+
import java.text.SimpleDateFormat;
21+
import java.util.HashMap;
22+
import java.util.HashSet;
23+
import java.util.LinkedHashMap;
24+
import java.util.Map;
25+
import java.util.Set;
26+
import java.util.regex.Pattern;
27+
import org.codehaus.plexus.logging.Logger;
28+
import org.codehaus.plexus.util.cli.StreamConsumer;
29+
30+
/**
31+
* @author Kristian Rosenvold
32+
*/
33+
abstract class AttributeParser
34+
implements StreamConsumer
35+
{
36+
protected static final Pattern LINE_SPLITTER = Pattern.compile( "\\s+" );
37+
protected static final int[] LS_LAST_DATE_PART_INDICES = { 7, 7, 6 };
38+
39+
protected final StreamConsumer delegate;
40+
41+
protected final Map<String, PlexusIoResourceAttributes>
42+
attributesByPath = new LinkedHashMap<String, PlexusIoResourceAttributes>();
43+
44+
45+
private final Logger logger;
46+
47+
private boolean nextIsPathPrefix = false;
48+
49+
private String pathPrefix = "";
50+
51+
private final SimpleDateFormat[] LS_DATE_FORMATS;
52+
53+
public AttributeParser( StreamConsumer delegate, Logger logger )
54+
{
55+
this.delegate = delegate;
56+
this.logger = logger;
57+
LS_DATE_FORMATS =
58+
new SimpleDateFormat[]{ new SimpleDateFormat( "MMM dd yyyy" ), new SimpleDateFormat( "MMM dd HH:mm" ),
59+
new SimpleDateFormat( "yyyy-MM-dd HH:mm" ), };
60+
}
61+
62+
public void consumeLine( String line )
63+
{
64+
if ( PlexusIoResourceAttributeUtils.totalLinePattern.matcher( line ).matches() )
65+
{
66+
// skip it.
67+
}
68+
else if ( line.trim().length() == 0 )
69+
{
70+
nextIsPathPrefix = true;
71+
72+
if ( logger.isDebugEnabled() )
73+
{
74+
logger.debug( "Anticipating path prefix in next line" );
75+
}
76+
}
77+
else if ( nextIsPathPrefix )
78+
{
79+
if ( !line.endsWith( ":" ) )
80+
{
81+
if ( logger.isDebugEnabled() )
82+
{
83+
logger.debug( "Path prefix not found. Checking next line." );
84+
}
85+
}
86+
else
87+
{
88+
nextIsPathPrefix = false;
89+
pathPrefix = line.substring( 0, line.length() - 1 );
90+
91+
if ( !pathPrefix.endsWith( "/" ) )
92+
{
93+
pathPrefix += "/";
94+
}
95+
96+
if ( logger.isDebugEnabled() )
97+
{
98+
logger.debug( "Set path prefix to: " + pathPrefix );
99+
}
100+
}
101+
}
102+
else
103+
{
104+
String[] parts = LINE_SPLITTER.split( line );
105+
int lastDatePart = verifyParsability( line, parts, logger );
106+
107+
if ( lastDatePart > 0 )
108+
{
109+
int idx = line.indexOf( parts[lastDatePart] ) + parts[lastDatePart].length() + 1;
110+
111+
String path = pathPrefix + line.substring( idx );
112+
while ( path.length() > 0 && Character.isWhitespace( path.charAt( 0 ) ) )
113+
{
114+
path = path.substring( 1 );
115+
}
116+
117+
if ( logger.isDebugEnabled() )
118+
{
119+
logger.debug( "path: '" + path + "'" );
120+
logger.debug( "mode: '" + parts[0] + "'" );
121+
logger.debug( "uid: '" + parts[2] );
122+
logger.debug( "gid: '" + parts[3] );
123+
}
124+
125+
FileAttributes attributes;
126+
synchronized ( attributesByPath )
127+
{
128+
attributes = new FileAttributes();
129+
attributes.setLsModeline( parts[0] );
130+
attributesByPath.put( path, attributes );
131+
processAttributes( attributes, parts);
132+
}
133+
}
134+
}
135+
136+
delegate.consumeLine( line );
137+
}
138+
139+
protected abstract void processAttributes( FileAttributes attributes, String[] parts );
140+
141+
public Map<String, PlexusIoResourceAttributes> getAttributesByPath()
142+
{
143+
return attributesByPath;
144+
}
145+
146+
private int verifyParsability( String line, String[] parts, Logger logger )
147+
{
148+
if ( parts.length > 7 )
149+
{
150+
String dateCandidate = parts[5] + " " + parts[6] + " " + parts[7];
151+
for ( int i = 0; i < LS_DATE_FORMATS.length; i++ )
152+
{
153+
try
154+
{
155+
LS_DATE_FORMATS[i].parse( dateCandidate );
156+
return LS_LAST_DATE_PART_INDICES[i];
157+
}
158+
catch ( ParseException e )
159+
{
160+
if ( logger.isDebugEnabled() )
161+
{
162+
logger.debug( "Failed to parse date: '" + dateCandidate + "' using format: "
163+
+ LS_DATE_FORMATS[i].toPattern(), e );
164+
}
165+
}
166+
}
167+
}
168+
169+
if ( logger.isDebugEnabled() )
170+
{
171+
logger.debug( "Unparseable line: '" + line
172+
+ "'\nReason: unrecognized date format; ambiguous start-index for path in listing." );
173+
}
174+
175+
return -1;
176+
}
177+
178+
static class NumericUserIDAttributeParser
179+
extends AttributeParser
180+
{
181+
NumericUserIDAttributeParser( StreamConsumer delegate, Logger logger )
182+
{
183+
super( delegate, logger );
184+
}
185+
186+
@Override
187+
protected void processAttributes( FileAttributes attributes, String[] parts )
188+
{
189+
attributes.setUserId( (int) Long.parseLong( parts[2] ) );
190+
attributes.setGroupId( (int) Long.parseLong( parts[3] ) );
191+
192+
}
193+
}
194+
195+
static class SymbolicUserIDAttributeParser
196+
extends AttributeParser
197+
{
198+
SymbolicUserIDAttributeParser( StreamConsumer delegate, Logger logger )
199+
{
200+
super( delegate, logger );
201+
}
202+
203+
@Override
204+
protected void processAttributes( FileAttributes attributes, String[] parts )
205+
{
206+
attributes.setUserName( parts[2] );
207+
attributes.setGroupName( parts[3] );
208+
}
209+
210+
public Map<String, PlexusIoResourceAttributes> merge( NumericUserIDAttributeParser otherParser )
211+
{
212+
final Map<String, PlexusIoResourceAttributes> attributes = getAttributesByPath();
213+
if ( otherParser == null )
214+
{
215+
return attributes;
216+
}
217+
final Map<String, PlexusIoResourceAttributes> result = new HashMap<String, PlexusIoResourceAttributes>( );
218+
219+
final Map<String, PlexusIoResourceAttributes> otherAttributes = otherParser.getAttributesByPath();
220+
PlexusIoResourceAttributes thisAttribute, otherAttribute;
221+
222+
Set<String> allKeys = new HashSet<String>(attributes.keySet());
223+
allKeys.addAll( otherAttributes.keySet() );
224+
for ( String key : allKeys )
225+
{
226+
thisAttribute = attributes.get( key );
227+
otherAttribute = otherAttributes.get( key );
228+
if ( thisAttribute == null )
229+
{ // Slight workaround because symbolic parsing is failure prone
230+
thisAttribute = otherAttribute;
231+
}
232+
if ( thisAttribute != null && otherAttribute != null )
233+
{
234+
thisAttribute.setUserId( otherAttribute.getUserId() );
235+
thisAttribute.setGroupId( otherAttribute.getGroupId() );
236+
}
237+
result.put( key, thisAttribute);
238+
}
239+
return result;
240+
}
241+
}
242+
}

0 commit comments

Comments
 (0)