1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.felix.bundleplugin;
20
21
22 import java.util.Collection;
23 import java.util.Iterator;
24 import java.util.LinkedHashSet;
25 import java.util.Map;
26 import java.util.regex.Pattern;
27
28 import org.apache.maven.artifact.Artifact;
29 import org.apache.maven.plugin.MojoExecutionException;
30
31 import aQute.bnd.osgi.Instruction;
32 import aQute.bnd.header.OSGiHeader;
33
34
35
36
37
38
39
40 public abstract class AbstractDependencyFilter
41 {
42 private static final Pattern MISSING_KEY_PATTERN = Pattern.compile( "(^|,)\\p{Blank}*(!)?\\p{Blank}*([a-zA-Z]+=)" );
43
44
45
46
47 private final Collection m_dependencyArtifacts;
48
49
50 public AbstractDependencyFilter( Collection dependencyArtifacts )
51 {
52 m_dependencyArtifacts = dependencyArtifacts;
53 }
54
55 private static abstract class DependencyFilter
56 {
57 private final Instruction m_instruction;
58 private final String m_defaultValue;
59
60
61 public DependencyFilter( String expression )
62 {
63 this( expression, "" );
64 }
65
66
67 public DependencyFilter( String expression, String defaultValue )
68 {
69 m_instruction = new Instruction( expression );
70 m_defaultValue = defaultValue;
71 }
72
73
74 public void filter( Collection dependencies )
75 {
76 for ( Iterator i = dependencies.iterator(); i.hasNext(); )
77 {
78 if ( false == matches( ( Artifact ) i.next() ) )
79 {
80 i.remove();
81 }
82 }
83 }
84
85
86 abstract boolean matches( Artifact dependency );
87
88
89 boolean matches( String text )
90 {
91 boolean result;
92
93 if ( null == text )
94 {
95 result = m_instruction.matches( m_defaultValue );
96 }
97 else
98 {
99 result = m_instruction.matches( text );
100 }
101
102 return m_instruction.isNegated() ? !result : result;
103 }
104 }
105
106
107 protected final void processInstructions( String header ) throws MojoExecutionException
108 {
109 Map instructions = OSGiHeader.parseHeader( MISSING_KEY_PATTERN.matcher( header ).replaceAll( "$1$2*;$3" ) );
110
111 Collection availableDependencies = new LinkedHashSet( m_dependencyArtifacts );
112
113 DependencyFilter filter;
114 for ( Iterator clauseIterator = instructions.entrySet().iterator(); clauseIterator.hasNext(); )
115 {
116 String inline = "false";
117
118
119 Collection filteredDependencies = new LinkedHashSet( availableDependencies );
120
121
122 Map.Entry clause = ( Map.Entry ) clauseIterator.next();
123 String primaryKey = ( ( String ) clause.getKey() ).replaceFirst( "~+$", "" );
124 boolean isNegative = primaryKey.startsWith( "!" );
125 if ( isNegative )
126 {
127 primaryKey = primaryKey.substring( 1 );
128 }
129
130 if ( !"*".equals( primaryKey ) )
131 {
132 filter = new DependencyFilter( primaryKey )
133 {
134 boolean matches( Artifact dependency )
135 {
136 return super.matches( dependency.getArtifactId() );
137 }
138 };
139
140 filter.filter( filteredDependencies );
141 }
142
143 for ( Iterator attrIterator = ( ( Map ) clause.getValue() ).entrySet().iterator(); attrIterator.hasNext(); )
144 {
145
146 Map.Entry attr = ( Map.Entry ) attrIterator.next();
147 if ( "groupId".equals( attr.getKey() ) )
148 {
149 filter = new DependencyFilter( ( String ) attr.getValue() )
150 {
151 boolean matches( Artifact dependency )
152 {
153 return super.matches( dependency.getGroupId() );
154 }
155 };
156 }
157 else if ( "artifactId".equals( attr.getKey() ) )
158 {
159 filter = new DependencyFilter( ( String ) attr.getValue() )
160 {
161 boolean matches( Artifact dependency )
162 {
163 return super.matches( dependency.getArtifactId() );
164 }
165 };
166 }
167 else if ( "version".equals( attr.getKey() ) )
168 {
169 filter = new DependencyFilter( ( String ) attr.getValue() )
170 {
171 boolean matches( Artifact dependency )
172 {
173 try
174 {
175
176 return super.matches( dependency.getSelectedVersion().toString() );
177 }
178 catch ( Exception e )
179 {
180 return super.matches( dependency.getVersion() );
181 }
182 }
183 };
184 }
185 else if ( "scope".equals( attr.getKey() ) )
186 {
187 filter = new DependencyFilter( ( String ) attr.getValue(), "compile" )
188 {
189 boolean matches( Artifact dependency )
190 {
191 return super.matches( dependency.getScope() );
192 }
193 };
194 }
195 else if ( "type".equals( attr.getKey() ) )
196 {
197 filter = new DependencyFilter( ( String ) attr.getValue(), "jar" )
198 {
199 boolean matches( Artifact dependency )
200 {
201 return super.matches( dependency.getType() );
202 }
203 };
204 }
205 else if ( "classifier".equals( attr.getKey() ) )
206 {
207 filter = new DependencyFilter( ( String ) attr.getValue() )
208 {
209 boolean matches( Artifact dependency )
210 {
211 return super.matches( dependency.getClassifier() );
212 }
213 };
214 }
215 else if ( "optional".equals( attr.getKey() ) )
216 {
217 filter = new DependencyFilter( ( String ) attr.getValue(), "false" )
218 {
219 boolean matches( Artifact dependency )
220 {
221 return super.matches( "" + dependency.isOptional() );
222 }
223 };
224 }
225 else if ( "inline".equals( attr.getKey() ) )
226 {
227 inline = ( String ) attr.getValue();
228 continue;
229 }
230 else
231 {
232 throw new MojoExecutionException( "Unexpected attribute " + attr.getKey() );
233 }
234
235
236 filter.filter( filteredDependencies );
237 }
238
239 if ( isNegative )
240 {
241
242 availableDependencies.removeAll( filteredDependencies );
243 if ( !clauseIterator.hasNext() )
244 {
245
246 processDependencies( availableDependencies, inline );
247 }
248 }
249 else
250 {
251
252 processDependencies( filteredDependencies, inline );
253 }
254 }
255 }
256
257
258 protected abstract void processDependencies( Collection dependencies, String inline );
259 }