| /* |
| * 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. |
| */ |
| package org.qi4j.library.fileconfig; |
| |
| import java.io.File; |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.ResourceBundle; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| import org.qi4j.api.activation.ActivatorAdapter; |
| import org.qi4j.api.activation.Activators; |
| import org.qi4j.api.injection.scope.Structure; |
| import org.qi4j.api.injection.scope.This; |
| import org.qi4j.api.injection.scope.Uses; |
| import org.qi4j.api.mixin.Mixins; |
| import org.qi4j.api.property.Property; |
| import org.qi4j.api.service.ServiceComposite; |
| import org.qi4j.api.service.ServiceDescriptor; |
| import org.qi4j.api.service.ServiceReference; |
| import org.qi4j.api.structure.Application; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| @Mixins( FileConfigurationService.Mixin.class ) |
| @Activators( FileConfigurationService.Activator.class ) |
| public interface FileConfigurationService |
| extends FileConfiguration, ServiceComposite |
| { |
| |
| void resolveFileConfiguration(); |
| |
| public static class Activator |
| extends ActivatorAdapter<ServiceReference<FileConfigurationService>> |
| { |
| |
| @Override |
| public void afterActivation( ServiceReference<FileConfigurationService> activated ) |
| throws Exception |
| { |
| activated.get().resolveFileConfiguration(); |
| } |
| |
| } |
| |
| interface Data |
| { |
| |
| Property<OS> os(); |
| |
| Property<String> application(); |
| |
| Property<File> user(); |
| |
| Property<File> configuration(); |
| |
| Property<File> data(); |
| |
| Property<File> temporary(); |
| |
| Property<File> cache(); |
| |
| Property<File> log(); |
| |
| } |
| |
| abstract class Mixin |
| implements FileConfigurationService |
| { |
| |
| final Logger logger = LoggerFactory.getLogger( getClass().getName() ); |
| |
| @This |
| Data data; |
| |
| @Uses |
| ServiceDescriptor descriptor; |
| |
| @Structure |
| Application app; |
| |
| @Override |
| public void resolveFileConfiguration() |
| { |
| OS os = detectOS(); |
| |
| data.os().set( os ); |
| logger.info( "Operating system : " + os.name() ); |
| |
| // Get bundle with application name and configured directories |
| ResourceBundle bundle = ResourceBundle.getBundle( FileConfiguration.class.getName(), new Locale( os.name() ) ); |
| |
| Map arguments = getArguments( os ); |
| |
| data.configuration().set( new File( format( bundle.getString( "configuration" ), arguments ) ) ); |
| data.data().set( new File( format( bundle.getString( "data" ), arguments ) ) ); |
| data.temporary().set( new File( format( bundle.getString( "temporary" ), arguments ) ) ); |
| data.cache().set( new File( format( bundle.getString( "cache" ), arguments ) ) ); |
| data.log().set( new File( format( bundle.getString( "log" ), arguments ) ) ); |
| |
| applyOverride(); |
| autoCreateDirectories(); |
| } |
| |
| private Map getArguments( OS os ) |
| { |
| // Get user directory |
| String user = System.getenv( "USERPROFILE" ); // On Windows we use this instead of user.home |
| if ( user == null ) { |
| user = System.getProperty( "user.home" ); |
| } |
| |
| data.user().set( new File( user ) ); |
| |
| // Set application name. This is taken from the Zest application but can be overriden by a system property |
| String application = System.getProperty( "application", app.name() ); |
| |
| if ( !app.mode().equals( Application.Mode.production ) ) { |
| application += "-" + app.mode().name(); |
| } |
| |
| data.application().set( application ); |
| |
| // Temp dir |
| String temp = System.getProperty( "java.io.tmpdir" ); |
| if ( temp.endsWith( "/" ) ) { |
| temp = temp.substring( 0, temp.length() - 1 ); |
| } |
| |
| // Arguments available to use in directory specifications |
| Map<String, String> arguments = new HashMap<String, String>(); |
| arguments.put( "application", application ); |
| arguments.put( "user", user ); |
| arguments.put( "os", os.name() ); |
| arguments.put( "temp", temp ); |
| |
| // Add environment variables |
| for ( Map.Entry<String, String> envVariable : System.getenv().entrySet() ) { |
| arguments.put( "environment." + envVariable.getKey(), envVariable.getValue() ); |
| } |
| // Add system properties |
| for ( Map.Entry<Object, Object> envVariable : System.getProperties().entrySet() ) { |
| arguments.put( "system." + envVariable.getKey(), envVariable.getValue().toString() ); |
| } |
| |
| return arguments; |
| } |
| |
| private void applyOverride() |
| { |
| FileConfigurationOverride override = descriptor.metaInfo( FileConfigurationOverride.class ); |
| if ( override != null ) { |
| if ( override.configuration() != null ) { |
| data.configuration().set( override.configuration() ); |
| } |
| if ( override.data() != null ) { |
| data.data().set( override.data() ); |
| } |
| if ( override.temporary() != null ) { |
| data.temporary().set( override.temporary() ); |
| } |
| if ( override.cache() != null ) { |
| data.cache().set( override.cache() ); |
| } |
| if ( override.log() != null ) { |
| data.log().set( override.log() ); |
| } |
| } |
| } |
| |
| @Override |
| public OS os() |
| { |
| return data.os().get(); |
| } |
| |
| @Override |
| public File user() |
| { |
| return data.user().get(); |
| } |
| |
| @Override |
| public File configurationDirectory() |
| { |
| return data.configuration().get(); |
| } |
| |
| @Override |
| public File dataDirectory() |
| { |
| return data.data().get(); |
| } |
| |
| @Override |
| public File temporaryDirectory() |
| { |
| return data.temporary().get(); |
| } |
| |
| @Override |
| public File cacheDirectory() |
| { |
| return data.cache().get(); |
| } |
| |
| @Override |
| public File logDirectory() |
| { |
| return data.log().get(); |
| } |
| |
| private OS detectOS() |
| { |
| String osName = System.getProperty( "os.name" ).toLowerCase(); |
| OS os; |
| if ( osName.indexOf( "win" ) != -1 ) { |
| os = OS.windows; |
| } else if ( osName.indexOf( "mac" ) != -1 ) { |
| os = OS.mac; |
| } else { |
| os = OS.unix; |
| } |
| return os; |
| } |
| |
| private void autoCreateDirectories() |
| { |
| // Create directories |
| if ( !configurationDirectory().exists() && !configurationDirectory().mkdirs() ) { |
| throw new IllegalStateException( "Could not create configuration directory(" + configurationDirectory() + ")" ); |
| } |
| if ( !dataDirectory().exists() && !dataDirectory().mkdirs() ) { |
| throw new IllegalStateException( "Could not create data directory(" + dataDirectory() + ")" ); |
| } |
| if ( !temporaryDirectory().exists() && !temporaryDirectory().mkdirs() ) { |
| throw new IllegalStateException( "Could not create temporary directory(" + temporaryDirectory() + ")" ); |
| } |
| if ( !cacheDirectory().exists() && !cacheDirectory().mkdirs() ) { |
| throw new IllegalStateException( "Could not create cache directory(" + cacheDirectory() + ")" ); |
| } |
| if ( !logDirectory().exists() && !logDirectory().mkdirs() ) { |
| throw new IllegalStateException( "Could not create log directory(" + logDirectory() + ")" ); |
| } |
| } |
| |
| private String format( String configuration, Map arguments ) |
| { |
| Pattern paramPattern = Pattern.compile( "\\{(.*?)\\}" ); |
| |
| Matcher matcher = paramPattern.matcher( configuration ); |
| |
| StringBuilder buffer = new StringBuilder(); |
| int lastEnd = 0; |
| while ( matcher.find() ) { |
| buffer.append( configuration.substring( lastEnd, matcher.start() ) ); |
| lastEnd = matcher.end(); |
| |
| String var = matcher.group( 1 ); |
| Object value = arguments.get( var ); |
| |
| if ( value != null ) { |
| buffer.append( format( value.toString(), arguments ) ); |
| } else { |
| throw new IllegalArgumentException( "Illegal file configuration parameter:" + var ); |
| } |
| } |
| buffer.append( configuration.substring( lastEnd ) ); |
| |
| return buffer.toString(); |
| } |
| |
| } |
| |
| } |