
io.ebean.enhance.common.AgentManifest Maven / Gradle / Ivy
package io.ebean.enhance.common;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
/**
* Reads all the META-INF/ebean.mf and META-INF/ebean-typequery.mf resources with the locations
* of all the entity beans (and hence locations of query beans).
*/
public class AgentManifest {
enum TxProfileMode {
NONE,
ENABLED,
MANUAL
}
private final Set entityPackages = new HashSet<>();
private final Set transactionalPackages = new HashSet<>();
private final Set querybeanPackages = new HashSet<>();
private TxProfileMode transactionProfilingMode = TxProfileMode.NONE;
/**
* Start profileId when automatically assigned by enhancement.
*/
private int transactionProfilingStart = 1000;
private boolean transientInternalFields;
private boolean checkNullManyFields = true;
public static AgentManifest read(ClassLoader classLoader, Set initialPackages) {
try {
return new AgentManifest(initialPackages)
.readManifests(classLoader, "META-INF/ebean-typequery.mf")
.readManifests(classLoader, "META-INF/ebean.mf")
.readManifests(classLoader, "ebean.mf");
} catch (IOException e) {
// log to standard error and return empty
System.err.println("Agent: error reading ebean manifest resources");
e.printStackTrace();
return new AgentManifest();
}
}
/**
* Construct with some packages defined externally.
*/
public AgentManifest(Set initialPackages) {
if (initialPackages != null) {
entityPackages.addAll(initialPackages);
}
}
/**
* Construct with no initial packages (to use with addRaw()).
*/
public AgentManifest() {
}
public String toString() {
return "entityPackages:" + entityPackages + " querybeanPackages:" + querybeanPackages
+ " transactionalPackages:" + transactionalPackages + " profilingMode:" + transactionProfilingMode;
}
/**
* Return the initial starting profileId when automatically assigned.
*/
int transactionProfilingStart() {
switch (transactionProfilingMode) {
case NONE:
return -1;
case MANUAL:
return 0;
case ENABLED:
return transactionProfilingStart;
default: {
return transactionProfilingStart;
}
}
}
/**
* Return the parsed set of packages that type query beans are in.
*/
public Set getEntityPackages() {
return entityPackages;
}
/**
* Return true if transactional enhancement is turned off.
*/
public boolean isTransactionalNone() {
return transactionalPackages.contains("none") && transactionalPackages.size() == 1;
}
/**
* Return true if we should use transient internal fields.
*/
public boolean isTransientInternalFields() {
return transientInternalFields;
}
/**
* Return false if enhancement should skip checking for null many fields.
*/
public boolean isCheckNullManyFields() {
return checkNullManyFields;
}
/**
* Return true if query bean enhancement is turned off.
*/
public boolean isQueryBeanNone() {
return querybeanPackages.contains("none") && querybeanPackages.size() == 1;
}
/**
* Return the packages that should be enhanced for transactional.
* An empty set means all packages are scanned for transaction classes and methods.
*/
public Set getTransactionalPackages() {
return transactionalPackages;
}
/**
* Return the packages that should be enhanced for query bean use.
* An empty set means all packages are scanned for transaction classes and methods.
*/
public Set getQuerybeanPackages() {
return querybeanPackages;
}
/**
* Read all the specific manifest files and return the set of packages containing type query beans.
*/
AgentManifest readManifests(ClassLoader classLoader, String path) throws IOException {
Enumeration resources = classLoader.getResources(path);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
try {
addResource(url.openStream());
} catch (IOException e) {
System.err.println("Error reading manifest resources " + url);
e.printStackTrace();
}
}
return this;
}
/**
* Add given the manifest InputStream.
*/
public void addResource(InputStream is) throws IOException {
try {
addManifest(new Manifest(is));
} finally {
try {
is.close();
} catch (IOException e) {
System.err.println("Error closing manifest resource");
e.printStackTrace();
}
}
}
void readProfilingMode(Attributes attributes) {
String mode = attributes.getValue("transaction-profiling");
if (mode != null) {
transactionProfilingMode = parseMode(mode);
}
}
private TxProfileMode parseMode(String mode) {
switch (mode.trim().toLowerCase()) {
case "enabled":
case "auto":
case "enable":
return TxProfileMode.ENABLED;
case "manual":
return TxProfileMode.MANUAL;
case "none":
return TxProfileMode.NONE;
default:
return TxProfileMode.NONE;
}
}
void readProfilingStart(Attributes attributes) {
String start = attributes.getValue("transaction-profiling-startvalue");
if (start != null) {
try {
transactionProfilingStart = Integer.parseInt(start);
} catch (NumberFormatException e) {
// ignore
}
}
}
private void addManifest(Manifest manifest) {
Attributes attributes = manifest.getMainAttributes();
readProfilingMode(attributes);
readProfilingStart(attributes);
readOptions(attributes);
add(entityPackages, attributes.getValue("packages"));
add(entityPackages, attributes.getValue("entity-packages"));
add(transactionalPackages, attributes.getValue("transactional-packages"));
add(querybeanPackages, attributes.getValue("querybean-packages"));
}
private void readOptions(Attributes attributes) {
transientInternalFields = bool("transient-internal-fields", transientInternalFields, attributes);
checkNullManyFields = bool("check-null-many-fields", checkNullManyFields, attributes);
}
private boolean bool(String key, boolean defaultValue, Attributes attributes) {
String val = attributes.getValue(key);
return val != null ? Boolean.parseBoolean(val) : defaultValue;
}
/**
* Collect each individual package splitting by delimiters.
*/
private void add(Set addTo, String packages) {
if (packages != null) {
String[] split = packages.split(",|;| ");
for (String aSplit : split) {
String pkg = aSplit.trim();
if (!pkg.isEmpty()) {
addTo.add(pkg);
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy