package aQute.lib.spring;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Descriptors.PackageRef;
import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.Resource;
import aQute.lib.io.IO;
public class XMLType {
Transformer transformer;
Pattern paths;
String root;
static Pattern QN = Pattern.compile("[_A-Za-z$][_A-Za-z0-9$]*(\\.[_A-Za-z$][_A-Za-z0-9$]*)*");
public XMLType(URL source, String root, String paths) throws Exception {
transformer = getTransformer(source);
this.paths = Pattern.compile(paths);
this.root = root;
}
public Set<String> analyze(InputStream in) throws Exception {
Set<String> refers = new HashSet<String>();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
Result r = new StreamResult(bout);
Source s = new StreamSource(in);
transformer.transform(s, r);
try (BufferedReader br = IO.reader(bout.toString("UTF-8"))) {
String line = br.readLine();
while (line != null) {
line = line.trim();
if (line.length() > 0) {
String parts[] = line.split("\\s*,\\s*");
for (int i = 0; i < parts.length; i++) {
String pack = toPackage(parts[i]);
if (pack != null)
refers.add(pack);
}
}
line = br.readLine();
}
}
return refers;
}
static String toPackage(String fqn) {
int n = fqn.lastIndexOf('.');
if (n < 0 || n + 1 >= fqn.length())
return null;
char c = fqn.charAt(n + 1);
if (Character.isJavaIdentifierStart(c) && Character.isUpperCase(c)) {
String other = fqn.substring(0, n);
return toPackage(other);
}
return fqn;
}
public boolean analyzeJar(Analyzer analyzer) throws Exception {
Jar jar = analyzer.getJar();
Map<String,Resource> dir = jar.getDirectories().get(root);
if (dir == null || dir.isEmpty()) {
Resource resource = jar.getResource(root);
if (resource != null)
process(analyzer, root, resource);
return false;
}
for (Iterator<Map.Entry<String,Resource>> i = dir.entrySet().iterator(); i.hasNext();) {
Map.Entry<String,Resource> entry = i.next();
String path = entry.getKey();
Resource resource = entry.getValue();
if (paths.matcher(path).matches()) {
process(analyzer, path, resource);
}
}
return false;
}
private void process(Analyzer analyzer, String path, Resource resource) {
try {
Set<String> set;
try (InputStream in = resource.openInputStream()) {
set = analyze(in);
}
for (Iterator<String> r = set.iterator(); r.hasNext();) {
PackageRef pack = analyzer.getPackageRef(r.next());
if (!QN.matcher(pack.getFQN()).matches())
analyzer.warning("Package does not seem a package in spring resource (%s): %s", path, pack);
if (!analyzer.getReferred().containsKey(pack))
analyzer.getReferred().put(pack);
}
} catch (Exception e) {
analyzer.error("Unexpected exception in processing spring resources(%s): %s", path, e);
}
}
protected Transformer getTransformer(java.net.URL url) throws Exception {
TransformerFactory tf = TransformerFactory.newInstance();
Source source = new StreamSource(url.openStream());
return tf.newTransformer(source);
}
}