/*
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the Classpath exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.btrace.runtime;
import com.sun.btrace.DebugSupport;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Map;
import javax.xml.bind.*;
import javax.xml.bind.helpers.DefaultValidationEventHandler;
import java.util.concurrent.ConcurrentHashMap;
/**
* This class loads BTrace probe descriptor XML files and
* caches the probe descriptions in a map. The XML to object
* unmarshalling is done using JAXB.
*
* @author A. Sundararajan
*/
final class ProbeDescriptorLoader {
// directories to search probe descriptor XML files.
private final String[] probeDescDirs;
private final DebugSupport debug;
ProbeDescriptorLoader(String probeDescPath, DebugSupport ds) {
// split probe descriptor path into directories
this.probeDescDirs = probeDescPath != null ?
probeDescPath.split(File.pathSeparator) : null;
this.debug = ds;
}
// cache for loaded probe descriptors
private static final Map<String, ProbeDescriptor> probeDescMap;
static {
probeDescMap = new ConcurrentHashMap<>();
}
ProbeDescriptor load(String namespace) {
// check in the cache
ProbeDescriptor res = probeDescMap.get(namespace);
if (res != null) {
if (debug.isDebug()) debug.debug("probe descriptor cache hit for " + namespace);
return res;
} else {
// load probe descriptor for the given namespace
InputStream file = openDescriptor(namespace);
if (file == null) {
if (debug.isDebug()) debug.debug("didn't find probe descriptor file " + namespace);
return null;
}
ProbeDescriptor pd = load(file);
if (pd != null) {
if (debug.isDebug()) debug.debug("read probe descriptor for " + namespace);
probeDescMap.put(namespace, pd);
}
return pd;
}
}
// unmarshall BTrace probe descriptor from XML
private ProbeDescriptor load(InputStream stream) {
try {
JAXBContext jc = JAXBContext.newInstance("com.sun.btrace.annotations:com.sun.btrace.runtime");
Unmarshaller u = jc.createUnmarshaller();
u.setEventHandler(new DefaultValidationEventHandler());
ProbeDescriptor pd = (ProbeDescriptor)u.unmarshal(stream);
pd.setProbes(pd.getProbes());
return pd;
} catch (JAXBException exp) {
if (debug.isDebug()) debug.debug(exp);
return null;
}
}
// look for <namespace>.xml file in each probe descriptor dir or on classpath
private InputStream openDescriptor(String namespace) {
InputStream is = null;
if (probeDescDirs != null) {
is = openDescriptorFromDirs(namespace);
}
if (is == null) {
is = openDescriptorFromClassPath(namespace);
}
if (is == null && debug.isDebug()) debug.debug("no probe descriptor found for " + namespace);
return is;
}
private InputStream openDescriptorFromDirs(String namespace) {
String desc = namespace.trim() + ".xml";
for (String dir : probeDescDirs) {
File f = new File(dir.trim(), desc);
if (debug.isDebug()) debug.debug("looking for probe descriptor file '" + f.getPath() + "' (" + f.exists() + ", " + f.isFile() + ")");
if (f.exists() && f.isFile()) {
if (debug.isDebug()) debug.debug("probe descriptor for " + namespace + " is " + f);
try {
return new FileInputStream(f);
} catch (FileNotFoundException e) {
// ignore; never happens
}
}
}
return null;
}
private InputStream openDescriptorFromClassPath(String namespace) {
String target = Constants.EMBEDDED_BTRACE_SECTION_HEADER + namespace.trim() + ".xml";
if (debug.isDebug()) debug.debug("looking for probe descriptor file '" + target);
return ClassLoader.getSystemResourceAsStream(target);
}
}