Skip to content

Commit

Permalink
Merge pull request OpenLiberty#19 from arturdzm/EAR-support
Browse files Browse the repository at this point in the history
Issues OpenLiberty#1545 - Add EAR support, keep track of multiple apps
  • Loading branch information
navidsh authored Jan 31, 2018
2 parents b69082c + 1a98b96 commit f583396
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class ApplicationListener implements ApplicationStateListener {
public void applicationStarting(ApplicationInfo appInfo) throws StateChangeException {
if (appProcessor != null) {
try {
appProcessor.processApplication(appInfo);
appProcessor.addApplication(appInfo);
} catch (Throwable e) {
if (OpenAPIUtils.isEventEnabled(tc)) {
Tr.event(tc, "Failed to process application: " + e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
Expand All @@ -35,6 +36,7 @@
import com.ibm.websphere.ras.Tr;
import com.ibm.websphere.ras.TraceComponent;
import com.ibm.ws.container.service.app.deploy.ApplicationInfo;
import com.ibm.ws.container.service.app.deploy.EARApplicationInfo;
import com.ibm.ws.container.service.app.deploy.WebModuleInfo;
import com.ibm.ws.ffdc.annotation.FFDCIgnore;
import com.ibm.ws.microprofile.openapi.impl.core.util.Json;
Expand All @@ -50,6 +52,8 @@
import com.ibm.ws.microprofile.openapi.utils.OpenAPIUtils;
import com.ibm.ws.microprofile.openapi.utils.ServerInfo;
import com.ibm.wsspi.adaptable.module.Container;
import com.ibm.wsspi.adaptable.module.Entry;
import com.ibm.wsspi.adaptable.module.UnableToAdaptException;
import com.ibm.wsspi.http.VirtualHost;

/**
Expand All @@ -65,146 +69,193 @@ enum DocType {
YAML
}

private static ApplicationProcessor instance;
private OpenAPI document = null;
private ApplicationInfo currentApp = null;
private static ApplicationInfo currentApp = null;
private static Map<String, ApplicationInfo> applications = new HashMap<>();
private final ServerInfo serverInfo = new ServerInfo();

public void activate(ComponentContext cc) {
this.document = createBaseOpenAPIDocument();
instance = this;
if (currentApp != null) {
this.document = createBaseOpenAPIDocument();
processApplication(currentApp);
} else {
this.document = createBaseOpenAPIDocument();
}
}

public void processApplication(ApplicationInfo appInfo) {
public void addApplication(ApplicationInfo appInfo) {
synchronized (this.document) {

if (currentApp != null) {
return;
if (currentApp == null) {
processApplication(appInfo);
} else {
applications.put(appInfo.getName(), appInfo);
}
}
}

if (appInfo == null) {
return;
}
private OpenAPI processWebModule(Container appContainer, WebModuleInfo moduleInfo) {
ClassLoader appClassloader = moduleInfo.getClassLoader();
String contextRoot = moduleInfo.getContextRoot();

Container appContainer = appInfo.getContainer();
if (appContainer == null) {
return;
}
boolean isOASApp = false;

WebModuleInfo moduleInfo = OpenAPIUtils.getWebModuleInfo(appContainer);
if (moduleInfo == null) {
return;
}
ClassLoader appClassloader = moduleInfo.getClassLoader();
String contextRoot = moduleInfo.getContextRoot();

boolean isOASApp = false;

//read and process the MicroProfile config
ConfigProcessor configProcessor = new ConfigProcessor(appClassloader);

OpenAPI newDocument = null;
//Retrieve model from model reader
OASModelReader modelReader = OpenAPIUtils.getOASModelReader(appClassloader, configProcessor.getModelReaderClassName());
if (modelReader != null) {
try {
OpenAPI model = modelReader.buildModel();
if (model != null) {
isOASApp = true;
newDocument = model;
}
} catch (Throwable e) {
if (OpenAPIUtils.isEventEnabled(tc)) {
Tr.event(tc, "Failed to construct model from the application: " + e.getMessage());
}
//read and process the MicroProfile config
ConfigProcessor configProcessor = new ConfigProcessor(appClassloader);

OpenAPI newDocument = null;
//Retrieve model from model reader
OASModelReader modelReader = OpenAPIUtils.getOASModelReader(appClassloader, configProcessor.getModelReaderClassName());
if (modelReader != null) {
try {
OpenAPI model = modelReader.buildModel();
if (model != null) {
isOASApp = true;
newDocument = model;
}
} catch (Throwable e) {
if (OpenAPIUtils.isEventEnabled(tc)) {
Tr.event(tc, "Failed to construct model from the application: " + e.getMessage());
}
}
}

//Retrieve OpenAPI document as a string
String openAPIStaticFile = StaticFileProcessor.getOpenAPIFile(appContainer);
if (openAPIStaticFile != null) {
isOASApp = true;
SwaggerParseResult result = new OpenAPIV3Parser().readContents(openAPIStaticFile, newDocument, null, null);
if (result.getOpenAPI() != null) {
newDocument = result.getOpenAPI();
}
//Retrieve OpenAPI document as a string
String openAPIStaticFile = StaticFileProcessor.getOpenAPIFile(appContainer);
if (openAPIStaticFile != null) {
isOASApp = true;
SwaggerParseResult result = new OpenAPIV3Parser().readContents(openAPIStaticFile, newDocument, null, null);
if (result.getOpenAPI() != null) {
newDocument = result.getOpenAPI();
}
}

//Scan for annotated classes
AnnotationScanner scanner = OpenAPIUtils.creatAnnotationScanner(appClassloader, appContainer);
if (!configProcessor.isScanDisabled()) {
//Scan for annotated classes
AnnotationScanner scanner = OpenAPIUtils.creatAnnotationScanner(appClassloader, appContainer);
if (!configProcessor.isScanDisabled()) {

Set<String> classNamesToScan = new HashSet<>();
if (configProcessor.getClassesToScan() != null) {
classNamesToScan.addAll(configProcessor.getClassesToScan());
}
Set<String> classNamesToScan = new HashSet<>();
if (configProcessor.getClassesToScan() != null) {
classNamesToScan.addAll(configProcessor.getClassesToScan());
}

if (configProcessor.getPackagesToScan() != null) {
Set<String> foundClasses = scanner.getAnnotatedClassesNames();
for (String packageName : configProcessor.getPackagesToScan()) {
for (String className : foundClasses) {
if (className.startsWith(packageName)) {
classNamesToScan.add(className);
}
if (configProcessor.getPackagesToScan() != null) {
Set<String> foundClasses = scanner.getAnnotatedClassesNames();
for (String packageName : configProcessor.getPackagesToScan()) {
for (String className : foundClasses) {
if (className.startsWith(packageName)) {
classNamesToScan.add(className);
}
}
}
}

if (classNamesToScan.size() == 0 && scanner.anyAnnotatedClasses()) {
classNamesToScan.addAll(scanner.getAnnotatedClassesNames());
}
if (configProcessor.getClassesToExclude() != null) {
classNamesToScan.removeAll(configProcessor.getClassesToExclude());
}
if (configProcessor.getPackagesToExclude() != null) {
for (String packageToExclude : configProcessor.getPackagesToExclude()) {
Iterator<String> iterator = classNamesToScan.iterator();
while (iterator.hasNext()) {
if (iterator.next().startsWith(packageToExclude)) {
iterator.remove();
}
if (classNamesToScan.size() == 0 && scanner.anyAnnotatedClasses()) {
classNamesToScan.addAll(scanner.getAnnotatedClassesNames());
}
if (configProcessor.getClassesToExclude() != null) {
classNamesToScan.removeAll(configProcessor.getClassesToExclude());
}
if (configProcessor.getPackagesToExclude() != null) {
for (String packageToExclude : configProcessor.getPackagesToExclude()) {
Iterator<String> iterator = classNamesToScan.iterator();
while (iterator.hasNext()) {
if (iterator.next().startsWith(packageToExclude)) {
iterator.remove();
}
}
}
}

if (classNamesToScan.size() > 0) {
isOASApp = true;
Set<Class<?>> classes = new HashSet<>();
for (String clazz : classNamesToScan) {
try {
classes.add(appClassloader.loadClass(clazz));
} catch (ClassNotFoundException e) {
if (OpenAPIUtils.isEventEnabled(tc))
Tr.event(tc, "Failed to load class: " + e.getMessage());
if (classNamesToScan.size() > 0) {
isOASApp = true;
Set<Class<?>> classes = new HashSet<>();
for (String clazz : classNamesToScan) {
try {
classes.add(appClassloader.loadClass(clazz));
} catch (ClassNotFoundException e) {
if (OpenAPIUtils.isEventEnabled(tc)) {
Tr.event(tc, "Failed to load class: " + e.getMessage());
}
}
newDocument = new Reader(newDocument).read(classes);
}
newDocument = new Reader(newDocument).read(classes);
}
}

// Handle servers specified in configuration (before filtering)
handleServers(newDocument, configProcessor);
if (!isOASApp) {
return null;
}

// Filter
OASFilter oasFilter = OpenAPIUtils.getOASFilter(appClassloader, configProcessor.getOpenAPIFilterClassName());
// Handle servers specified in configuration (before filtering)
handleServers(newDocument, configProcessor);

if (oasFilter != null) {
OpenAPIModelWalker walker = new OpenAPIModelWalker(newDocument);
try {
walker.accept(new OpenAPIFilter(oasFilter));
} catch (Throwable e) {
if (OpenAPIUtils.isEventEnabled(tc)) {
Tr.event(tc, "Failed to call OASFilter: " + e.getMessage());
}
// Filter
OASFilter oasFilter = OpenAPIUtils.getOASFilter(appClassloader, configProcessor.getOpenAPIFilterClassName());

if (oasFilter != null) {
OpenAPIModelWalker walker = new OpenAPIModelWalker(newDocument);
try {
walker.accept(new OpenAPIFilter(oasFilter));
} catch (Throwable e) {
if (OpenAPIUtils.isEventEnabled(tc)) {
Tr.event(tc, "Failed to call OASFilter: " + e.getMessage());
}
}
}

if (isOASApp && currentApp == null) {
this.currentApp = appInfo;
this.serverInfo.setApplicationPath(contextRoot);
return newDocument;
}

if (OpenAPIUtils.isEventEnabled(tc)) {
Tr.event(this, tc, "Received new document");
@FFDCIgnore(UnableToAdaptException.class)
private void processApplication(ApplicationInfo appInfo) {
synchronized (this.document) {

if (appInfo == null) {
return;
}

Container appContainer = appInfo.getContainer();
if (appContainer == null) {
return;
}

WebModuleInfo moduleInfo = null;
if (appInfo instanceof EARApplicationInfo) {
for (Entry entry : appContainer) {
try {
Container c = entry.adapt(Container.class);
if (c != null) {
WebModuleInfo wmi = OpenAPIUtils.getWebModuleInfo(c);
if (wmi != null) {
OpenAPI openAPI = processWebModule(c, wmi);
if (openAPI != null) {
currentApp = appInfo;
this.document = openAPI;
break;
}
}
}

} catch (UnableToAdaptException e) {
if (OpenAPIUtils.isDebugEnabled(tc)) {
Tr.debug(tc, "Failed to adapt entry: " + e.getMessage());
}
}
}
this.document = newDocument;
} else {
moduleInfo = OpenAPIUtils.getWebModuleInfo(appContainer);
}

if (moduleInfo == null) {
return;
}

OpenAPI openAPI = processWebModule(appContainer, moduleInfo);
if (openAPI != null) {
currentApp = appInfo;
this.document = openAPI;
}
}
}
Expand Down Expand Up @@ -281,6 +332,17 @@ public void removeApplication(ApplicationInfo appInfo) {
currentApp = null;
this.serverInfo.setApplicationPath(null);
this.document = createBaseOpenAPIDocument();
Iterator<java.util.Map.Entry<String, ApplicationInfo>> iterator = applications.entrySet().iterator();
while (iterator.hasNext()) {
java.util.Map.Entry<String, ApplicationInfo> entry = iterator.next();
processApplication(entry.getValue());
iterator.remove();
if (currentApp != null) {
break;
}
}
} else {
applications.remove(appInfo.getName());
}
}
}
Expand Down Expand Up @@ -351,4 +413,10 @@ private void updateOpenAPIServer(VirtualHost vhost, Map<String, Object> props) {
}
}

/**
* @return the instance
*/
public static ApplicationProcessor getInstance() {
return instance;
}
}
Loading

0 comments on commit f583396

Please sign in to comment.