fish.payara.micro.impl.PayaraMicroImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-client Show documentation
Show all versions of payara-client Show documentation
Appclient for Payara Server
The newest version!
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) [2016-2023] Payara Foundation and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://github.com/payara/Payara/blob/main/LICENSE.txt
* See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* The Payara Foundation designates this particular file as subject to the "Classpath"
* exception as provided by the Payara Foundation in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package fish.payara.micro.impl;
import com.sun.enterprise.util.JDK;
import com.sun.enterprise.util.PropertyPlaceholderHelper;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import com.sun.appserv.server.util.Version;
import com.sun.common.util.logging.SortedLoggingProperties;
import com.sun.enterprise.glassfish.bootstrap.Constants;
import com.sun.enterprise.glassfish.bootstrap.GlassFishImpl;
import com.sun.enterprise.server.logging.ODLLogFormatter;
import fish.payara.deployment.util.JavaArchiveUtils;
import fish.payara.deployment.util.URIUtils;
import org.glassfish.embeddable.BootstrapProperties;
import org.glassfish.embeddable.CommandRunner;
import org.glassfish.embeddable.Deployer;
import org.glassfish.embeddable.GlassFish;
import org.glassfish.embeddable.GlassFish.Status;
import org.glassfish.embeddable.GlassFishException;
import org.glassfish.embeddable.GlassFishProperties;
import org.glassfish.embeddable.GlassFishRuntime;
import fish.payara.appserver.rest.endpoints.config.admin.ListRestEndpointsCommand;
import fish.payara.boot.runtime.BootCommand;
import fish.payara.boot.runtime.BootCommands;
import fish.payara.deployment.util.GAVConvertor;
import fish.payara.micro.BootstrapException;
import fish.payara.micro.PayaraMicroRuntime;
import fish.payara.micro.boot.AdminCommandRunner;
import fish.payara.micro.boot.PayaraMicroBoot;
import fish.payara.micro.boot.PayaraMicroLauncher;
import fish.payara.micro.boot.loader.OpenURLClassLoader;
import fish.payara.micro.cmd.options.RUNTIME_OPTION;
import fish.payara.micro.cmd.options.RuntimeOptions;
import fish.payara.micro.cmd.options.ValidationException;
import fish.payara.micro.data.InstanceDescriptor;
import fish.payara.nucleus.executorservice.PayaraFileWatcher;
/**
* Main class for Bootstrapping Payara Micro Edition This class is used from
* applications to create a full JavaEE runtime environment and deploy war
* files.
*
* This class is used to configure and bootstrap a Payara Micro Runtime.
*
* @author steve
*/
public class PayaraMicroImpl implements PayaraMicroBoot {
private static final Logger LOGGER = Logger.getLogger("PayaraMicro");
private static final String BOOT_PROPS_FILE = "/MICRO-INF/payara-boot.properties";
private static final String USER_PROPS_FILE = "MICRO-INF/deploy/payaramicro.properties";
private static final String CONTEXT_PROPS_FILE = "MICRO-INF/deploy/contexts.properties";
private static PayaraMicroImpl instance;
private String hzMulticastGroup;
private int hzPort = Integer.MIN_VALUE;
private int hzStartPort = Integer.MIN_VALUE;
private String hzClusterName;
private int httpPort = Integer.MIN_VALUE;
private int sslPort = Integer.MIN_VALUE;
private int maxHttpThreads = Integer.MIN_VALUE;
private int minHttpThreads = Integer.MIN_VALUE;
private String instanceName;
private String contextRoot;
private File rootDir;
private File deploymentRoot;
private File alternateDomainXML;
private File alternateHZConfigFile;
private List> deploymentOptions;
private Map deployments;
private Properties contextRoots;
private List libraries;
private GlassFish gf;
private PayaraMicroRuntimeImpl runtime;
private boolean noCluster = false;
private boolean noHazelcast = false;
private boolean hostAware = true;
private boolean autoBindHttp = false;
private boolean autoBindSsl = false;
private boolean liteMember = false;
private boolean generateLogo = false;
private boolean logToFile = false;
private boolean enableAccessLog = false;
private boolean enableAccessLogFormat = false;
private boolean logPropertiesFile = false;
private boolean enableDynamicLogging;
private String userLogPropertiesFile = "";
private int autoBindRange = 50;
private String bootImage = "MICRO-INF/domain/boot.txt";
private String applicationDomainXml;
private boolean enableHealthCheck = false;
private boolean disablePhoneHome = false;
private File uberJar;
private boolean outputLauncher;
private File copyDirectory;
private Properties userSystemProperties;
private final List repositoryURIs;
private final short defaultHttpPort = 8080;
private final short defaultHttpsPort = 8181;
private final BootCommands preBootCommands;
private final BootCommands postBootCommands;
private final BootCommands postDeployCommands;
private Consumer preBootHandler;
private Consumer postBootHandler;
private String userLogFile = "payara-server%u.log";
private String userAccessLogDirectory = "";
private String accessLogFormat = "%client.name% %auth-user-name% %datetime% %request% %status% %response.length%";
private int accessLogInterval = 300;
private String accessLogSuffix = "yyyy-MM-dd";
private String accessLogPrefix;
private boolean enableRequestTracing = false;
private String requestTracingThresholdUnit = "SECONDS";
private long requestTracingThresholdValue = 30;
private boolean enableRequestTracingAdaptiveSampling = false;
private int requestTracingAdaptiveSamplingTargetCount = 12;
private int requestTracingAdaptiveSamplingTimeValue = 1;
private String requestTracingAdaptiveSamplingTimeUnit = "MINUTES";
private String instanceGroup;
private String preBootFileName;
private String postBootFileName;
private String postDeployFileName;
private RuntimeDirectory runtimeDir = null;
private String clustermode;
private String interfaces;
private String secretsDir;
private String sslCert;
private boolean showServletMappings;
private boolean sniEnabled = false;
private String publicAddress = "";
private int initialJoinWait = 1;
private boolean warmup;
private boolean hotDeploy;
/**
* Runs a Payara Micro server used via java -jar payara-micro.jar
*
* @param args Command line arguments for PayaraMicro Usage: --help to see
* all the options
*
* --help Shows this message and exits\n
* @throws BootstrapException If there is a problem booting the server
*/
public static void main(String[] args) throws Exception {
create(args);
}
public static PayaraMicroBoot create(String[] args) throws Exception {
// configure boot system properties
setBootProperties();
PayaraMicroImpl main = getInstance();
main.scanArgs(args);
if (main.getUberJar() != null) {
main.packageUberJar();
} else if (main.outputLauncher) {
main.createLauncher();
} else {
main.bootStrap();
if (main.warmup) {
main.shutdown();
}
}
return main;
}
/**
* Obtains the static singleton instance of the Payara Micro Server. If it
* does not exist it will be create.
*
* @return The singleton instance
*/
public static PayaraMicroImpl getInstance() {
return getInstance(true);
}
/**
* Bootstraps the PayaraMicroRuntime with all defaults and no additional
* configuration. Functionally equivalent to
* PayaraMicro.getInstance().bootstrap();
*
* @return
*/
public static PayaraMicroRuntime bootstrap() throws BootstrapException {
return getInstance().bootStrap();
}
/**
*
* @param create If false the instance won't be created if it has not been
* initialised
* @return null if no instance exists and create is false. Otherwise returns
* the singleton instance
*/
public static PayaraMicroImpl getInstance(boolean create) {
if (instance == null && create) {
instance = new PayaraMicroImpl();
PayaraMicroLauncher.registerLaunchedInstance(instance);
}
return instance;
}
/**
* Gets the cluster group
*
* @return The Multicast Group that will beused for the Hazelcast clustering
*/
@Override
public String getClusterMulticastGroup() {
return hzMulticastGroup;
}
/**
* Sets the cluster group used for Payara Micro clustering used for cluster
* communications and discovery. Each Payara Micro cluster should have
* different values for the MulticastGroup
*
* @param hzMulticastGroup String representation of the multicast group
* @return
*/
@Override
public PayaraMicroImpl setClusterMulticastGroup(String hzMulticastGroup) {
//if (runtime != null) {
checkNotRunning();
this.hzMulticastGroup = hzMulticastGroup;
return this;
}
/**
* Sets the path to the logo file printed at boot. This can be on the
* classpath of the server or an absolute URL
*
* @param filePath
* @return
*/
@Override
public PayaraMicroImpl setLogoFile(String filePath) {
bootImage = filePath;
return this;
}
/**
* Set whether the logo should be generated on boot
*
* @param generate
* @return
*/
@Override
public PayaraMicroImpl setPrintLogo(boolean generate) {
generateLogo = generate;
return this;
}
/**
* Set user defined file for the Log entries
*
* @param fileName
* @return
*/
@Override
public PayaraMicroImpl setUserLogFile(String fileName) {
File file = new File(fileName);
if (file.isDirectory()) {
if (!file.exists() || !file.canWrite()) {
LOGGER.log(Level.SEVERE, "{0} is not a valid directory for storing logs as it must exist and be writable", file.getAbsolutePath());
throw new IllegalArgumentException();
}
this.userLogFile = file.getAbsolutePath() + File.separator + userLogFile;
} else {
userLogFile = fileName;
}
logToFile = true;
return this;
}
/**
* Set user defined properties file for logging
*
* @param fileName
* @return
*/
@Override
public PayaraMicroImpl setLogPropertiesFile(File fileName) {
System.setProperty("java.util.logging.config.file", fileName.getAbsolutePath());
logPropertiesFile = true;
userLogPropertiesFile = fileName.getAbsolutePath();
return this;
}
/**
* Set user defined file directory for the access log
*
* @param filePath
* @return
*/
@Override
public PayaraMicroBoot setAccessLogDir(String filePath) {
this.userAccessLogDirectory = filePath;
enableAccessLog = true;
return this;
}
/**
* Set user defined formatting for the access log
*
* @param format
* @return
*/
@Override
public PayaraMicroBoot setAccessLogFormat(String format) {
this.accessLogFormat = format;
this.enableAccessLogFormat = true;
return this;
}
/**
* Set user defined interval for the access log
*
* @param interval
* @return
*/
public PayaraMicroBoot setAccessLogInterval(int interval) {
this.accessLogInterval = interval;
return this;
}
/**
* Gets the cluster multicast port used for cluster communications
*
* @return The configured cluster port
*/
@Override
public int getClusterPort() {
return hzPort;
}
/**
* Sets the multicast group used for Payara Micro clustering used for
* cluster communication and discovery. Each Payara Micro cluster should
* have different values for the cluster port
*
* @param hzPort The port number
* @return
*/
@Override
public PayaraMicroImpl setClusterPort(int hzPort) {
//if (runtime != null) {
checkNotRunning();
this.hzPort = hzPort;
return this;
}
/**
* Gets the instance listen port number used by clustering. This number will
* be incremented automatically if the port is unavailable due to another
* instance running on the same host,
*
* @return The start port number
*/
@Override
public int getClusterStartPort() {
return hzStartPort;
}
/**
* Sets the start port number for the Payara Micro to listen on for cluster
* communications.
*
* @param hzStartPort Start port number
* @return
*/
@Override
public PayaraMicroImpl setClusterStartPort(int hzStartPort) {
//if (runtime != null) {
checkNotRunning();
this.hzStartPort = hzStartPort;
return this;
}
/**
* The configured port Payara Micro will use for HTTP requests.
*
* @return The HTTP port
*/
@Override
public int getHttpPort() {
return httpPort;
}
/**
* Sets the port used for HTTP requests
*
* @param httpPort The port number
* @return
*/
@Override
public PayaraMicroImpl setHttpPort(int httpPort) {
//if (runtime != null) {
checkNotRunning();
this.httpPort = httpPort;
return this;
}
/**
* The UberJar to create
*
* @return
*/
@Override
public File getUberJar() {
return uberJar;
}
/**
* The configured port for HTTPS requests
*
* @return The HTTPS port
*/
@Override
public int getSslPort() {
return sslPort;
}
/**
* Sets the configured port for HTTPS requests. If this is not set HTTPS is
* disabled
*
* @param sslPort The HTTPS port
* @return
*/
@Override
public PayaraMicroImpl setSslPort(int sslPort) {
//if (runtime != null) {
checkNotRunning();
this.sslPort = sslPort;
return this;
}
@Override
public PayaraMicroImpl setSniEnabled(boolean value) {
sniEnabled = value;
return this;
}
/**
* Set the certificate alias in the keystore to use for the server cert
*
* @param alias name of the certificate in the keystore
* @return
*/
@Override
public PayaraMicroImpl setSslCert(String alias) {
sslCert = alias;
return this;
}
@Override
public String getSslCert() {
return sslCert;
}
/**
* Gets the logical name for this PayaraMicro Server within the server
* cluster
*
* @return The configured instance name
*/
@Override
public String getInstanceName() {
return instanceName;
}
/**
* Sets the logical instance name for this PayaraMicro server within the
* server cluster If this is not set a name is generated
*
* @param instanceName The logical server name
* @return
*/
@Override
public PayaraMicroImpl setInstanceName(String instanceName) {
//if (runtime != null) {
checkNotRunning();
this.instanceName = instanceName;
return this;
}
/**
* A directory which will be scanned for archives to deploy
*
* @return
*/
@Override
public File getDeploymentDir() {
return deploymentRoot;
}
/**
* Sets a directory to scan for archives to deploy on boot. This directory
* is not monitored while running for changes. Therefore archives in this
* directory will NOT be redeployed during runtime.
*
* @param deploymentRoot File path to the directory
* @return
*/
@Override
public PayaraMicroImpl setDeploymentDir(File deploymentRoot) {
//if (runtime != null) {
checkNotRunning();
validateRuntimeOption(RUNTIME_OPTION.deploydir, deploymentRoot.getPath());
if (this.deploymentRoot == null) {
if (deploymentOptions == null) {
deploymentOptions = new LinkedList<>();
}
// Map entry value are unused because we use deploymentRoot property
deploymentOptions.add(new AbstractMap.SimpleImmutableEntry<>(RUNTIME_OPTION.deploydir, null));
} else {
LOGGER.warning("Multiple deploy dirs only last one will be apply");
}
this.deploymentRoot = deploymentRoot;
return this;
}
/**
* The path to an alternative domain.xml for PayaraMicro to use at boot
*
* @return The path to the domain.xml
*/
@Override
public File getAlternateDomainXML() {
return alternateDomainXML;
}
/**
* Sets an application specific domain.xml file that is embedded on the
* classpath of your application.
*
* @param domainXml This is a resource string for your domain.xml
* @return
*/
@Override
public PayaraMicroImpl setApplicationDomainXML(String domainXml) {
applicationDomainXml = domainXml;
return this;
}
/**
* Sets the path to a domain.xml file PayaraMicro should use to boot. If
* this is not set PayaraMicro will use an appropriate domain.xml from
* within its jar file
*
* @param alternateDomainXML
* @return
*/
@Override
public PayaraMicroImpl setAlternateDomainXML(File alternateDomainXML) {
//if (runtime != null) {
checkNotRunning();
this.alternateDomainXML = alternateDomainXML;
return this;
}
private void checkNotRunning() {
if (isRunning()) {
throw new IllegalStateException("Payara Micro is already running, setting attributes has no effect");
}
}
/**
* Adds an archive to the list of archives to be deployed at boot. These
* archives are not monitored for changes during running so are not
* redeployed without restarting the server
*
* @param pathToWar File path to the deployment archive
* @return
*/
@Override
public PayaraMicroImpl addDeployment(String pathToWar) {
//if (runtime != null) {
checkNotRunning();
validateRuntimeOption(RUNTIME_OPTION.deploy, pathToWar);
if (deploymentOptions == null) {
deploymentOptions = new LinkedList<>();
}
deploymentOptions.add(new AbstractMap.SimpleImmutableEntry<>(RUNTIME_OPTION.deploy, pathToWar));
return this;
}
/**
* Adds an archive to the list of archives to be deployed at boot. These
* archives are not monitored for changes during running so are not
* redeployed without restarting the server
*
* @param file File path to the deployment archive
* @return
*/
@Override
public PayaraMicroImpl addDeploymentFile(File file) {
//if (runtime != null) {
checkNotRunning();
return addDeployment(file.getPath());
}
/**
* Adds a Maven GAV coordinate to the list of archives to be deployed at
* boot.
*
* @param GAV GAV coordinate
* @return
*/
@Override
public PayaraMicroImpl addDeployFromGAV(String GAV) {
//if (runtime != null) {
checkNotRunning();
validateRuntimeOption(RUNTIME_OPTION.deployfromgav, GAV);
if (deploymentOptions == null) {
deploymentOptions = new LinkedList<>();
}
deploymentOptions.add(new AbstractMap.SimpleImmutableEntry<>(RUNTIME_OPTION.deployfromgav, GAV));
return this;
}
private void validateRuntimeOption(RUNTIME_OPTION option, String optionValue) {
try {
option.validate(optionValue);
} catch (ValidationException ex) {
LOGGER.log(Level.SEVERE, ex.getMessage());
System.exit(-1);
}
}
/**
* Adds a Maven repository to the list of repositories to search for
* artifacts in
*
* @param URLs URL to Maven repository
* @return
*/
@Override
public PayaraMicroImpl addRepoUrl(String... URLs) {
//if (runtime != null) {
checkNotRunning();
repositoryURIs.addAll(Arrays.asList(URLs));
return this;
}
/**
* Indicated whether clustering is enabled
*
* @return
*/
@Override
public boolean isNoCluster() {
return noCluster;
}
/**
* Indicated whether distributed data grid is enabled
*
* @return
*/
@Override
public boolean isNoHazelcast() {
return noHazelcast;
}
/**
* Enables or disables clustering before bootstrap
*
* @param noCluster set to true to disable clustering
* @return
*/
@Override
public PayaraMicroImpl setNoCluster(boolean noCluster) {
//if (runtime != null) {
checkNotRunning();
this.noCluster = noCluster;
return this;
}
/**
* Enables or disables clustering before bootstrap
*
* @param noHazelcast set to true to disable clustering
* @return
*/
@Override
public PayaraMicroImpl setNoHazelcast(boolean noHazelcast) {
checkNotRunning();
this.noHazelcast = noHazelcast;
return this;
}
/**
* Indicates whether this is a lite cluster member which means it stores no
* cluster data although it participates fully in the cluster.
*
* @return
*/
@Override
public boolean isLite() {
return liteMember;
}
/**
* Sets the lite status of this cluster member. If true the Payara Micro is
* a lite cluster member which means it stores no cluster data.
*
* @param liteMember set to true to set as a lite cluster member with no
* data storage
* @return
*/
@Override
public PayaraMicroImpl setLite(boolean liteMember) {
//if (runtime != null) {
checkNotRunning();
this.liteMember = liteMember;
return this;
}
/**
* The maximum threads in the HTTP(S) threadpool processing HTTP(S)
* requests. Setting this will determine how many concurrent HTTP requests
* can be processed. The default value is 200. This value is shared by both
* HTTP and HTTP(S) requests.
*
* @return
*/
@Override
public int getMaxHttpThreads() {
return maxHttpThreads;
}
/**
* The maximum threads in the HTTP(S) threadpool processing HTTP(S)
* requests. Setting this will determine how many concurrent HTTP requests
* can be processed. The default value is 200
*
* @param maxHttpThreads Maximum threads in the HTTP(S) threadpool
* @return
*/
@Override
public PayaraMicroImpl setMaxHttpThreads(int maxHttpThreads) {
//if (runtime != null) {
checkNotRunning();
this.maxHttpThreads = maxHttpThreads;
return this;
}
/**
* The minimum number of threads in the HTTP(S) threadpool Default value is
* 10
*
* @return The minimum threads to be created in the threadpool
*/
@Override
public int getMinHttpThreads() {
return minHttpThreads;
}
/**
* The minimum number of threads in the HTTP(S) threadpool Default value is
* 10
*
* @param minHttpThreads
* @return
*/
@Override
public PayaraMicroImpl setMinHttpThreads(int minHttpThreads) {
//if (runtime != null) {
checkNotRunning();
this.minHttpThreads = minHttpThreads;
return this;
}
/**
* The File path to a directory that PayaraMicro should use for storing its
* configuration files
*
* @return
*/
@Override
public File getRootDir() {
return rootDir;
}
/**
* Sets the File path to a directory PayaraMicro should use to install its
* configuration files. If this is set the PayaraMicro configuration files
* will be stored in the directory and persist across server restarts. If
* this is not set the configuration files are created in a temporary
* location and not persisted across server restarts.
*
* @param rootDir Path to a valid directory
* @return Returns the PayaraMicro instance
*/
@Override
public PayaraMicroImpl setRootDir(File rootDir) {
//if (runtime != null) {
checkNotRunning();
this.rootDir = rootDir;
return this;
}
/**
* Indicates whether autobinding of the HTTP port is enabled
*
* @return
*/
@Override
public boolean getHttpAutoBind() {
return autoBindHttp;
}
/**
* Enables or disables autobinding of the HTTP port
*
* @param httpAutoBind The true or false value to enable or disable HTTP
* autobinding
* @return
*/
@Override
public PayaraMicroImpl setHttpAutoBind(boolean httpAutoBind) {
this.autoBindHttp = httpAutoBind;
return this;
}
/**
* Indicates whether autobinding of the HTTPS port is enabled
*
* @return
*/
@Override
public boolean getSslAutoBind() {
return autoBindSsl;
}
/**
* Enables or disables autobinding of the HTTPS port
*
* @param sslAutoBind The true or false value to enable or disable HTTPS
* autobinding
* @return
*/
@Override
public PayaraMicroImpl setSslAutoBind(boolean sslAutoBind) {
this.autoBindSsl = sslAutoBind;
return this;
}
/**
* Gets the maximum number of ports to check if free for autobinding
* purposes
*
* @return The number of ports to check if free
*/
@Override
public int getAutoBindRange() {
return autoBindRange;
}
/**
* Sets the maximum number of ports to check if free for autobinding
* purposes
*
* @param autoBindRange The maximum number of ports to increment the port
* value by
* @return
*/
@Override
public PayaraMicroImpl setAutoBindRange(int autoBindRange) {
this.autoBindRange = autoBindRange;
return this;
}
/**
* Gets the name of the Hazelcast cluster group. Clusters with different
* names do not interact
*
* @return The current Cluster Name
*/
@Override
public String getHzClusterName() {
return hzClusterName;
}
/**
* Sets the name of the Hazelcast cluster group
*
* @param hzClusterName The name of the hazelcast cluster
* @return
*/
@Override
public PayaraMicroImpl setHzClusterName(String hzClusterName) {
this.hzClusterName = hzClusterName;
return this;
}
/**
* Gets the name of the instance group
*
* @return The name of the instance group
*/
@Override
public String getInstanceGroup() {
return instanceGroup;
}
/**
* Sets the instance group name
*
* @param instanceGroup The instance group name
* @return
*/
@Override
public PayaraMicroImpl setInstanceGroup(String instanceGroup) {
this.instanceGroup = instanceGroup;
return this;
}
/**
* Boots the Payara Micro Server. All parameters are checked at this point
*
* @return An instance of PayaraMicroRuntime that can be used to access the
* running server
* @throws BootstrapException
*/
@Override
public PayaraMicroRuntime bootStrap() throws BootstrapException {
// First check whether we are already running
if (isRunning()) {
throw new IllegalStateException("Payara Micro is already running, calling bootstrap now is meaningless");
}
long start = System.currentTimeMillis();
// Build the runtime directory
try {
unPackRuntime();
} catch (IOException | URISyntaxException ex) {
throw new BootstrapException("Problem unpacking the Runtime", ex);
}
final String loggingProperty = System.getProperty("java.util.logging.config.file");
resetLogging(loggingProperty);
// If it's been enabled, watch the log file for changes
if (enableDynamicLogging) {
PayaraFileWatcher.watch(new File(loggingProperty).toPath(), () -> {
LOGGER.info("Logging file modified, resetting logging");
resetLogging(loggingProperty);
});
}
//Check a supported JDK version is being used
if (!JDK.isRunningLTSJDK()) {
LOGGER.warning("You are running the product on an unsupported JDK version and might see unexpected results or exceptions.");
}
runtimeDir.processDirectoryInformation();
// build the runtime
BootstrapProperties bprops = new BootstrapProperties();
bprops.setInstallRoot(runtimeDir.getDirectory().getAbsolutePath());
bprops.setProperty(Constants.PLATFORM_PROPERTY_KEY, Constants.Platform.PayaraMicro.toString());
GlassFishRuntime gfruntime;
try {
gfruntime = GlassFishRuntime.bootstrap(bprops, Thread.currentThread().getContextClassLoader());
GlassFishProperties gfproperties = new GlassFishProperties();
gfproperties.setProperty("-type", "MICRO");
gfproperties.setInstanceRoot(runtimeDir.getDirectory().getAbsolutePath());
gfproperties.setConfigFileReadOnly(false);
gfproperties.setConfigFileURI(runtimeDir.getDomainXML().toURI().toString());
try {
parsePreBootCommandFiles();
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Unable to load command file", ex);
}
gf = gfruntime.newGlassFish(gfproperties);
configurePorts();
configureThreads();
configureAccessLogging();
configureHazelcast();
configurePhoneHome();
configureNotificationService();
configureHealthCheck();
configureRequestTracingService();
configureSecrets();
// Add additional libraries
addLibraries();
// boot the server
preBootCommands.executeCommands(gf.getCommandRunner());
callHandler(preBootHandler);
gf.start();
// Parse and execute post boot commands
try {
parsePostBootCommandFiles();
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Unable to load command file", ex);
}
postBootCommands.executeCommands(gf.getCommandRunner());
callHandler(postBootHandler);
this.runtime = new PayaraMicroRuntimeImpl(gf, gfruntime);
// deploy all applications and then initialize them
deployAll();
// These steps are separated in case any steps need to be done in between
gf.getCommandRunner().run("initialize-all-applications");
// Parse and execute post deploy commands
try {
parsePostDeployCommandFiles();
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Unable to load command file", ex);
}
postDeployCommands.executeCommands(gf.getCommandRunner());
long end = System.currentTimeMillis();
dumpFinalStatus(end - start);
return runtime;
} catch (Exception ex) {
try {
if (gf != null) {
gf.dispose();
}
} catch (GlassFishException ex1) {
LOGGER.log(Level.SEVERE, null, ex1);
}
throw new BootstrapException(ex.getMessage(), ex);
}
}
private void callHandler(Consumer handler) throws GlassFishException {
CommandRunner runner = gf.getCommandRunner();
if (handler != null) {
handler.accept((cmd, args) -> new CommandResultAdapter(runner.run(cmd, args)));
}
}
/**
* Get a handle on the running Payara instance to manipulate the server once
* running
*
* @return
* @throws IllegalStateException
*/
@Override
public PayaraMicroRuntimeImpl getRuntime() throws IllegalStateException {
if (!isRunning()) {
throw new IllegalStateException("Payara Micro is not running");
}
return runtime;
}
/**
* Stops and then shutsdown the Payara Micro Server
*
* @throws BootstrapException
*/
@Override
public void shutdown() throws BootstrapException {
if (!isRunning()) {
throw new IllegalStateException("Payara Micro is not running");
}
runtime.shutdown();
runtime = null;
}
private PayaraMicroImpl() {
// Initialise a random instance name
repositoryURIs = new LinkedList<>();
preBootCommands = new BootCommands();
postBootCommands = new BootCommands();
postDeployCommands = new BootCommands();
addShutdownHook();
}
private void scanArgs(String[] args) {
RuntimeOptions options = null;
try {
options = new RuntimeOptions(args);
} catch (ValidationException ex) {
LOGGER.log(Level.SEVERE, ex.getMessage());
System.exit(-1);
}
processUserProperties(options);
setArgumentsFromSystemProperties();
for (Map.Entry optionEntry : options.getOptions()) {
RUNTIME_OPTION option = optionEntry.getKey();
String value = optionEntry.getValue();
switch (option) {
case port: {
httpPort = Integer.parseInt(value);
break;
}
case sslport: {
sslPort = Integer.parseInt(value);
break;
}
case sslcert: {
sslCert = value;
break;
}
case version: {
printVersion();
System.exit(1);
break;
}
case maxhttpthreads: {
maxHttpThreads = Integer.parseInt(value);
break;
}
case minhttpthreads: {
minHttpThreads = Integer.parseInt(value);
break;
}
case mcaddress:
hzMulticastGroup = value;
break;
case clustername:
hzClusterName = value;
break;
case hostaware: {
hostAware = true;
break;
}
case nohostaware: {
hostAware = false;
break;
}
case mcport: {
hzPort = Integer.parseInt(value);
break;
}
case startport:
hzStartPort = Integer.parseInt(value);
break;
case name:
instanceName = value;
break;
case instancegroup:
case group:
instanceGroup = value;
break;
case deploymentdir:
case deploydir:
if (deploymentRoot == null) {
if (deploymentOptions == null) {
deploymentOptions = new LinkedList<>();
}
deploymentOptions.add(new AbstractMap.SimpleImmutableEntry<>(option, null));
} else {
LOGGER.warning("Multiple --deploydir arguments only the last one will apply");
}
deploymentRoot = new File(value);
break;
case rootdir:
rootDir = new File(value);
break;
case addlibs:
case addjars:
List files = UberJarCreator.parseFileList(value, File.pathSeparator);
if (!files.isEmpty()) {
if (libraries == null) {
libraries = new LinkedList<>();
}
libraries.addAll(files);
}
break;
case deploy:
case deployfromgav:
if (deploymentOptions == null) {
deploymentOptions = new LinkedList<>();
}
deploymentOptions.add(new AbstractMap.SimpleImmutableEntry<>(option, value));
break;
case domainconfig:
alternateDomainXML = new File(value);
break;
case nocluster:
noCluster = true;
break;
case nohazelcast:
noHazelcast = true;
break;
case lite:
liteMember = true;
break;
case hzconfigfile:
alternateHZConfigFile = new File(value);
break;
case autobindhttp:
autoBindHttp = true;
break;
case autobindssl:
autoBindSsl = true;
break;
case autobindrange:
autoBindRange = Integer.parseInt(value);
break;
case enablehealthcheck:
enableHealthCheck = Boolean.parseBoolean(value);
break;
case additionalrepository:
repositoryURIs.add(value);
break;
case outputuberjar:
uberJar = new File(value);
break;
case copytouberjar:
copyDirectory = new File(value);
break;
case outputlauncher:
outputLauncher = true;
break;
case warmup:
warmup = true;
break;
case hotdeploy:
hotDeploy = true;
break;
case disablephonehome:
disablePhoneHome = true;
break;
case enablerequesttracing:
enableRequestTracing = true;
// Check if a value has actually been given
// Split strings from numbers
if (value != null) {
String[] requestTracing = value.split("(?<=\\d)(?=\\D)|(?=\\d)(?<=\\D)");
// If valid, there should be no more than 2 entries
if (requestTracing.length <= 2) {
// If the first entry is a number
if (requestTracing[0].matches("\\d+")) {
requestTracingThresholdValue = parseArgument(requestTracing[0],
"request tracing threshold value", Long::parseLong);
// If there is a second entry, and it's a String
if (requestTracing.length == 2 && requestTracing[1].matches("\\D+")) {
requestTracingThresholdUnit = parseTimeUnit(requestTracing[1],
"request tracing threshold unit").name();
}
} // If the first entry is a String
else if (requestTracing[0].matches("\\D+")) {
requestTracingThresholdUnit = parseTimeUnit(requestTracing[0],
"request tracing threshold unit").name();
}
} else {
throw new IllegalArgumentException();
}
}
break;
case requesttracingthresholdunit:
requestTracingThresholdUnit = parseTimeUnit(value, "value for --requestTracingThresholdUnit").name();
break;
case requesttracingthresholdvalue:
requestTracingThresholdValue = parseArgument(value, "value for --requestTracingThresholdValue",
Long::parseLong);
break;
case enablerequesttracingadaptivesampling:
enableRequestTracingAdaptiveSampling = true;
break;
case requesttracingadaptivesamplingtargetcount:
enableRequestTracingAdaptiveSampling = true;
requestTracingAdaptiveSamplingTargetCount = parseArgument(value,
"value for --requestTracingAdaptiveSamplingTargetCount", Integer::parseInt);
break;
case requesttracingadaptivesamplingtimevalue:
enableRequestTracingAdaptiveSampling = true;
requestTracingAdaptiveSamplingTimeValue = parseArgument(value,
"value for --requestTracingAdaptiveSamplingTimeValue", Integer::parseInt);
break;
case requesttracingadaptivesamplingtimeunit:
enableRequestTracingAdaptiveSampling = true;
requestTracingAdaptiveSamplingTimeUnit = parseTimeUnit(value,
"value for --requestTracingAdaptiveSamplingTimeUnit").name();
break;
case help:
RuntimeOptions.printHelp();
System.exit(1);
break;
case logtofile:
setUserLogFile(value);
break;
case accesslog:
File file = new File(value);
setAccessLogDir(file.getAbsolutePath());
break;
case accesslogformat:
setAccessLogFormat(value);
break;
case logproperties:
setLogPropertiesFile(new File(value));
break;
case enabledynamiclogging:
enableDynamicLogging = true;
break;
case logo:
generateLogo = true;
break;
case postbootcommandfile:
postBootFileName = value;
break;
case prebootcommandfile:
preBootFileName = value;
break;
case postdeploycommandfile:
postDeployFileName = value;
break;
case clustermode:
clustermode = value;
break;
case interfaces:
interfaces = value;
break;
case secretsdir:
secretsDir = value;
break;
case showservletmappings:
showServletMappings = true;
break;
case enablesni:
sniEnabled = true;
break;
case hzpublicaddress:
publicAddress = value;
break;
case shutdowngrace:
System.setProperty(GlassFishImpl.PAYARA_SHUTDOWNGRACE_PROPERTY, value);
break;
case hzinitialjoinwait:
initialJoinWait = Integer.parseInt(value);
break;
case contextroot:
if (contextRoot != null) {
LOGGER.warning("Multiple --contextroot arguments only the last one will apply");
}
contextRoot = value;
if (isRoot(contextRoot)) {
contextRoot = "/";
}
break;
case accessloginterval:
accessLogInterval = Integer.parseInt(value);
break;
case accesslogsuffix:
accessLogSuffix = value;
break;
case accesslogprefix:
accessLogPrefix = value;
break;
default:
break;
}
}
}
private boolean isRoot(String context) {
return "ROOT".equals(context);
}
private void configureRequestTracingService() {
if (enableRequestTracing) {
preBootCommands.add(new BootCommand("set",
"configs.config.server-config.request-tracing-service-configuration.enabled=true"));
preBootCommands.add(new BootCommand("set",
"configs.config.server-config.request-tracing-service-configuration.threshold-unit="
+ requestTracingThresholdUnit));
preBootCommands.add(new BootCommand("set",
"configs.config.server-config.request-tracing-service-configuration.threshold-value" + "="
+ Long.toString(requestTracingThresholdValue)));
if (enableRequestTracingAdaptiveSampling) {
preBootCommands.add(new BootCommand("set",
"configs.config.server-config.request-tracing-service-configuration.adaptive-sampling-enabled="
+ Boolean.toString(enableRequestTracingAdaptiveSampling)));
preBootCommands.add(new BootCommand("set",
"configs.config.server-config.request-tracing-service-configuration.adaptive-sampling-target-count="
+ Integer.toString(requestTracingAdaptiveSamplingTargetCount)));
preBootCommands.add(new BootCommand("set",
"configs.config.server-config.request-tracing-service-configuration.adaptive-sampling-time-value="
+ Integer.toString(requestTracingAdaptiveSamplingTimeValue)));
preBootCommands.add(new BootCommand("set",
"configs.config.server-config.request-tracing-service-configuration.adaptive-sampling-time-unit="
+ requestTracingAdaptiveSamplingTimeUnit));
}
}
}
/**
* Process the user system properties in precedence 1st loads the properties
* from the uber jar location then loads each command line system properties
* file which will override uber jar properties
*
* @param options
* @throws IllegalArgumentException
*/
private void processUserProperties(RuntimeOptions options) throws IllegalArgumentException {
userSystemProperties = new Properties();
// load all from the uber jar first
try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(USER_PROPS_FILE)) {
if (is != null) {
Properties props = new Properties();
props.load(is);
for (Map.Entry, ?> entry : props.entrySet()) {
userSystemProperties.setProperty((String) entry.getKey(), (String) entry.getValue());
}
}
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "", ex);
}
// process each command line system properties option
List propertiesoption = options.getOption(RUNTIME_OPTION.systemproperties);
if (propertiesoption != null && !propertiesoption.isEmpty()) {
// process the system properties
for (String string : propertiesoption) {
File propertiesFile = new File(string);
Properties tempProperties = new Properties();
try (FileReader reader = new FileReader(propertiesFile)) {
tempProperties.load(reader);
Enumeration names = (Enumeration) tempProperties.propertyNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
userSystemProperties.setProperty(name, tempProperties.getProperty(name));
}
} catch (IOException e) {
LOGGER.log(Level.SEVERE,
"{0} is not a valid properties file",
propertiesFile.getAbsolutePath());
throw new IllegalArgumentException(e);
}
}
}
// now set them
for (String stringPropertyName : userSystemProperties.stringPropertyNames()) {
System.setProperty(stringPropertyName, userSystemProperties.getProperty(stringPropertyName));
}
}
private void processDeploymentOptions() throws GlassFishException {
if (deploymentOptions == null) {
return;
}
if (deployments == null) {
deployments = new LinkedHashMap<>();
}
boolean contextRootAvailable = contextRoot != null;
for (Map.Entry deploymentOption : deploymentOptions) {
RUNTIME_OPTION option = deploymentOption.getKey();
String value = deploymentOption.getValue();
if (option == RUNTIME_OPTION.deploy) {
String fileName = value;
String deploymentContext = null;
if (fileName.contains(File.pathSeparator)) {
fileName = fileName.substring(0, fileName.indexOf(File.pathSeparator));
deploymentContext = value.substring(value.indexOf(File.pathSeparator) + 1);
}
File deployment = new File(fileName);
deployments.put(deployment.getName(), deployment.toURI());
if (JavaArchiveUtils.hasContextRoot(deployment)) {
if (deploymentContext != null) {
addDeploymentContext(deployment.getName(), deploymentContext);
} else {
contextRootAvailable = false;
}
}
} else if (option == RUNTIME_OPTION.deploydir || option == RUNTIME_OPTION.deploymentdir) {
// Get all files in the directory, and sort them by file type
File[] deploymentEntries = deploymentRoot.listFiles(file -> JavaArchiveUtils.hasJavaArchiveExtension(file.getName(), false));
Arrays.sort(deploymentEntries, new DeploymentComparator());
for (File deploymentEntry : deploymentEntries) {
if (deploymentEntry.isFile() && deploymentEntry.canRead()) {
deployments.put(deploymentEntry.getName(), deploymentEntry.toURI());
if (JavaArchiveUtils.hasContextRoot(deploymentEntry)) {
contextRootAvailable = false;
}
}
}
} else if (option == RUNTIME_OPTION.deployfromgav) {
Map.Entry gavEntry = getGAVURI(value);
URI artifactURI = gavEntry.getValue();
String artifactName = new File(artifactURI.getPath()).getName();
deployments.put(artifactName, artifactURI);
if (JavaArchiveUtils.hasWebArchiveExtension(artifactName)) {
String deploymentContext = gavEntry.getKey();
if (contextRootAvailable) {
deploymentContext = contextRoot;
contextRoot = null; // use only once
contextRootAvailable = false;
}
addDeploymentContext(artifactName, deploymentContext);
}
}
}
}
private void addDeploymentContext(String fileName, String deploymentContext) {
if (contextRoots == null) {
contextRoots = new Properties();
}
if (isRoot(deploymentContext)) {
deploymentContext = "/";
}
contextRoots.put(fileName, deploymentContext);
}
private void deployAll() throws GlassFishException {
// Deploy from within the jar first.
int deploymentCount = 0;
Deployer deployer = gf.getDeployer();
// load context roots from uber jar
try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(CONTEXT_PROPS_FILE)) {
if (is != null) {
Properties props = new Properties();
props.load(is);
for (Map.Entry, ?> entry : props.entrySet()) {
if (contextRoots == null) {
contextRoots = new Properties();
}
contextRoots.setProperty((String) entry.getKey(), (String) entry.getValue());
}
}
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "", ex);
}
// search and deploy from MICRO-INF/deploy directory.
// if there is a deployment called ROOT deploy to the root context /
URL url = this.getClass().getClassLoader().getResource("MICRO-INF/deploy");
if (url != null) {
String entryName = "";
try {
List microInfEntries = new LinkedList<>();
JarURLConnection urlcon = (JarURLConnection) url.openConnection();
JarFile jFile = urlcon.getJarFile();
Enumeration entries = jFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
entryName = entry.getName();
if (!entry.isDirectory() && !entryName.endsWith(".properties") && !entryName.endsWith(".xml") && !entryName.endsWith(".gitkeep") && entryName.startsWith("MICRO-INF/deploy")) {
microInfEntries.add(entryName);
}
}
for (String entry : microInfEntries) {
File deployment = new File(entry);
String deploymentName = JavaArchiveUtils.removeJavaArchiveExtension(deployment.getName(), false);
List deploymentParams = new ArrayList<>();
deploymentParams.add("--availabilityenabled=true");
deploymentParams.add("--force=true");
deploymentParams.add("--loadOnly=true");
deploymentParams.add("--name=" + deploymentName);
if (hotDeploy) {
deploymentParams.add("--hotDeploy=true");
}
if (JavaArchiveUtils.hasWebArchiveExtension(deployment.getName())) {
String deploymentContext;
if (isRoot(deploymentName)) {
deploymentContext = "/";
} else if (contextRoots != null && contextRoots.containsKey(deployment.getName())) {
deploymentContext = contextRoots.getProperty(deployment.getName());
} else {
deploymentContext = deploymentName;
}
if (isRoot(deploymentContext)) {
deploymentContext = "/";
}
deploymentParams.add("--contextroot=" + deploymentContext);
}
deployer.deploy(this.getClass().getClassLoader().getResourceAsStream(entry), deploymentParams.toArray(new String[0]));
deploymentCount++;
}
} catch (IOException ioe) {
LOGGER.log(Level.WARNING, "Could not deploy jar entry {0}", entryName);
}
} else {
LOGGER.info("No META-INF/deploy directory");
}
processDeploymentOptions();
if (deployments != null) {
for (Map.Entry deploymentEntry : deployments.entrySet()) {
String fileName = deploymentEntry.getKey();
URI deploymentURI = deploymentEntry.getValue();
List deploymentParams = new ArrayList<>();
deploymentParams.add("--availabilityenabled=true");
deploymentParams.add("--force=true");
deploymentParams.add("--loadOnly=true");
if (hotDeploy) {
deploymentParams.add("--hotDeploy=true");
}
String deploymentContext = null;
if (URIUtils.hasFileScheme(deploymentURI)) {
File deployment = new File(deploymentURI);
if (JavaArchiveUtils.hasContextRoot(deployment)) {
String deploymentName = deployment.isFile() ? JavaArchiveUtils.removeJavaArchiveExtension(fileName, false) : fileName;
if (isRoot(deploymentName)) {
deploymentContext = "/";
} else if (contextRoots != null && contextRoots.containsKey(fileName)) {
deploymentContext = contextRoots.getProperty(fileName);
} else if (contextRoot != null) {
deploymentContext = contextRoot;
contextRoot = null; // use only once
} else if (deployment.isDirectory()) {
deploymentContext = fileName;
}
}
} else {
deploymentParams.add("--name=" + JavaArchiveUtils.removeJavaArchiveExtension(fileName, false));
if (JavaArchiveUtils.hasWebArchiveExtension(fileName)) {
if (contextRoot != null) {
deploymentContext = contextRoot;
contextRoot = null;
} else {
deploymentContext = contextRoots.getProperty(fileName);
}
}
}
if (deploymentContext != null) {
if (isRoot(deploymentContext)) {
deploymentContext = "/";
}
deploymentParams.add("--contextroot=" + deploymentContext);
}
deployer.deploy(deploymentURI, deploymentParams.toArray(new String[0]));
deploymentCount++;
}
}
LOGGER.log(Level.INFO, "Deployed {0} archive(s)", deploymentCount);
}
private void addShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(
"GlassFish Shutdown Hook") {
@Override
public void run() {
try {
if (gf != null) {
gf.stop();
gf.dispose();
}
} catch (GlassFishException ex) {
} catch (IllegalStateException ex) {
// Just log at a fine level and move on
LOGGER.log(Level.FINE, "Already shut down");
}
}
});
}
/**
* Reset the logging properties from the given file.
* @param loggingProperty the location of the file to read from.
*/
private void resetLogging(String loggingProperty) {
if (loggingProperty != null) {
// we need to copy into the unpacked domain the specified logging.properties file
File file = new File(loggingProperty);
if (file.canRead()) {
try {
runtimeDir.setLoggingProperties(file);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Could not copy over logging properties file", ex);
}
}
if (logToFile) {
LOGGER.log(Level.WARNING, "logToFile command line option ignored as a logging.properties file has been provided");
}
System.setProperty("java.util.logging.config.file", runtimeDir.getLoggingProperties().getAbsolutePath());
try (InputStream is = new FileInputStream(runtimeDir.getLoggingProperties())) {
LogManager.getLogManager().readConfiguration(replaceEnvProperties(is));
// go through all root handlers and set formatters based on properties
Logger rootLogger = LogManager.getLogManager().getLogger("");
for (Handler handler : rootLogger.getHandlers()) {
String formatter = LogManager.getLogManager().getProperty(handler.getClass().getCanonicalName() + ".formatter");
if (formatter != null) {
handler.setFormatter((Formatter) Class.forName(formatter).newInstance());
}
}
} catch (SecurityException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
LOGGER.log(Level.SEVERE, "Unable to reset the log manager", ex);
}
} else { // system property was not set on the command line using the command option or via -D
// we are likely using our default properties file so see if we need to rewrite it
if (logToFile) {
// we need to reset our logging properties to use the file handler as well
// read the default properties and then add the file handler properties
Properties currentProps = new Properties();
try (InputStream is = new FileInputStream(runtimeDir.getLoggingProperties())) {
currentProps.load(is);
// add file handler properties
currentProps.setProperty("java.util.logging.FileHandler.pattern", userLogFile);
currentProps.setProperty("handlers", "java.util.logging.FileHandler, java.util.logging.ConsoleHandler");
currentProps.setProperty("java.util.logging.FileHandler.limit", "1024000");
currentProps.setProperty("java.util.logging.FileHandler.count", "10");
currentProps.setProperty("java.util.logging.FileHandler.level", "INFO");
currentProps.setProperty("java.util.logging.FileHandler.formatter", "java.util.logging.SimpleFormatter");
currentProps.setProperty("java.util.logging.FileHandler.append", "true");
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Unable to load the logging properties from the runtime directory", ex);
}
// now write them back
try (OutputStream os = new FileOutputStream(runtimeDir.getLoggingProperties())) {
new SortedLoggingProperties(currentProps).store(os, "Generated Logging properties file from Payara Micro log to file option");
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Unable to load the logging properties from the runtime directory", ex);
}
}
System.setProperty("java.util.logging.config.file", runtimeDir.getLoggingProperties().getAbsolutePath());
try (InputStream is = new FileInputStream(runtimeDir.getLoggingProperties())) {
LogManager.getLogManager().readConfiguration(replaceEnvProperties(is));
// reset the formatters on the two handlers
//Logger rootLogger = Logger.getLogger("");
String formatter = LogManager.getLogManager().getProperty("java.util.logging.ConsoleHandler.formatter");
Formatter formatterClass = new ODLLogFormatter(null);
try {
formatterClass = (Formatter) Class.forName(formatter).newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
LOGGER.log(Level.SEVERE, "Specified Formatter class could not be loaded " + formatter, ex);
}
Logger rootLogger = Logger.getLogger("");
for (Handler handler : rootLogger.getHandlers()) {
handler.setFormatter(formatterClass);
}
} catch (SecurityException | IOException ex) {
LOGGER.log(Level.SEVERE, "Unable to reset the log manager", ex);
}
}
}
/**
* Method to replace Env properties with corresponding value from System properties
* @param is InputStream from File with properties
* @return an instance of ByteArrayInputStream with the preprocessed properties
* @throws IOException
*/
private ByteArrayInputStream replaceEnvProperties(InputStream is) throws IOException {
//preprocessing the properties read from the custom properties file
Properties configuration = new Properties();
configuration.load(is);
//set the System.getenv() to be used for the replacement process. The desired property to be mapped
//should need to be available on the System.getenv() Map
configuration = new PropertyPlaceholderHelper(System.getenv(),
PropertyPlaceholderHelper.ENV_REGEX).replacePropertiesPlaceholder(configuration);
StringWriter writer = new StringWriter();
configuration.store(new PrintWriter(writer), null);
//here is added the new inputStream with the preprocessed properties solving the replacement issues
return new ByteArrayInputStream(writer.getBuffer().toString().getBytes());
}
/**
* Helper method to parse the pre-boot command file.
*
* @throws IOException
*/
private void parsePreBootCommandFiles() throws IOException {
parseCommandFiles("MICRO-INF/pre-boot-commands.txt", preBootFileName, preBootCommands, false);
}
/**
* Helper method to parse the post-boot command file.
*
* @throws IOException
*/
private void parsePostBootCommandFiles() throws IOException {
parseCommandFiles("MICRO-INF/post-boot-commands.txt", postBootFileName, postBootCommands, true);
}
/**
* Helper method to parse the post-deploy command file.
*
* @throws IOException
*/
private void parsePostDeployCommandFiles() throws IOException {
parseCommandFiles("MICRO-INF/post-deploy-commands.txt", postDeployFileName, postDeployCommands, true);
}
/**
* Parse the pre-boot, post-boot, or post-deploy command files - both the embedded one in MICRO-INF and the file
* provided by the user.
*
* @param resourcePath The path of the embedded pre-boot, post-boot, or post-deploy command file.
* @param fileName The path of the pre-boot, post-boot, or post-deploy command file provided by the user.
* @param bootCommands The {@link BootCommands} object to add the parsed commands to.
* @param expandValues Whether variable expansion should be attempted - cannot be done during pre-boot.
* @throws IOException
*/
private void parseCommandFiles(String resourcePath, String fileName, BootCommands bootCommands,
boolean expandValues) throws IOException {
// Load the embedded file
URL scriptURL = Thread.currentThread().getContextClassLoader().getResource(resourcePath);
if (scriptURL != null) {
bootCommands.parseCommandScript(scriptURL, expandValues);
}
if (fileName != null) {
bootCommands.parseCommandScript(new File(fileName), expandValues);
}
}
private void configureAccessLogging() {
if (enableAccessLog) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.http-service.access-logging-enabled=true"));
preBootCommands.add(new BootCommand("set", "configs.config.server-config.http-service.virtual-server.server.access-log=" + userAccessLogDirectory));
preBootCommands.add(new BootCommand("set", "configs.config.server-config.http-service.virtual-server.server.access-logging-enabled=true"));
preBootCommands.add(new BootCommand("set", "configs.config.server-config.http-service.access-log.write-interval-seconds=" + accessLogInterval));
preBootCommands.add(new BootCommand("set", "configs.config.server-config.http-service.access-log.rotation-suffix=" + accessLogSuffix));
if(accessLogPrefix != null && !accessLogPrefix.trim().isEmpty()) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.http-service.virtual-server.server.property.accessLogPrefix=" + accessLogPrefix));
}
if (enableAccessLogFormat) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.http-service.access-log.format=" + accessLogFormat));
}
}
}
private void configureThreads() {
if (this.maxHttpThreads != Integer.MIN_VALUE) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.thread-pools.thread-pool.http-thread-pool.max-thread-pool-size=" + maxHttpThreads));
}
if (this.minHttpThreads != Integer.MIN_VALUE) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.thread-pools.thread-pool.http-thread-pool.min-thread-pool-size=" + minHttpThreads));
}
}
private void configurePorts() throws GlassFishException {
// build the glassfish properties
if (httpPort != Integer.MIN_VALUE) {
if (autoBindHttp == true) {
// Log warnings if overriding other options
logPortPrecedenceWarnings(false);
// Configure the port range from the specified port
int minPort = httpPort;
int maxPort = minPort + autoBindRange;
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.http-listener.port-range=" + Integer.toString(minPort) + "," + Integer.toString(maxPort)));
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.http-listener.enabled=true"));
} else {
// Log warnings if overriding other options
logPortPrecedenceWarnings(false);
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.http-listener.port=" + httpPort));
}
} else if (autoBindHttp == true) {
// Log warnings if overriding other options
logPortPrecedenceWarnings(false);
// Configure the port range from the default HTTP port
int minPort = defaultHttpPort;
int maxPort = minPort + autoBindRange;
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.http-listener.port-range=" + Integer.toString(minPort) + "," + Integer.toString(maxPort)));
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.http-listener.enabled=true"));
}
if (sslPort != Integer.MIN_VALUE) {
if (autoBindSsl == true) {
// Log warnings if overriding other options
logPortPrecedenceWarnings(true);
// Configure the port range from the specified port
int minPort = sslPort;
int maxPort = minPort + autoBindRange;
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.https-listener.port-range=" + Integer.toString(minPort) + "," + Integer.toString(maxPort)));
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.https-listener.enabled=true"));
} else {
// Log warnings if overriding other options
logPortPrecedenceWarnings(true);
// Configure the port range from the default port
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.https-listener.port=" + sslPort));
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.https-listener.enabled=true"));
}
} else if (autoBindSsl == true) {
// Log warnings if overriding other options
logPortPrecedenceWarnings(true);
// Configure the port range from the default HTTPS port
int minPort = defaultHttpsPort;
int maxPort = minPort + autoBindRange;
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.https-listener.port-range=" + Integer.toString(minPort) + "," + Integer.toString(maxPort)));
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.network-listeners.network-listener.https-listener.enabled=true"));
}
if (sniEnabled) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.protocols.protocol.https-listener.ssl.sni-enabled=true"));
}
if (sslCert != null) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.network-config.protocols.protocol.https-listener.ssl.cert-nickname=" + sslCert));
}
}
private void configurePhoneHome() {
if (disablePhoneHome == true) {
LOGGER.info("Disabled Phone Home");
preBootCommands.add(new BootCommand("set", "configs.config.server-config.phone-home-runtime-configuration.enabled=false"));
}
}
private void configureHazelcast() {
// check hazelcast cluster overrides
// set join wait based on the command flag
if (System.getProperty("hazelcast.wait.seconds.before.join") == null) {
System.setProperty("hazelcast.wait.seconds.before.join", Integer.toString(initialJoinWait));
}
if (noCluster) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.hazelcast-config-specific-configuration.clustering-enabled=false"));
} else if (noHazelcast) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.hazelcast-config-specific-configuration.enabled=false"));
preBootCommands.add(new BootCommand("set", "configs.config.server-config.ejb-container.ejb-timer-service.ejb-timer-service=Dummy"));
} else {
if (hzPort > Integer.MIN_VALUE) {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.multicast-port=" + hzPort));
}
if (hzStartPort > Integer.MIN_VALUE) {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.start-port=" + hzStartPort));
}
if (hzMulticastGroup != null) {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.multicast-group=" + hzMulticastGroup));
}
if (alternateHZConfigFile != null) {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.hazelcast-configuration-file=" + alternateHZConfigFile.getPath()));
}
preBootCommands.add(new BootCommand("set", "configs.config.server-config.hazelcast-config-specific-configuration.lite=" + liteMember));
if (hzClusterName != null) {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.cluster-group-name=" + hzClusterName));
}
if (instanceName != null) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.hazelcast-config-specific-configuration.member-name=" + instanceName));
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.generate-names=false"));
}
if (instanceGroup != null) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.hazelcast-config-specific-configuration.member-group=" + instanceGroup));
}
if (publicAddress != null && !publicAddress.isEmpty()) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.hazelcast-config-specific-configuration.public-address=" + publicAddress));
}
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.host-aware-partitioning=" + hostAware));
if (clustermode != null) {
if (clustermode.startsWith("tcpip:")) {
String tcpipmembers = clustermode.substring(6);
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.tcpip-members=" + tcpipmembers));
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.discovery-mode=tcpip"));
} else if (clustermode.startsWith("multicast:")) {
String hostPort[] = clustermode.split(":");
if (hostPort.length == 3) {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.multicast-group=" + hostPort[1]));
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.multicast-port=" + hostPort[2]));
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.discovery-mode=multicast"));
}
} else if (clustermode.startsWith("domain:")) {
String hostPort[] = clustermode.split(":");
if (hostPort.length == 3) {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.das-public-address=" + hostPort[1]));
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.das-port=" + hostPort[2]));
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.discovery-mode=domain"));
}
} else if (clustermode.startsWith("kubernetes")) {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.discovery-mode=kubernetes"));
if (clustermode.length() > 11) {
String[] kubernetesInfo = clustermode.substring(11).split(",");
if (kubernetesInfo.length == 2) {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.kubernetes-namespace=" + kubernetesInfo[0]));
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.kubernetes-service-name=" + kubernetesInfo[1]));
}
}
} else if (clustermode.startsWith("dns:")) {
String dnsmembers = clustermode.substring(4);
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.dns-members=" + dnsmembers));
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.discovery-mode=dns"));
}
} else {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.discovery-mode=multicast"));
}
if (interfaces != null) {
preBootCommands.add(new BootCommand("set", "hazelcast-runtime-configuration.interface=" + interfaces));
}
}
}
/**
* Determines whether the server is running i.e. bootstrap has been called
*
* @return true of the server is running
*/
boolean isRunning() {
try {
return (gf != null && gf.getStatus() == Status.STARTED);
} catch (GlassFishException ex) {
return false;
}
}
void generateLogo() {
try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(bootImage);) {
byte[] buffer = new byte[1024];
for (int length; (length = is.read(buffer)) != -1;) {
System.err.write(buffer, 0, length);
System.err.flush();
}
} catch (IOException | NullPointerException ex) {
LOGGER.log(Level.WARNING, "Problems displaying Boot Image", ex);
}
}
private Map.Entry getGAVURI(String gav) throws GlassFishException {
try {
Map.Entry artefactMapEntry = GAVConvertor.getArtefactMapEntry(gav, repositoryURIs);
return new AbstractMap.SimpleImmutableEntry<>(artefactMapEntry.getKey(), artefactMapEntry.getValue());
} catch (URISyntaxException ex) {
throw new GlassFishException(ex.getMessage());
}
}
/**
* Logs warnings if ports are being overridden
*
* @param HTTPS True if checking if HTTPS ports are being overridden
*/
private void logPortPrecedenceWarnings(boolean HTTPS) {
if (HTTPS == true) {
if (alternateDomainXML != null) {
if (sslPort != Integer.MIN_VALUE) {
if (autoBindSsl == true) {
LOGGER.log(Level.INFO, "Overriding HTTPS port value set"
+ " in {0} and auto-binding against " + sslPort,
alternateDomainXML.getAbsolutePath());
} else {
LOGGER.log(Level.INFO, "Overriding HTTPS port value set"
+ " in {0} with " + sslPort,
alternateDomainXML.getAbsolutePath());
}
} else if (autoBindSsl == true) {
LOGGER.log(Level.INFO, "Overriding HTTPS port value set"
+ " in {0} and auto-binding against "
+ defaultHttpsPort,
alternateDomainXML.getAbsolutePath());
} else {
LOGGER.log(Level.INFO, "Overriding HTTPS port value set"
+ " in {0} with " + defaultHttpsPort,
alternateDomainXML.getAbsolutePath());
}
}
if (rootDir != null) {
File configFile = new File(rootDir.getAbsolutePath()
+ File.separator + "config" + File.separator
+ "domain.xml");
if (configFile.exists()) {
if (sslPort != Integer.MIN_VALUE) {
if (autoBindSsl == true) {
LOGGER.log(Level.INFO, "Overriding HTTPS port value"
+ " set in {0} and auto-binding against "
+ sslPort, configFile.getAbsolutePath());
} else {
LOGGER.log(Level.INFO, "Overriding HTTPS port value"
+ " set in {0} with " + sslPort,
configFile.getAbsolutePath());
}
} else if (autoBindSsl == true) {
LOGGER.log(Level.INFO, "Overriding HTTPS port value"
+ " set in {0} and auto-binding against "
+ defaultHttpsPort,
configFile.getAbsolutePath());
} else {
LOGGER.log(Level.INFO, "Overriding HTTPS port value"
+ " set in {0} with default value of "
+ defaultHttpsPort,
configFile.getAbsolutePath());
}
}
}
} else {
if (alternateDomainXML != null) {
if (httpPort != Integer.MIN_VALUE) {
if (autoBindHttp == true) {
LOGGER.log(Level.INFO, "Overriding HTTP port value set "
+ "in {0} and auto-binding against " + httpPort,
alternateDomainXML.getAbsolutePath());
} else {
LOGGER.log(Level.INFO, "Overriding HTTP port value set "
+ "in {0} with " + httpPort,
alternateDomainXML.getAbsolutePath());
}
} else if (autoBindHttp == true) {
LOGGER.log(Level.INFO, "Overriding HTTP port value set "
+ "in {0} and auto-binding against "
+ defaultHttpPort,
alternateDomainXML.getAbsolutePath());
} else {
LOGGER.log(Level.INFO, "Overriding HTTP port value set "
+ "in {0} with default value of "
+ defaultHttpPort,
alternateDomainXML.getAbsolutePath());
}
}
if (rootDir != null) {
File configFile = new File(rootDir.getAbsolutePath()
+ File.separator + "config" + File.separator
+ "domain.xml");
if (configFile.exists()) {
if (httpPort != Integer.MIN_VALUE) {
if (autoBindHttp == true) {
LOGGER.log(Level.INFO, "Overriding HTTP port value "
+ "set in {0} and auto-binding against "
+ httpPort, configFile.getAbsolutePath());
} else {
LOGGER.log(Level.INFO, "Overriding HTTP port value "
+ "set in {0} with " + httpPort,
configFile.getAbsolutePath());
}
} else if (autoBindHttp == true) {
LOGGER.log(Level.INFO, "Overriding HTTP port value "
+ "set in {0} and auto-binding against "
+ defaultHttpPort,
configFile.getAbsolutePath());
} else {
LOGGER.log(Level.INFO, "Overriding HTTP port value "
+ "set in {0} with default value of "
+ defaultHttpPort,
configFile.getAbsolutePath());
}
}
}
}
}
private void setArgumentsFromSystemProperties() {
// Set the domain.xml
String alternateDomainXMLStr = getProperty("payaramicro.domainConfig");
if (alternateDomainXMLStr != null && !alternateDomainXMLStr.isEmpty()) {
applicationDomainXml = alternateDomainXMLStr;
}
// Set the hazelcast config file
String alternateHZConfigFileStr = getProperty("payaramicro.hzConfigFile");
if (alternateHZConfigFileStr != null && !alternateHZConfigFileStr.isEmpty()) {
alternateHZConfigFile = new File(alternateHZConfigFileStr);
}
String userLogPropertiesFileStr = getProperty("payaramicro.logPropertiesFile");
if (userLogPropertiesFileStr != null && !userLogPropertiesFileStr.trim().isEmpty()) {
setLogPropertiesFile(new File(userLogPropertiesFileStr));
}
autoBindHttp = getBooleanProperty("payaramicro.autoBindHttp");
autoBindRange = getIntegerProperty("payaramicro.autoBindRange", 5);
initialJoinWait = getIntegerProperty("payaramicro.initialJoinWait", 1);
autoBindSsl = getBooleanProperty("payaramicro.autoBindSsl");
generateLogo = getBooleanProperty("payaramicro.logo");
logToFile = getBooleanProperty("payaramicro.logToFile");
userLogFile = getProperty("payaramicro.userLogFile");
enableAccessLog = getBooleanProperty("payaramicro.enableAccessLog");
enableAccessLogFormat = getBooleanProperty("payaramicro.enableAccessLogFormat");
enableDynamicLogging = getBooleanProperty("payaramicro.enableDynamicLogging");
enableHealthCheck = getBooleanProperty("payaramicro.enableHealthCheck");
httpPort = getIntegerProperty("payaramicro.port", Integer.MIN_VALUE);
sslPort = getIntegerProperty("payaramicro.sslPort", Integer.MIN_VALUE);
sslCert = getProperty("payaramicro.sslCert");
sniEnabled = getBooleanProperty("payaramicro.sniEnabled");
hzMulticastGroup = getProperty("payaramicro.mcAddress");
hzPort = getIntegerProperty("payaramicro.mcPort", Integer.MIN_VALUE);
hostAware = getBooleanProperty("payaramicro.hostAware", "true");
hzStartPort = getIntegerProperty("payaramicro.startPort", Integer.MIN_VALUE);
hzClusterName = getProperty("payaramicro.clusterName");
liteMember = getBooleanProperty("payaramicro.lite");
maxHttpThreads = getIntegerProperty("payaramicro.maxHttpThreads", Integer.MIN_VALUE);
minHttpThreads = getIntegerProperty("payaramicro.minHttpThreads", Integer.MIN_VALUE);
noCluster = getBooleanProperty("payaramicro.noCluster");
noHazelcast = getBooleanProperty("payaramicro.noHazelcast");
disablePhoneHome = getBooleanProperty("payaramicro.disablePhoneHome");
enableRequestTracing = getBooleanProperty("payaramicro.enableRequestTracing");
requestTracingThresholdUnit = getProperty("payaramicro.requestTracingThresholdUnit", "SECONDS");
requestTracingThresholdValue = getLongProperty("payaramicro.requestTracingThresholdValue", 30L);
enableRequestTracingAdaptiveSampling = getBooleanProperty("payaramicro.enableRequestTracingAdaptiveSampling");
requestTracingAdaptiveSamplingTargetCount = getIntegerProperty("payaramicro.requestTracingAdaptiveSamplingTargetCount", requestTracingAdaptiveSamplingTargetCount);
requestTracingAdaptiveSamplingTimeValue = getIntegerProperty("payaramicro.requestTracingAdaptiveSamplingTimeValue", requestTracingAdaptiveSamplingTimeValue);
requestTracingAdaptiveSamplingTimeUnit = getProperty("payaramicro.requestTracingAdaptiveSamplingTimeUnit", requestTracingAdaptiveSamplingTimeUnit).toUpperCase();
clustermode = getProperty("payaramicro.clusterMode");
interfaces = getProperty("payaramicro.interfaces");
secretsDir = getProperty("payaramicro.secretsDir");
showServletMappings = getBooleanProperty("payaramicro.showServletMappings", "false");
publicAddress = getProperty("payaramicro.publicAddress");
contextRoot = getProperty("payaramicro.contextRoot");
// Set the rootDir file
String rootDirFileStr = getProperty("payaramicro.rootDir");
if (rootDirFileStr != null && !rootDirFileStr.isEmpty()) {
rootDir = new File(rootDirFileStr);
}
String name = getProperty("payaramicro.name");
if (name != null && !name.isEmpty()) {
instanceName = name;
}
String instanceGroupName = getProperty("payaramicro.instanceGroup");
if (instanceGroupName != null && !instanceGroupName.isEmpty()) {
instanceGroup = instanceGroupName;
}
}
private void packageUberJar() throws GlassFishException {
processDeploymentOptions();
UberJarCreator creator = new UberJarCreator(uberJar);
if (rootDir != null) {
creator.setDomainDir(rootDir);
}
if (postBootFileName != null) {
creator.setPostBootCommands(new File(postBootFileName));
}
if (preBootFileName != null) {
creator.setPreBootCommands(new File(preBootFileName));
}
if (postDeployFileName != null) {
creator.setPostDeployCommands(new File(postDeployFileName));
}
if (logPropertiesFile) {
creator.setLoggingPropertiesFile(new File(userLogPropertiesFile));
}
if (deployments != null) {
for (Map.Entry deployment : deployments.entrySet()) {
creator.addDeployment(deployment.getKey(), deployment.getValue());
}
}
if (libraries != null) {
for (File lib : libraries) {
creator.addLibraryJar(lib);
}
}
if (copyDirectory != null) {
creator.setDirectoryToCopy(copyDirectory);
}
if (contextRoots != null) {
creator.setContextRoots(contextRoots);
}
// write the system properties file
Properties props = new Properties();
if (hzMulticastGroup != null) {
props.setProperty("payaramicro.mcAddress", hzMulticastGroup);
}
if (hzPort != Integer.MIN_VALUE) {
props.setProperty("payaramicro.mcPort", Integer.toString(hzPort));
}
if (instanceName != null) {
props.setProperty("payaramicro.name", instanceName);
}
if (instanceGroup != null) {
props.setProperty("payaramicro.instanceGroup", instanceGroup);
}
if (hzStartPort != Integer.MIN_VALUE) {
props.setProperty("payaramicro.startPort", Integer.toString(hzStartPort));
}
if (rootDir != null) {
props.setProperty("payaramicro.rootDir", rootDir.getAbsolutePath());
}
if (alternateDomainXML != null) {
props.setProperty("payaramicro.domainConfig", "MICRO-INF/domain/domain.xml");
}
if (minHttpThreads != Integer.MIN_VALUE) {
props.setProperty("payaramicro.minHttpThreads", Integer.toString(minHttpThreads));
}
if (maxHttpThreads != Integer.MIN_VALUE) {
props.setProperty("payaramicro.maxHttpThreads", Integer.toString(maxHttpThreads));
}
if (alternateHZConfigFile != null) {
props.setProperty("payaramicro.hzConfigFile", "MICRO-INF/domain/hzconfig.xml");
}
if (hzClusterName != null) {
props.setProperty("payaramicro.clusterName", hzClusterName);
}
if (clustermode != null) {
props.setProperty("payaramicro.clusterMode", clustermode);
}
if (interfaces != null) {
props.setProperty("payaramicro.interfaces", interfaces);
}
if (secretsDir != null) {
props.setProperty("payaramicro.secretsDir", secretsDir);
}
if (sslCert != null) {
props.setProperty("payaramicro.sslCert", sslCert);
}
if (contextRoot != null) {
props.setProperty("payaramicro.contextRoot", contextRoot);
}
props.setProperty("payaramicro.autoBindHttp", Boolean.toString(autoBindHttp));
props.setProperty("payaramicro.autoBindSsl", Boolean.toString(autoBindSsl));
props.setProperty("payaramicro.autoBindRange", Integer.toString(autoBindRange));
props.setProperty("payaramicro.lite", Boolean.toString(liteMember));
props.setProperty("payaramicro.enableHealthCheck", Boolean.toString(enableHealthCheck));
props.setProperty("payaramicro.logo", Boolean.toString(generateLogo));
props.setProperty("payaramicro.logToFile", Boolean.toString(logToFile));
props.setProperty("payaramicro.enableAccessLog", Boolean.toString(enableAccessLog));
props.setProperty("payaramicro.enableAccessLogFormat", Boolean.toString(enableAccessLogFormat));
props.setProperty("payaramicro.logPropertiesFile", Boolean.toString(logPropertiesFile));
props.setProperty("payaramicro.enableDynamicLogging", Boolean.toString(enableDynamicLogging));
props.setProperty("payaramicro.noCluster", Boolean.toString(noCluster));
props.setProperty("payaramicro.noHazelcast", Boolean.toString(noHazelcast));
props.setProperty("payaramicro.hostAware", Boolean.toString(hostAware));
props.setProperty("payaramicro.disablePhoneHome", Boolean.toString(disablePhoneHome));
props.setProperty("payaramicro.showServletMappings", Boolean.toString(showServletMappings));
props.setProperty("payaramicro.sniEnabled", Boolean.toString(sniEnabled));
props.setProperty("payaramicro.initialJoinWait", Integer.toString(initialJoinWait));
if (publicAddress != null) {
props.setProperty("payaramicro.publicAddress", publicAddress);
}
if (userLogFile != null) {
props.setProperty("payaramicro.userLogFile", userLogFile);
}
if (httpPort != Integer.MIN_VALUE) {
props.setProperty("payaramicro.port", Integer.toString(httpPort));
}
if (sslPort != Integer.MIN_VALUE) {
props.setProperty("payaramicro.sslPort", Integer.toString(sslPort));
}
if (enableRequestTracing) {
props.setProperty("payaramicro.enableRequestTracing", Boolean.toString(enableRequestTracing));
}
if (!requestTracingThresholdUnit.equals("SECONDS")) {
props.setProperty("payaramicro.requestTracingThresholdUnit", requestTracingThresholdUnit);
}
if (requestTracingThresholdValue != 30) {
props.setProperty("payaramicro.requestTracingThresholdValue", Long.toString(requestTracingThresholdValue));
}
if (enableRequestTracingAdaptiveSampling) {
props.setProperty("payaramicro.enableRequestTracingAdaptiveSampling", Boolean.toString(enableRequestTracingAdaptiveSampling));
}
if (requestTracingAdaptiveSamplingTargetCount != 12) {
props.setProperty("payaramicro.requestTracingAdaptiveSamplingTargetCount", Integer.toString(requestTracingAdaptiveSamplingTargetCount));
}
if (requestTracingAdaptiveSamplingTimeValue != 1) {
props.setProperty("payaramicro.requestTracingAdaptiveSamplingTimeValue", Integer.toString(requestTracingAdaptiveSamplingTimeValue));
}
if (!requestTracingAdaptiveSamplingTimeUnit.equals("MINUTES")) {
props.setProperty("payaramicro.requestTracingAdaptiveSamplingTimeUnit", requestTracingAdaptiveSamplingTimeUnit);
}
// write all user defined system properties
if (userSystemProperties != null) {
Enumeration names = (Enumeration) userSystemProperties.propertyNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
props.setProperty(name, userSystemProperties.getProperty(name));
}
}
creator.addBootProperties(props);
// add the alternate domain.xml file if present
if (alternateDomainXML != null && alternateDomainXML.isFile() && alternateDomainXML.canRead()) {
creator.setDomainXML(alternateDomainXML);
}
// add the alternate hazelcast config to the uberJar
if (alternateHZConfigFile != null) {
creator.setAlternateHZConfigFile(alternateHZConfigFile);
}
creator.buildUberJar();
}
private void createLauncher() throws BootstrapException {
try {
if (rootDir == null) {
LOGGER.severe("--rootdir is required for creating a launcher");
System.exit(-1);
}
unPackRuntime();
addLibraries();
LauncherCreator creator = new LauncherCreator(rootDir, ((URLClassLoader)getClass().getClassLoader()));
creator.buildLauncher();
} catch (RuntimeException | URISyntaxException | IOException e) {
throw new BootstrapException("Unable to create launcher", e);
}
}
private static String unifyTimeUnit(String option) {
switch (option.toLowerCase()) {
case "nanosecond":
case "ns":
return "NANOSECONDS";
case "microsecond":
case "us":
case "µs":
return "MICROSECONDS";
case "millisecond":
case "ms":
return "MILLISECONDS";
case "second":
case "s":
return "SECONDS";
case "m":
case "minute":
case "min":
case "mins":
return "MINUTES";
case "hour":
case "h":
return "HOURS";
case "day":
case "d":
return "DAYS";
default:
return option;
}
}
private static TimeUnit parseTimeUnit(String value, String errorText) {
return parseArgument(value, errorText, val -> TimeUnit.valueOf(unifyTimeUnit(val).toUpperCase()));
}
private static T parseArgument(String value, String errorText, Function parser) {
try {
return parser.apply(value);
} catch (IllegalArgumentException e) {
LOGGER.log(Level.WARNING, "{0} is not a valid " + errorText, value);
throw e;
}
}
private void printVersion() {
try {
Properties props = new Properties();
InputStream input = PayaraMicroImpl.class
.getResourceAsStream("/MICRO-INF/domain/branding/glassfish-version.properties");
props.load(input);
StringBuilder output = new StringBuilder();
if (props.getProperty("product_name").isEmpty() == false) {
output.append(props.getProperty("product_name")).append(" ");
}
if (props.getProperty("major_version").isEmpty() == false) {
output.append(props.getProperty("major_version")).append(".");
}
if (props.getProperty("minor_version").isEmpty() == false) {
output.append(props.getProperty("minor_version")).append(".");
}
if (props.getProperty("update_version").isEmpty() == false) {
output.append(props.getProperty("update_version")).append(".");
}
if (props.getProperty("build_id").isEmpty() == false) {
output.append(" Build Number ").append(props.getProperty("build_id"));
}
System.err.println(output.toString());
} catch (FileNotFoundException ex) {
LOGGER.log(Level.SEVERE, null, ex);
} catch (IOException io) {
LOGGER.log(Level.SEVERE, null, io);
}
}
private void unPackRuntime() throws IOException, URISyntaxException {
if (rootDir != null) {
runtimeDir = new RuntimeDirectory(rootDir);
} else {
runtimeDir = new RuntimeDirectory();
}
if (alternateDomainXML != null) {
runtimeDir.setDomainXML(alternateDomainXML);
} else if (applicationDomainXml != null) {
try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(applicationDomainXml)) {
runtimeDir.setDomainXML(is);
}
}
if (alternateHZConfigFile != null) {
runtimeDir.setHZConfigFile(alternateHZConfigFile);
}
}
private static void setBootProperties() {
Properties bootProperties = new Properties();
// First Read from embedded boot preoprties
try (InputStream is = PayaraMicroImpl.class
.getResourceAsStream(BOOT_PROPS_FILE)) {
if (is != null) {
bootProperties.load(is);
for (String key : bootProperties.stringPropertyNames()) {
// do not override an existing system property
if (System.getProperty(key) == null) {
System.setProperty(key, bootProperties.getProperty(key));
}
}
}
} catch (IOException ioe) {
LOGGER.log(Level.WARNING, "Could not load the boot system properties from " + BOOT_PROPS_FILE, ioe);
}
}
private void configureNotificationService() {
if (enableHealthCheck || enableRequestTracing) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.notification-service-configuration.enabled=true"));
}
}
private void configureHealthCheck() {
if (enableHealthCheck) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.health-check-service-configuration.enabled=true"));
}
}
private void dumpFinalStatus(long bootTime) {
// Print instance descriptor
InstanceDescriptor id = getRuntime().getLocalDescriptor();
LOGGER.log(Level.INFO, id.toJsonString(showServletMappings));
// Get Payara Micro endpoints
StringBuilder sb = new StringBuilder();
sb.append("\nPayara Micro URLs:\n");
List urls = id.getApplicationURLS();
for (URL url : urls) {
sb.append(url.toString()).append('\n');
}
// Count through applications and add their REST endpoints
try {
ListRestEndpointsCommand cmd = gf.getService(ListRestEndpointsCommand.class);
id.getDeployedApplications().forEach(app -> {
Map> endpoints = null;
try {
endpoints = cmd.getEndpointMap(app.getName());
} catch (IllegalArgumentException ex) {
// The application has no endpoints
endpoints = null;
}
if (endpoints != null) {
sb.append("\n'").append(app.getName()).append("' REST Endpoints:\n");
endpoints.forEach((path, methods) -> {
methods.forEach(method -> {
sb.append(method).append("\t").append(path).append("\n");
});
});
}
});
} catch (GlassFishException ex) {
// Really shouldn't happen, the command catches it's own errors most of the time
LOGGER.log(Level.SEVERE, "Failed to get REST endpoints for application", ex);
}
sb.append("\n");
// Print out all endpoints
LOGGER.log(Level.INFO, sb.toString());
// Print the logo if it's enabled
if (generateLogo) {
generateLogo();
}
// Print final ready message
LOGGER.log(Level.INFO, "{0} ready in {1} (ms)", new Object[]{Version.getFullVersion(), bootTime});
}
private static String getProperty(String value) {
String result;
result = System.getProperty(value);
if (result == null) {
result = System.getenv(value.replace('.', '_'));
}
return result;
}
private static String getProperty(String value, String defaultValue) {
String result = getProperty(value);
if (result == null) {
result = defaultValue;
}
return result;
}
private static boolean getBooleanProperty(String value) {
String property;
property = System.getProperty(value);
if (property == null) {
property = System.getenv(value.replace('.', '_'));
}
return "true".equals(property);
}
private static boolean getBooleanProperty(String value, String defaultValue) {
String property;
property = System.getProperty(value);
if (property == null) {
property = System.getenv(value.replace('.', '_'));
if (property == null) {
property = defaultValue;
}
}
return "true".equals(property);
}
private static int getIntegerProperty(String value, int defaultValue) {
String property;
property = System.getProperty(value);
if (property == null) {
property = System.getenv(value.replace('.', '_'));
}
if (property == null) {
return defaultValue;
}
return Integer.decode(property);
}
private static long getLongProperty(String value, long defaultValue) {
String property;
property = System.getProperty(value);
if (property == null) {
property = System.getenv(value.replace('.', '_'));
}
if (property == null) {
return defaultValue;
}
return Long.decode(property);
}
/**
* Adds libraries to the classlader
*/
private void addLibraries() {
if (libraries != null) {
try {
for (File lib : libraries) {
addLibrary(lib);
}
} catch (SecurityException | IllegalArgumentException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
}
@Override
public PayaraMicroImpl addLibrary(File lib) {
OpenURLClassLoader loader = (OpenURLClassLoader) this.getClass().getClassLoader();
if (lib.exists() && lib.canRead() && lib.getName().endsWith(".jar")) {
try {
loader.addURL(lib.toURI().toURL());
LOGGER.log(Level.INFO, "Added " + lib.getAbsolutePath() + " to classpath");
} catch (MalformedURLException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
} else {
LOGGER.log(Level.SEVERE, "Unable to read jar " + lib.getName());
}
return this;
}
private void configureSecrets() {
if (secretsDir != null) {
preBootCommands.add(new BootCommand("set", "configs.config.server-config.microprofile-config.secret-dir=" + secretsDir));
}
}
@Override
public PayaraMicroBoot setPreBootHandler(Consumer handler) {
checkNotRunning();
preBootHandler = handler;
return this;
}
@Override
public PayaraMicroBoot setPostBootHandler(Consumer handler) {
checkNotRunning();
postBootHandler = handler;
return this;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy