Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Glassfish service name detector #579

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
interface AppServer {

/** Path to directory to be scanned for deployments. */
@Nullable
Path getDeploymentDir() throws Exception;

/**
* Returns a single class that, when present, determines that the given application server is
* active/running.
*/
@Nullable
Class<?> getServerClass();

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.resourceproviders;

import static java.util.logging.Level.FINE;

import com.google.errorprone.annotations.MustBeClosed;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import java.util.logging.Logger;
import java.util.stream.Stream;
import javax.annotation.Nullable;

final class AppServerServiceNameDetector implements ServiceNameDetector {

private static final Logger logger =
Logger.getLogger(AppServerServiceNameDetector.class.getName());

private final AppServer appServer;
private final ParseBuddy parseBuddy;
private final DirectoryTool dirTool;

AppServerServiceNameDetector(AppServer appServer) {
this(appServer, new ParseBuddy(appServer), new DirectoryTool());
}

// Exists for testing
AppServerServiceNameDetector(AppServer appServer, ParseBuddy parseBuddy, DirectoryTool dirTool) {
this.appServer = appServer;
this.parseBuddy = parseBuddy;
this.dirTool = dirTool;
}

@Override
@Nullable
public String detect() throws Exception {
if (appServer.getServerClass() == null) {
return null;
}

Path deploymentDir = appServer.getDeploymentDir();
if (deploymentDir == null) {
return null;
}

if (!dirTool.isDirectory(deploymentDir)) {
logger.log(FINE, "Deployment dir '{0}' doesn't exist.", deploymentDir);
return null;
}

logger.log(FINE, "Looking for deployments in '{0}'.", deploymentDir);
try (Stream<Path> stream = dirTool.list(deploymentDir)) {
return stream.map(this::detectName).filter(Objects::nonNull).findFirst().orElse(null);
}
}

@Nullable
private String detectName(Path path) {
if (!appServer.isValidAppName(path)) {
logger.log(FINE, "Skipping '{0}'.", path);
return null;
}

logger.log(FINE, "Attempting service name detection in '{0}'.", path);
String name = path.getFileName().toString();
if (dirTool.isDirectory(path)) {
return parseBuddy.handleExplodedApp(path);
}
if (name.endsWith(".war")) {
return parseBuddy.handlePackagedWar(path);
}
if (appServer.supportsEar() && name.endsWith(".ear")) {
return parseBuddy.handlePackagedEar(path);
}

return null;
}

// Exists for testing
static class DirectoryTool {
boolean isDirectory(Path path) {
return Files.isDirectory(path);
}

@MustBeClosed
Stream<Path> list(Path path) throws IOException {
return Files.list(path);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@

package io.opentelemetry.resourceproviders;

import java.net.URL;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;

/**
* This class is just a factory that provides a ServiceNameDetector that knows how to find and parse
Expand All @@ -21,7 +23,30 @@ static ServiceNameDetector create() {
private CommonAppServersServiceNameDetector() {}

private static List<ServiceNameDetector> detectors() {
// TBD: This will contain common app server detector implementations
return Collections.emptyList();
ResourceLocator locator = new ResourceLocatorImpl();
// Additional implementations will be added to this list.
return Collections.singletonList(detectorFor(new GlassfishAppServer(locator)));
}

private static AppServerServiceNameDetector detectorFor(AppServer appServer) {
return new AppServerServiceNameDetector(appServer);
}

private static class ResourceLocatorImpl implements ResourceLocator {

@Override
@Nullable
public Class<?> findClass(String className) {
try {
return Class.forName(className, false, ClassLoader.getSystemClassLoader());
} catch (ClassNotFoundException | LinkageError exception) {
return null;
}
}

@Override
public URL getClassLocation(Class<?> clazz) {
return clazz.getProtectionDomain().getCodeSource().getLocation();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.resourceproviders;

import java.nio.file.Path;
import java.nio.file.Paths;
import javax.annotation.Nullable;

class GlassfishAppServer implements AppServer {

private static final String SERVICE_CLASS_NAME = "com.sun.enterprise.glassfish.bootstrap.ASMain";
private final ResourceLocator locator;

GlassfishAppServer(ResourceLocator locator) {
this.locator = locator;
}

@Nullable
@Override
public Path getDeploymentDir() {
String instanceRoot = System.getProperty("com.sun.aas.instanceRoot");
if (instanceRoot == null) {
return null;
}

// besides autodeploy directory it is possible to deploy applications through admin console and
// asadmin script, to detect those we would need to parse config/domain.xml
return Paths.get(instanceRoot, "autodeploy");
}

@Override
@Nullable
public Class<?> getServerClass() {
return locator.findClass(SERVICE_CLASS_NAME);
}
}
Loading