| package org.apache.tomcat.maven.runner; |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import org.apache.catalina.Context; |
| import org.apache.catalina.Host; |
| import org.apache.catalina.connector.Connector; |
| import org.apache.catalina.core.StandardContext; |
| import org.apache.catalina.startup.Catalina; |
| import org.apache.catalina.startup.ContextConfig; |
| import org.apache.catalina.startup.Tomcat; |
| import org.apache.catalina.valves.AccessLogValve; |
| import org.apache.juli.ClassLoaderLogManager; |
| import org.apache.tomcat.util.ExceptionUtils; |
| import org.apache.tomcat.util.http.fileupload.FileUtils; |
| |
| import java.io.BufferedOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.security.AccessController; |
| import java.security.PrivilegedAction; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.StringTokenizer; |
| import java.util.logging.LogManager; |
| |
| /** |
| * FIXME add junit for that but when https://issues.apache.org/bugzilla/show_bug.cgi?id=52028 fixed |
| * Main class used to run the standalone wars in a Apache Tomcat instance. |
| * |
| * @author Olivier Lamy |
| * @since 2.0 |
| */ |
| public class Tomcat7Runner |
| { |
| // true/false to use the server.xml located in the jar /conf/server.xml |
| public static final String USE_SERVER_XML_KEY = "useServerXml"; |
| |
| // contains war name wars=foo.war,bar.war |
| public static final String WARS_KEY = "wars"; |
| |
| public static final String ARCHIVE_GENERATION_TIMESTAMP_KEY = "generationTimestamp"; |
| |
| public static final String ENABLE_NAMING_KEY = "enableNaming"; |
| |
| public static final String ACCESS_LOG_VALVE_FORMAT_KEY = "accessLogValveFormat"; |
| |
| public static final String CODE_SOURCE_CONTEXT_PATH = "codeSourceContextPath"; |
| |
| /** |
| * key of the property which contains http protocol : HTTP/1.1 or org.apache.coyote.http11.Http11NioProtocol |
| */ |
| public static final String HTTP_PROTOCOL_KEY = "connectorhttpProtocol"; |
| |
| /** |
| * key for default http port defined in the plugin |
| */ |
| public static final String HTTP_PORT_KEY = "httpPort"; |
| |
| |
| public int httpPort; |
| |
| public int httpsPort; |
| |
| public int ajpPort; |
| |
| public String serverXmlPath; |
| |
| public Properties runtimeProperties; |
| |
| public boolean resetExtract; |
| |
| public boolean debug = false; |
| |
| public String clientAuth = "false"; |
| |
| public String keyAlias = null; |
| |
| public String httpProtocol; |
| |
| public String extractDirectory = ".extract"; |
| |
| public File extractDirectoryFile; |
| |
| public String codeSourceContextPath = null; |
| |
| public File codeSourceWar = null; |
| |
| public String loggerName; |
| |
| Catalina container; |
| |
| Tomcat tomcat; |
| |
| String uriEncoding = "ISO-8859-1"; |
| |
| /** |
| * key = context of the webapp, value = war path on file system |
| */ |
| Map<String, String> webappWarPerContext = new HashMap<String, String>(); |
| |
| public Tomcat7Runner() |
| { |
| // no op |
| } |
| |
| public void run() |
| throws Exception |
| { |
| |
| PasswordUtil.deobfuscateSystemProps(); |
| |
| if ( loggerName != null && loggerName.length() > 0 ) |
| { |
| installLogger( loggerName ); |
| } |
| |
| this.extractDirectoryFile = new File( this.extractDirectory ); |
| |
| debugMessage( "use extractDirectory:" + extractDirectoryFile.getPath() ); |
| |
| boolean archiveTimestampChanged = false; |
| |
| // compare timestamp stored during previous run if exists |
| File timestampFile = new File( extractDirectoryFile, ".tomcat_executable_archive.timestamp" ); |
| |
| Properties timestampProps = loadProperties( timestampFile ); |
| |
| if ( timestampFile.exists() ) |
| { |
| String timestampValue = timestampProps.getProperty( Tomcat7Runner.ARCHIVE_GENERATION_TIMESTAMP_KEY ); |
| if ( timestampValue != null ) |
| { |
| long timestamp = Long.parseLong( timestampValue ); |
| archiveTimestampChanged = |
| Long.parseLong( runtimeProperties.getProperty( Tomcat7Runner.ARCHIVE_GENERATION_TIMESTAMP_KEY ) ) |
| > timestamp; |
| |
| debugMessage( "read timestamp from file " + timestampValue + ", archiveTimestampChanged: " |
| + archiveTimestampChanged ); |
| } |
| |
| } |
| |
| codeSourceContextPath = runtimeProperties.getProperty( CODE_SOURCE_CONTEXT_PATH ); |
| if ( codeSourceContextPath != null && !codeSourceContextPath.isEmpty() ) |
| { |
| codeSourceWar = AccessController.doPrivileged( new PrivilegedAction<File>() |
| { |
| public File run() |
| { |
| try |
| { |
| File src = |
| new File( Tomcat7Runner.class.getProtectionDomain().getCodeSource().getLocation().toURI() ); |
| if ( src.getName().endsWith( ".war" ) ) |
| { |
| return src; |
| } |
| else |
| { |
| debugMessage( "ERROR: Code source is not a war file, ignoring." ); |
| } |
| } |
| catch ( URISyntaxException e ) |
| { |
| debugMessage( "ERROR: Could not find code source. " + e.getMessage() ); |
| |
| } |
| return null; |
| } |
| } ); |
| } |
| |
| // do we have to extract content |
| { |
| if ( !extractDirectoryFile.exists() || resetExtract || archiveTimestampChanged ) |
| { |
| extract(); |
| //if archiveTimestampChanged or timestamp file not exists store the last timestamp from the archive |
| if ( archiveTimestampChanged || !timestampFile.exists() ) |
| { |
| timestampProps.put( Tomcat7Runner.ARCHIVE_GENERATION_TIMESTAMP_KEY, runtimeProperties.getProperty( |
| Tomcat7Runner.ARCHIVE_GENERATION_TIMESTAMP_KEY ) ); |
| saveProperties( timestampProps, timestampFile ); |
| } |
| } |
| else |
| { |
| String wars = runtimeProperties.getProperty( WARS_KEY ); |
| populateWebAppWarPerContext( wars ); |
| } |
| } |
| |
| // create tomcat various paths |
| new File( extractDirectory, "conf" ).mkdirs(); |
| new File( extractDirectory, "logs" ).mkdirs(); |
| new File( extractDirectory, "webapps" ).mkdirs(); |
| new File( extractDirectory, "work" ).mkdirs(); |
| File tmpDir = new File( extractDirectory, "temp" ); |
| tmpDir.mkdirs(); |
| |
| System.setProperty( "java.io.tmpdir", tmpDir.getAbsolutePath() ); |
| |
| System.setProperty( "catalina.base", extractDirectoryFile.getAbsolutePath() ); |
| System.setProperty( "catalina.home", extractDirectoryFile.getAbsolutePath() ); |
| |
| // start with a server.xml |
| if ( serverXmlPath != null || useServerXml() ) |
| { |
| container = new Catalina(); |
| container.setUseNaming( this.enableNaming() ); |
| if ( serverXmlPath != null && new File( serverXmlPath ).exists() ) |
| { |
| container.setConfig( serverXmlPath ); |
| } |
| else |
| { |
| container.setConfig( new File( extractDirectory, "conf/server.xml" ).getAbsolutePath() ); |
| } |
| container.start(); |
| } |
| else |
| { |
| tomcat = new Tomcat() |
| { |
| public Context addWebapp( Host host, String url, String name, String path ) |
| { |
| |
| Context ctx = new StandardContext(); |
| ctx.setName( name ); |
| ctx.setPath( url ); |
| ctx.setDocBase( path ); |
| |
| ContextConfig ctxCfg = new ContextConfig(); |
| ctx.addLifecycleListener( ctxCfg ); |
| |
| ctxCfg.setDefaultWebXml( new File( extractDirectory, "conf/web.xml" ).getAbsolutePath() ); |
| |
| if ( host == null ) |
| { |
| getHost().addChild( ctx ); |
| } |
| else |
| { |
| host.addChild( ctx ); |
| } |
| |
| return ctx; |
| } |
| }; |
| |
| if ( this.enableNaming() ) |
| { |
| System.setProperty( "catalina.useNaming", "true" ); |
| tomcat.enableNaming(); |
| } |
| |
| tomcat.getHost().setAppBase( new File( extractDirectory, "webapps" ).getAbsolutePath() ); |
| |
| String connectorHttpProtocol = runtimeProperties.getProperty( HTTP_PROTOCOL_KEY ); |
| |
| if ( httpProtocol != null && httpProtocol.trim().length() > 0 ) |
| { |
| connectorHttpProtocol = httpProtocol; |
| } |
| |
| debugMessage( "use connectorHttpProtocol:" + connectorHttpProtocol ); |
| |
| if ( httpPort > 0 ) |
| { |
| Connector connector = new Connector( connectorHttpProtocol ); |
| connector.setPort( httpPort ); |
| |
| if ( httpsPort > 0 ) |
| { |
| connector.setRedirectPort( httpsPort ); |
| } |
| connector.setURIEncoding( uriEncoding ); |
| |
| tomcat.getService().addConnector( connector ); |
| |
| tomcat.setConnector( connector ); |
| } |
| |
| // add a default acces log valve |
| AccessLogValve alv = new AccessLogValve(); |
| alv.setDirectory( new File( extractDirectory, "logs" ).getAbsolutePath() ); |
| alv.setPattern( runtimeProperties.getProperty( Tomcat7Runner.ACCESS_LOG_VALVE_FORMAT_KEY ) ); |
| tomcat.getHost().getPipeline().addValve( alv ); |
| |
| // create https connector |
| if ( httpsPort > 0 ) |
| { |
| Connector httpsConnector = new Connector( connectorHttpProtocol ); |
| httpsConnector.setPort( httpsPort ); |
| httpsConnector.setSecure( true ); |
| httpsConnector.setProperty( "SSLEnabled", "true" ); |
| httpsConnector.setProperty( "sslProtocol", "TLS" ); |
| httpsConnector.setURIEncoding( uriEncoding ); |
| |
| String keystoreFile = System.getProperty( "javax.net.ssl.keyStore" ); |
| String keystorePass = System.getProperty( "javax.net.ssl.keyStorePassword" ); |
| String keystoreType = System.getProperty( "javax.net.ssl.keyStoreType", "jks" ); |
| |
| if ( keystoreFile != null ) |
| { |
| httpsConnector.setAttribute( "keystoreFile", keystoreFile ); |
| } |
| if ( keystorePass != null ) |
| { |
| httpsConnector.setAttribute( "keystorePass", keystorePass ); |
| } |
| httpsConnector.setAttribute( "keystoreType", keystoreType ); |
| |
| String truststoreFile = System.getProperty( "javax.net.ssl.trustStore" ); |
| String truststorePass = System.getProperty( "javax.net.ssl.trustStorePassword" ); |
| String truststoreType = System.getProperty( "javax.net.ssl.trustStoreType", "jks" ); |
| if ( truststoreFile != null ) |
| { |
| httpsConnector.setAttribute( "truststoreFile", truststoreFile ); |
| } |
| if ( truststorePass != null ) |
| { |
| httpsConnector.setAttribute( "truststorePass", truststorePass ); |
| } |
| httpsConnector.setAttribute( "truststoreType", truststoreType ); |
| |
| httpsConnector.setAttribute( "clientAuth", clientAuth ); |
| httpsConnector.setAttribute( "keyAlias", keyAlias ); |
| |
| tomcat.getService().addConnector( httpsConnector ); |
| |
| if ( httpPort <= 0 ) |
| { |
| tomcat.setConnector( httpsConnector ); |
| } |
| } |
| |
| // create ajp connector |
| if ( ajpPort > 0 ) |
| { |
| Connector ajpConnector = new Connector( "org.apache.coyote.ajp.AjpProtocol" ); |
| ajpConnector.setPort( ajpPort ); |
| ajpConnector.setURIEncoding( uriEncoding ); |
| tomcat.getService().addConnector( ajpConnector ); |
| } |
| |
| // add webapps |
| for ( Map.Entry<String, String> entry : this.webappWarPerContext.entrySet() ) |
| { |
| String baseDir = null; |
| Context context = null; |
| if ( entry.getKey().equals( "/" ) ) |
| { |
| baseDir = new File( extractDirectory, "webapps/ROOT.war" ).getAbsolutePath(); |
| context = tomcat.addWebapp( "", baseDir ); |
| } |
| else |
| { |
| baseDir = new File( extractDirectory, "webapps/" + entry.getValue() ).getAbsolutePath(); |
| context = tomcat.addWebapp( entry.getKey(), baseDir ); |
| } |
| |
| URL contextFileUrl = getContextXml( baseDir ); |
| if ( contextFileUrl != null ) |
| { |
| context.setConfigFile( contextFileUrl ); |
| } |
| } |
| |
| if ( codeSourceWar != null ) |
| { |
| String baseDir = new File( extractDirectory, "webapps/" + codeSourceWar.getName() ).getAbsolutePath(); |
| Context context = tomcat.addWebapp( codeSourceContextPath, baseDir ); |
| URL contextFileUrl = getContextXml( baseDir ); |
| if ( contextFileUrl != null ) |
| { |
| context.setConfigFile( contextFileUrl ); |
| } |
| } |
| |
| tomcat.start(); |
| |
| Runtime.getRuntime().addShutdownHook( new TomcatShutdownHook() ); |
| |
| } |
| |
| waitIndefinitely(); |
| |
| } |
| |
| protected class TomcatShutdownHook |
| extends Thread |
| { |
| |
| protected TomcatShutdownHook() |
| { |
| // no op |
| } |
| |
| @Override |
| public void run() |
| { |
| try |
| { |
| Tomcat7Runner.this.stop(); |
| } |
| catch ( Throwable ex ) |
| { |
| ExceptionUtils.handleThrowable( ex ); |
| System.out.println( "fail to properly shutdown Tomcat:" + ex.getMessage() ); |
| } |
| finally |
| { |
| // If JULI is used, shut JULI down *after* the server shuts down |
| // so log messages aren't lost |
| LogManager logManager = LogManager.getLogManager(); |
| if ( logManager instanceof ClassLoaderLogManager ) |
| { |
| ( (ClassLoaderLogManager) logManager ).shutdown(); |
| } |
| } |
| } |
| } |
| |
| private URL getContextXml( String warPath ) |
| throws IOException |
| { |
| InputStream inputStream = null; |
| try |
| { |
| String urlStr = "jar:file:" + warPath + "!/META-INF/context.xml"; |
| debugMessage( "search context.xml in url:'" + urlStr + "'" ); |
| URL url = new URL( urlStr ); |
| inputStream = url.openConnection().getInputStream(); |
| if ( inputStream != null ) |
| { |
| return url; |
| } |
| } |
| catch ( FileNotFoundException e ) |
| { |
| return null; |
| } |
| finally |
| { |
| closeQuietly( inputStream ); |
| } |
| return null; |
| } |
| |
| private static void closeQuietly( InputStream inputStream ) |
| { |
| if ( inputStream == null ) |
| { |
| return; |
| } |
| try |
| { |
| inputStream.close(); |
| } |
| catch ( IOException e ) |
| { |
| // ignore exception here |
| } |
| } |
| |
| private void waitIndefinitely() |
| { |
| Object lock = new Object(); |
| |
| synchronized ( lock ) |
| { |
| try |
| { |
| lock.wait(); |
| } |
| catch ( InterruptedException exception ) |
| { |
| throw new Error( "InterruptedException on wait Indefinitely lock:" + exception.getMessage(), |
| exception ); |
| } |
| } |
| } |
| |
| public void stop() |
| throws Exception |
| { |
| if ( container != null ) |
| { |
| container.stop(); |
| } |
| if ( tomcat != null ) |
| { |
| tomcat.stop(); |
| } |
| } |
| |
| protected void extract() |
| throws Exception |
| { |
| |
| if ( extractDirectoryFile.exists() ) |
| { |
| debugMessage( "delete extractDirectory:" + extractDirectoryFile.getAbsolutePath() ); |
| FileUtils.deleteDirectory( extractDirectoryFile ); |
| } |
| |
| if ( !this.extractDirectoryFile.exists() ) |
| { |
| boolean created = this.extractDirectoryFile.mkdirs(); |
| if ( !created ) |
| { |
| throw new Exception( "FATAL: impossible to create directory:" + this.extractDirectoryFile.getPath() ); |
| } |
| } |
| |
| // ensure webapp dir is here |
| boolean created = new File( extractDirectory, "webapps" ).mkdirs(); |
| if ( !created ) |
| { |
| throw new Exception( |
| "FATAL: impossible to create directory:" + this.extractDirectoryFile.getPath() + "/webapps" ); |
| |
| } |
| |
| String wars = runtimeProperties.getProperty( WARS_KEY ); |
| populateWebAppWarPerContext( wars ); |
| |
| for ( Map.Entry<String, String> entry : webappWarPerContext.entrySet() ) |
| { |
| debugMessage( "webappWarPerContext entry key/value: " + entry.getKey() + "/" + entry.getValue() ); |
| InputStream inputStream = null; |
| try |
| { |
| File expandFile = null; |
| inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream( entry.getValue() ); |
| if ( !useServerXml() ) |
| { |
| if ( entry.getKey().equals( "/" ) ) |
| { |
| expandFile = new File( extractDirectory, "webapps/ROOT.war" ); |
| } |
| else |
| { |
| expandFile = new File( extractDirectory, "webapps/" + entry.getValue() ); |
| } |
| } |
| else |
| { |
| expandFile = new File( extractDirectory, "webapps/" + entry.getValue() ); |
| } |
| |
| debugMessage( "expand to file:" + expandFile.getPath() ); |
| |
| // MTOMCAT-211 ensure parent directories created |
| |
| if ( !expandFile.getParentFile().mkdirs() ) |
| { |
| throw new Exception( "FATAL: impossible to create directories:" + expandFile.getParentFile() ); |
| } |
| |
| expand( inputStream, expandFile ); |
| |
| } |
| finally |
| { |
| if ( inputStream != null ) |
| { |
| inputStream.close(); |
| } |
| } |
| } |
| |
| //Copy code source to webapps folder |
| if ( codeSourceWar != null ) |
| { |
| FileInputStream inputStream = null; |
| try |
| { |
| File expandFile = new File( extractDirectory, "webapps/" + codeSourceContextPath + ".war" ); |
| inputStream = new FileInputStream( codeSourceWar ); |
| debugMessage( "move code source to file:" + expandFile.getPath() ); |
| expand( inputStream, expandFile ); |
| } |
| finally |
| { |
| if ( inputStream != null ) |
| { |
| inputStream.close(); |
| } |
| } |
| } |
| |
| // expand tomcat configuration files if there |
| expandConfigurationFile( "catalina.properties", extractDirectoryFile ); |
| expandConfigurationFile( "logging.properties", extractDirectoryFile ); |
| expandConfigurationFile( "tomcat-users.xml", extractDirectoryFile ); |
| expandConfigurationFile( "catalina.policy", extractDirectoryFile ); |
| expandConfigurationFile( "context.xml", extractDirectoryFile ); |
| expandConfigurationFile( "server.xml", extractDirectoryFile ); |
| expandConfigurationFile( "web.xml", extractDirectoryFile ); |
| |
| } |
| |
| private static void expandConfigurationFile( String fileName, File extractDirectory ) |
| throws Exception |
| { |
| InputStream inputStream = null; |
| try |
| { |
| inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream( "conf/" + fileName ); |
| if ( inputStream != null ) |
| { |
| File confDirectory = new File( extractDirectory, "conf" ); |
| if ( !confDirectory.exists() ) |
| { |
| confDirectory.mkdirs(); |
| } |
| expand( inputStream, new File( confDirectory, fileName ) ); |
| } |
| } |
| finally |
| { |
| if ( inputStream != null ) |
| { |
| inputStream.close(); |
| } |
| } |
| |
| } |
| |
| /** |
| * @param warsValue we can value in format: wars=foo.war|contextpath;bar.war ( |contextpath is optionnal if empty use the war name) |
| * so here we return war file name and populate webappWarPerContext |
| */ |
| private void populateWebAppWarPerContext( String warsValue ) |
| { |
| if ( warsValue == null ) |
| { |
| return; |
| } |
| |
| StringTokenizer st = new StringTokenizer( warsValue, ";" ); |
| while ( st.hasMoreTokens() ) |
| { |
| String warValue = st.nextToken(); |
| debugMessage( "populateWebAppWarPerContext warValue:" + warValue ); |
| String warFileName = ""; |
| String contextValue = ""; |
| int separatorIndex = warValue.indexOf( "|" ); |
| if ( separatorIndex >= 0 ) |
| { |
| warFileName = warValue.substring( 0, separatorIndex ); |
| contextValue = warValue.substring( separatorIndex + 1, warValue.length() ); |
| |
| } |
| else |
| { |
| warFileName = contextValue; |
| } |
| debugMessage( "populateWebAppWarPerContext contextValue/warFileName:" + contextValue + "/" + warFileName ); |
| this.webappWarPerContext.put( contextValue, warFileName ); |
| } |
| } |
| |
| |
| /** |
| * Expand the specified input stream into the specified file. |
| * |
| * @param input InputStream to be copied |
| * @param file The file to be created |
| * @throws java.io.IOException if an input/output error occurs |
| */ |
| private static void expand( InputStream input, File file ) |
| throws IOException |
| { |
| BufferedOutputStream output = null; |
| try |
| { |
| output = new BufferedOutputStream( new FileOutputStream( file ) ); |
| byte buffer[] = new byte[2048]; |
| while ( true ) |
| { |
| int n = input.read( buffer ); |
| if ( n <= 0 ) |
| { |
| break; |
| } |
| output.write( buffer, 0, n ); |
| } |
| } |
| finally |
| { |
| if ( output != null ) |
| { |
| try |
| { |
| output.close(); |
| } |
| catch ( IOException e ) |
| { |
| // Ignore |
| } |
| } |
| } |
| } |
| |
| public boolean useServerXml() |
| { |
| return Boolean.parseBoolean( runtimeProperties.getProperty( USE_SERVER_XML_KEY, Boolean.FALSE.toString() ) ); |
| } |
| |
| |
| public void debugMessage( String message ) |
| { |
| if ( debug ) |
| { |
| System.out.println( message ); |
| } |
| } |
| |
| |
| public boolean enableNaming() |
| { |
| return Boolean.parseBoolean( runtimeProperties.getProperty( ENABLE_NAMING_KEY, Boolean.FALSE.toString() ) ); |
| } |
| |
| private void installLogger( String loggerName ) |
| throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, |
| InvocationTargetException |
| { |
| if ( "slf4j".equals( loggerName ) ) |
| { |
| |
| try |
| { |
| // Check class is available |
| |
| //final Class<?> clazz = Class.forName( "org.slf4j.bridge.SLF4JBridgeHandler" ); |
| final Class<?> clazz = |
| Thread.currentThread().getContextClassLoader().loadClass( "org.slf4j.bridge.SLF4JBridgeHandler" ); |
| |
| // Remove all JUL handlers |
| java.util.logging.LogManager.getLogManager().reset(); |
| |
| // Install slf4j bridge handler |
| final Method method = clazz.getMethod( "install", null ); |
| method.invoke( null ); |
| } |
| catch ( ClassNotFoundException e ) |
| { |
| System.out.println( "WARNING: issue configuring slf4j jul bridge, skip it" ); |
| } |
| } |
| else |
| { |
| System.out.println( "WARNING: loggerName " + loggerName + " not supported, skip it" ); |
| } |
| } |
| |
| private Properties loadProperties( File file ) |
| throws FileNotFoundException, IOException |
| { |
| Properties properties = new Properties(); |
| if ( file.exists() ) |
| { |
| |
| FileInputStream fileInputStream = new FileInputStream( file ); |
| try |
| { |
| properties.load( fileInputStream ); |
| } |
| finally |
| { |
| fileInputStream.close(); |
| } |
| |
| } |
| return properties; |
| } |
| |
| private void saveProperties( Properties properties, File file ) |
| throws FileNotFoundException, IOException |
| { |
| FileOutputStream fileOutputStream = new FileOutputStream( file ); |
| try |
| { |
| properties.store( fileOutputStream, "Timestamp file for executable war/jar" ); |
| } |
| finally |
| { |
| fileOutputStream.close(); |
| } |
| } |
| } |