2424import java .util .ArrayList ;
2525import java .util .Arrays ;
2626import java .util .List ;
27+ import java .util .Map ;
2728import java .util .regex .Pattern ;
2829
2930import org .apache .uima .UIMAFramework ;
4445import aQute .bnd .osgi .Analyzer ;
4546import aQute .bnd .osgi .Resource ;
4647import aQute .bnd .service .AnalyzerPlugin ;
48+ import aQute .bnd .service .Plugin ;
49+ import aQute .lib .converter .Converter ;
50+ import aQute .service .reporter .Reporter ;
4751
48- @ BndPlugin (name = "UIMA" )
52+ @ BndPlugin (name = "UIMA" , parameters = UimaBndPlugin . Configuration . class )
4953public class UimaBndPlugin
50- implements AnalyzerPlugin
54+ implements AnalyzerPlugin , Plugin
5155{
52-
5356 private static final Logger LOG = LoggerFactory .getLogger (MethodHandles .lookup ().lookupClass ());
5457
5558 private static final Pattern XML_FILE = Pattern .compile (".*\\ .xml" );
@@ -58,6 +61,21 @@ public class UimaBndPlugin
5861
5962 private final static XMLParser PARSER = UIMAFramework .getXMLParser ();
6063
64+ private Reporter reporter ;
65+ private UimaBndPlugin .Configuration configuration ;
66+
67+ @ Override
68+ public void setProperties (Map <String , String > aMap ) throws Exception
69+ {
70+ configuration = Converter .cnv (UimaBndPlugin .Configuration .class , aMap );
71+ }
72+
73+ @ Override
74+ public void setReporter (Reporter aReporter )
75+ {
76+ reporter = aReporter ;
77+ }
78+
6179 @ Override
6280 public boolean analyzeJar (Analyzer analyzer ) throws Exception
6381 {
@@ -69,37 +87,37 @@ public boolean analyzeJar(Analyzer analyzer) throws Exception
6987 for (var entry : resources .entrySet ()) {
7088 var path = entry .getKey ();
7189 var resource = entry .getValue ();
72-
90+
7391 try {
7492 if (XML_FILE .matcher (path ).matches ()) {
75- importsProcessed += analyzeXmlFile (analyzer , path , resource );
93+ importsProcessed += analyzeXmlFile (analyzer , path , resource , 0 );
7694 }
7795 }
7896 catch (Exception e ) {
7997 analyzer .error ("Unexpected exception in processing resource (%s): %s" , path , e );
8098 }
8199 }
82100 }
83-
101+
84102 LOG .info ("UIMA bnd plugin processed {} imports" , importsProcessed );
85103
86104 return false ;
87105 }
88106
89- private int analyzeXmlFile (Analyzer analyzer , String path , Resource resource ) throws Exception
107+ private int analyzeXmlFile (Analyzer analyzer , String path , Resource resource , int level ) throws Exception
90108 {
91109 var desc = readUimaDescriptor (resource );
92110 if (desc == null ) {
93111 return 0 ;
94112 }
95113
96- LOG .debug ("Found {}: {}" , desc .getClass ().getSimpleName (), path );
114+ LOG .debug ("{} Found {}: {}" , repeat ( " " , level ) , desc .getClass ().getSimpleName (), path );
97115 var imports = getImportsFromDescriptor (desc );
98116
99117 var importsProcessed = 0 ;
100118 for (var imp : imports ) {
101119 if (imp .getName () != null ) {
102- handleImportByName (analyzer , path , imp );
120+ handleImportByName (analyzer , path , imp , level );
103121 importsProcessed ++;
104122 continue ;
105123 }
@@ -108,22 +126,21 @@ private int analyzeXmlFile(Analyzer analyzer, String path, Resource resource) th
108126 handleImportByLocation (imp );
109127 continue ;
110128 }
111-
129+
112130 LOG .warn (
113- "Found UIMA type system import without name and location - ignoring, please fix your type system description" );
131+ "Found UIMA import without name and location - ignoring, please fix your type system description" );
114132 }
115-
133+
116134 return importsProcessed ;
117135 }
118136
119137 private void handleImportByLocation (Import imp )
120138 {
121- LOG .warn (
122- "Found UIMA type system import by location: {} - ignoring, please only use import-by-name" ,
139+ LOG .warn ("Ignoring UIMA import by location (please only use import-by-name): {}" ,
123140 imp .getLocation ());
124141 }
125142
126- private void handleImportByName (Analyzer analyzer , String path , Import imp )
143+ private void handleImportByName (Analyzer analyzer , String path , Import imp , int level ) throws Exception
127144 {
128145 var tsdPackage = imp .getName ();
129146 int lastSeparatorPosition = tsdPackage .lastIndexOf ('.' );
@@ -132,18 +149,29 @@ private void handleImportByName(Analyzer analyzer, String path, Import imp)
132149 tsdPackage = tsdPackage .substring (0 , lastSeparatorPosition );
133150 }
134151
135- LOG .debug ("Found UIMA type system import by name: {}" , tsdPackage );
136-
137152 var pack = analyzer .getPackageRef (tsdPackage );
138153 if (!QN .matcher (pack .getFQN ()).matches ()) {
139- analyzer .warning ("Type system import does not seem to refer to a package (%s): %s" ,
140- path , pack );
154+ analyzer .warning ("Import does not seem to refer to a package (%s): %s" , path , pack );
141155 }
142156
143- if (!analyzer .getReferred ().containsKey (pack )) {
157+ var alreadyKnownImport = analyzer .getReferred ().containsKey (pack );
158+ if (!alreadyKnownImport ) {
144159 var attrs = new Attrs ();
145160 analyzer .getReferred ().put (pack , attrs );
146161 }
162+
163+ LOG .debug ("{}Found UIMA import by name: {} {}" , repeat (" " , level ), tsdPackage , alreadyKnownImport ? "" : "(new)" );
164+
165+ var importedResourcePath = imp .getName ().replace ('.' , '/' ) + ".xml" ;
166+ var importedResource = analyzer .findResource (importedResourcePath );
167+ if (importedResource == null ) {
168+ analyzer .warning ("Imported resource not found on classpath: {}" , importedResourcePath );
169+ return ;
170+ }
171+
172+ if (configuration == null || configuration .transitive (false )) {
173+ analyzeXmlFile (analyzer , importedResourcePath , importedResource , level + 1 );
174+ }
147175 }
148176
149177 private List <Import > getImportsFromDescriptor (XMLizable desc )
@@ -194,4 +222,22 @@ private static <T> List<T> asList(T[] aList)
194222
195223 return Arrays .asList (aList );
196224 }
225+
226+ private static String repeat (String aString , int aCount ) {
227+ if (aCount == 0 ) {
228+ return "" ;
229+ }
230+
231+ var buf = new StringBuilder ();
232+ for (var i = 0 ; i < aCount ; i ++) {
233+ buf .append (aString );
234+ }
235+
236+ return buf .toString ();
237+ }
238+
239+ public static interface Configuration
240+ {
241+ boolean transitive (boolean aDefault );
242+ }
197243}
0 commit comments