#731 - ENH: Add support for using ebean.mf manifest file for finding/defining packages to search for entities

This commit is contained in:
Robin Bygrave
2016-06-02 17:35:06 +12:00
parent b3828572fd
commit 1304646cce
23 changed files with 241 additions and 17 deletions
@@ -17,6 +17,8 @@ import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.cache.DefaultServerCachePlugin;
import com.avaje.ebeaninternal.server.cache.DefaultServerCacheManager;
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.core.bootup.BootupClassPathSearch;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.lib.ShutdownManager;
import org.avaje.datasource.DataSourceAlertFactory;
import org.avaje.datasource.DataSourceConfig;
@@ -22,6 +22,7 @@ import com.avaje.ebeaninternal.server.changelog.DefaultChangeLogListener;
import com.avaje.ebeaninternal.server.changelog.DefaultChangeLogPrepare;
import com.avaje.ebeaninternal.server.changelog.DefaultChangeLogRegister;
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.core.timezone.CloneDataTimeZone;
import com.avaje.ebeaninternal.server.core.timezone.DataTimeZone;
import com.avaje.ebeaninternal.server.core.timezone.NoDataTimeZone;
@@ -1,6 +1,7 @@
package com.avaje.ebeaninternal.server.core;
package com.avaje.ebeaninternal.server.core.bootup;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.server.core.ClassPathScanners;
import org.avaje.classpath.scanner.ClassPathScanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -10,10 +11,12 @@ import java.util.*;
/**
* Searches for interesting classes such as Entities, Embedded and ScalarTypes.
*/
class BootupClassPathSearch {
public class BootupClassPathSearch {
private static final Logger logger = LoggerFactory.getLogger(BootupClassPathSearch.class);
private static final String EBEAN_MF = "META-INF/ebean.mf";
private final List<String> packages;
private final List<ClassPathScanner> scanners;
@@ -28,7 +31,11 @@ class BootupClassPathSearch {
}
private BootupClassPathSearch(ServerConfig serverConfig) {
this.packages = serverConfig.getPackages();
// find packages defined in META-INF/ebean.mf resources
Set<String> mfPackages = ManifestReader.readManifests(serverConfig.getClassLoadConfig().getClassLoader(), EBEAN_MF);
this.packages = DistillPackages.distill(serverConfig.getPackages(), mfPackages);
this.scanners = ClassPathScanners.find(serverConfig);
}
@@ -1,4 +1,4 @@
package com.avaje.ebeaninternal.server.core;
package com.avaje.ebeaninternal.server.core.bootup;
import com.avaje.ebean.config.CompoundType;
import com.avaje.ebean.config.IdGenerator;
@@ -0,0 +1,48 @@
package com.avaje.ebeaninternal.server.core.bootup;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.TreeSet;
/**
* Distill packages into distinct top level packages for searching.
*/
class DistillPackages {
/**
* Distill the list of packages into distinct top level packages.
*/
static List<String> distill(Collection<String> packages, Collection<String> mfPackages) {
// sort into natural order
TreeSet<String> treeSet = new TreeSet<String>();
treeSet.addAll(packages);
treeSet.addAll(mfPackages);
List<String> distilled = new ArrayList<String>();
// build the distilled list
for (String pack : treeSet) {
if (notAlreadyContained(distilled, pack)) {
distilled.add(pack);
}
}
return distilled;
}
/**
* Return true if the package is not already contained in the distilled list.
*/
private static boolean notAlreadyContained(List<String> distilled, String pack) {
for (int i = 0; i < distilled.size(); i++) {
if (pack.startsWith(distilled.get(i))) {
return false;
}
}
return true;
}
}
@@ -0,0 +1,84 @@
package com.avaje.ebeaninternal.server.core.bootup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 resources with the package locations of entity beans.
*/
class ManifestReader {
private static final Logger logger = LoggerFactory.getLogger(ManifestReader.class);
private final Set<String> packageSet = new HashSet<String>();
/**
* Read the packages from ebean.mf manifest files found as resources.
*/
static Set<String> readManifests(ClassLoader classLoader, String resourcePath) {
return new ManifestReader().read(classLoader, resourcePath);
}
/**
* Read all the specific manifest files and return the set of packages containing type query beans.
*/
private Set<String> read(ClassLoader classLoader, String resourcePath) {
try {
Enumeration<URL> resources = classLoader.getResources(resourcePath);
while (resources.hasMoreElements()) {
InputStream is = resources.nextElement().openStream();
try {
read(new Manifest(is));
} finally {
close(is);
}
}
} catch (IOException e) {
logger.warn("Error reading META-INF/ebean.mf manifest resources", e);
}
return packageSet;
}
private void close(InputStream is) {
try {
is.close();
} catch (IOException e) {
logger.warn("Error closing manifest InputStream", e);
}
}
/**
* Read the packages from the manifest.
*/
private void read(Manifest manifest) throws IOException {
Attributes attributes = manifest.getMainAttributes();
String packages = attributes.getValue("packages");
if (packages != null) {
add(packages);
}
}
/**
* Collect each individual package splitting by delimiters.
*/
private void add(String packages) {
String[] split = packages.split(",|;| ");
for (int i = 0; i <split.length; i++) {
String pkg = split[i].trim();
if (!pkg.isEmpty()) {
packageSet.add(pkg);
}
}
}
}
@@ -22,7 +22,7 @@ import com.avaje.ebean.plugin.BeanType;
import com.avaje.ebeaninternal.api.ConcurrencyMode;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.api.TransactionEventTable;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.core.InternalConfiguration;
import com.avaje.ebeaninternal.server.core.Message;
@@ -1,7 +1,7 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.event.BeanFindController;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -1,7 +1,7 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.event.BeanQueryAdapter;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -3,7 +3,7 @@ package com.avaje.ebeaninternal.server.deploy;
import java.util.List;
import com.avaje.ebean.event.BeanPersistController;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -1,7 +1,7 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -1,7 +1,7 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.event.BeanPostLoad;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -1,6 +1,6 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
@@ -5,7 +5,7 @@ import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.api.SpiTransaction;
import com.avaje.ebeanservice.docstore.api.DocStoreUpdateProcessor;
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import java.sql.Connection;
@@ -6,7 +6,7 @@ import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebeaninternal.api.SpiTransaction;
import com.avaje.ebeanservice.docstore.api.DocStoreUpdateProcessor;
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import javax.sql.DataSource;
@@ -14,7 +14,7 @@ import com.avaje.ebeaninternal.api.TransactionEvent;
import com.avaje.ebeaninternal.api.TransactionEventTable;
import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD;
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import org.avaje.datasource.DataSourcePool;
import com.avaje.ebeanservice.docstore.api.DocStoreUpdateProcessor;
@@ -11,7 +11,7 @@ import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.config.dbplatform.DbType;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutable;
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutableResponse;
import com.avaje.ebeaninternal.server.type.reflect.ImmutableMeta;