/************************************************************************* * Copyright 2009-2015 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. * * This file may incorporate work covered under the following copyright * and permission notice: * * Software License Agreement (BSD License) * * Copyright (c) 2008, Regents of the University of California * All rights reserved. * * Redistribution and use of this software in source and binary forms, * with or without modification, are permitted provided that the * following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE * THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL, * COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE, * AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, * SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, * WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION, * REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO * IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT * NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS. ************************************************************************/ package com.eucalyptus.component; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.persistence.EntityTransaction; import javax.persistence.PersistenceException; import com.eucalyptus.auth.principal.UserPrincipal; import com.eucalyptus.bootstrap.Host; import com.eucalyptus.context.Contexts; import com.eucalyptus.context.IllegalContextAccessException; import com.eucalyptus.empyrean.ServiceAccount; import com.eucalyptus.util.Cidr; import com.eucalyptus.util.CollectionUtils; import com.eucalyptus.util.CompatPredicate; import com.eucalyptus.util.NonNullFunction; import org.apache.log4j.Logger; import com.eucalyptus.bootstrap.Hosts; import com.eucalyptus.component.Faults.CheckException; import com.eucalyptus.empyrean.ServiceId; import com.eucalyptus.empyrean.ServiceStatusDetail; import com.eucalyptus.empyrean.ServiceStatusType; import com.eucalyptus.entities.Entities; import com.eucalyptus.records.EventClass; import com.eucalyptus.records.EventRecord; import com.eucalyptus.records.EventType; import com.eucalyptus.util.Exceptions; import com.eucalyptus.util.Internets; import com.eucalyptus.util.LogUtil; import com.eucalyptus.util.TypeMapper; import com.eucalyptus.util.TypeMappers; import com.google.common.base.Function; import com.google.common.base.Functions; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.base.Strings; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.collect.Collections2; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; public class ServiceConfigurations { static Logger LOG = Logger.getLogger( ServiceConfigurations.class ); public static <T extends ServiceConfiguration> List<ServiceConfiguration> list( ) throws PersistenceException { Predicate<ServiceConfiguration> alwaysTrue = Predicates.alwaysTrue(); return Lists.newArrayList( filter( alwaysTrue ) ); } public static <T extends ServiceConfiguration> Iterable<ServiceConfiguration> filter( final Predicate<T> pred ) throws PersistenceException { List<ServiceConfiguration> configs = Lists.newArrayList( ); for ( ComponentId compId : ComponentIds.list( ) ) { Iterables.addAll( configs, filter( compId.getClass( ), pred ) ); } return configs; } private enum DatabaseProvider { INSTANCE; public <T extends ServiceConfiguration> List<T> list( final T example ) { final EntityTransaction db = Entities.get( example.getClass( ) ); List<T> componentList; try { componentList = Entities.query( example ); db.commit( ); return componentList; } catch ( final PersistenceException ex ) { LOG.debug( ex ); db.rollback( ); throw ex; } catch ( final Throwable ex ) { LOG.debug( ex ); db.rollback( ); throw new PersistenceException( "Service configuration lookup failed for: " + LogUtil.dumpObject( example ), ex ); } } public <T extends ServiceConfiguration> T lookup( final T example ) { final EntityTransaction db = Entities.get( example ); T existingName = null; try { existingName = Entities.uniqueResult( example ); db.commit( ); return existingName; } catch ( final NoSuchElementException ex ) { db.rollback( ); throw ex; } catch ( final PersistenceException ex ) { LOG.debug( ex ); db.rollback( ); throw ex; } catch ( final Throwable ex ) { LOG.debug( ex ); db.rollback( ); throw new PersistenceException( "Service configuration lookup failed for: " + LogUtil.dumpObject( example ), ex ); } } public <T extends ServiceConfiguration> T store( T config ) { final EntityTransaction db = Entities.get( config.getClass( ) ); try { config = Entities.mergeDirect( config ); db.commit( ); EventRecord.here( ServiceConfigurations.class, EventClass.COMPONENT, EventType.COMPONENT_REGISTERED, config.toString( ) ).info( ); } catch ( final PersistenceException ex ) { LOG.debug( ex ); EventRecord.here( ServiceConfigurations.class, EventClass.COMPONENT, EventType.COMPONENT_REGISTERED, "FAILED", config.toString( ) ).error( ); db.rollback( ); throw ex; } catch ( final Throwable ex ) { LOG.debug( ex ); EventRecord.here( ServiceConfigurations.class, EventClass.COMPONENT, EventType.COMPONENT_REGISTERED, "FAILED", config.toString( ) ).error( ); db.rollback( ); throw new PersistenceException( "Service configuration storing failed for: " + LogUtil.dumpObject( config ), ex ); } return config; } public <T extends ServiceConfiguration> T remove( final T config ) { final EntityTransaction db = Entities.get( config.getClass( ) ); try { final T searchConfig = ( T ) config.getClass( ).newInstance( ); searchConfig.setName( config.getName( ) ); final T exists = Entities.uniqueResult( searchConfig ); Entities.delete( exists ); db.commit( ); EventRecord.here( ServiceConfigurations.class, EventClass.COMPONENT, EventType.COMPONENT_DEREGISTERED, config.toString( ) ).info( ); } catch ( final NoSuchElementException ex ) { db.rollback( ); } catch ( final PersistenceException ex ) { LOG.debug( ex ); EventRecord.here( ServiceConfigurations.class, EventClass.COMPONENT, EventType.COMPONENT_DEREGISTERED, "FAILED", config.toString( ) ).error( ); db.rollback( ); throw ex; } catch ( final Throwable ex ) { LOG.debug( ex ); EventRecord.here( ServiceConfigurations.class, EventClass.COMPONENT, EventType.COMPONENT_DEREGISTERED, "FAILED", config.toString( ) ).error( ); db.rollback( ); throw new PersistenceException( "Service configuration removal failed for: " + LogUtil.dumpObject( config ), ex ); } return config; } } public static Function<ServiceConfiguration, ServiceStatusType> asServiceStatus( ) { return asServiceStatus( false, false ); } public static enum ServiceConfigurationToServiceAccounts implements Function<ServiceConfiguration, ArrayList<ServiceAccount>> { INSTANCE; public ArrayList<ServiceAccount> apply(ServiceConfiguration conf) { if(conf.getComponentId().getPublicComponentAccounts().isPresent()) { return Lists.newArrayList(Iterables.transform(conf.getComponentId().getPublicComponentAccounts().get(), new Function<UserPrincipal, ServiceAccount>() { @Nullable @Override public ServiceAccount apply(@Nullable UserPrincipal userPrincipal) { if(userPrincipal != null) { try { return new ServiceAccount(userPrincipal.getAccountAlias(), userPrincipal.getAccountNumber(), userPrincipal.getCanonicalId()); } catch(Exception e) { LOG.warn("Exception looking up account info for system account number: " + userPrincipal.getAccountNumber(), e); return null; } } else { return null; } } })); } else { return null; } } } public static Function<ServiceConfiguration, ServiceStatusType> asServiceStatus( final boolean showEvents, final boolean showEventStacks ) { return new Function<ServiceConfiguration, ServiceStatusType>( ) { @Override public ServiceStatusType apply( final ServiceConfiguration config ) { return new ServiceStatusType( ) { /** * */ private static final long serialVersionUID = 1L; { this.setServiceId( TypeMappers.transform( config, ServiceId.class ) ); this.setLocalEpoch( Topology.epoch( ) ); try { this.setLocalState( config.lookupState( ).toString( ) ); } catch ( final Exception ex ) { this.setLocalState( "n/a: " + ex.getMessage( ) ); } if ( showEvents ) { this.getStatusDetails( ).addAll( Collections2.transform( Faults.lookup( config ), TypeMappers.lookup( CheckException.class, ServiceStatusDetail.class ) ) ); if ( !showEventStacks ) { for ( final ServiceStatusDetail a : this.getStatusDetails( ) ) { a.setStackTrace( "" ); } } } //Populate the system accounts try { List<ServiceAccount> accnts = ServiceConfigurationToServiceAccounts.INSTANCE.apply(config); if(accnts != null && accnts.size() > 0) { this.getServiceAccounts().addAll(accnts); } } catch (Exception e) { LOG.warn("Failed finding service account for service: " + config.getName(), e); } } }; } }; } @TypeMapper enum ServiceConfigurationToStatus implements Function<ServiceConfiguration, ServiceStatusType> { INSTANCE; @Override public ServiceStatusType apply( final ServiceConfiguration config ) { return new ServiceStatusType( ) { { this.setServiceId( TypeMappers.transform( config, ServiceId.class ) ); this.setLocalEpoch( Topology.epoch( ) ); if ( config.isVmLocal( ) && Faults.isFailstop( ) ) { this.setLocalState( Component.State.NOTREADY.name( ) ); } else { try { this.setLocalState( config.lookupState( ).toString( ) ); } catch ( final Exception ex ) { this.setLocalState( "n/a: " + ex.getMessage( ) ); } } this.getStatusDetails( ).addAll( Collections2.transform( Faults.lookup( config ), TypeMappers.lookup( CheckException.class, ServiceStatusDetail.class ) ) ); for ( final ServiceStatusDetail a : this.getStatusDetails( ) ) { a.setStackTrace( "" ); } } }; } }; @TypeMapper public enum ServiceIdToServiceStatus implements Function<ServiceId, ServiceStatusType> { INSTANCE; private final Function<ServiceId, ServiceStatusType> transform = Functions.compose( ServiceConfigurationToStatus.INSTANCE, ServiceIdToServiceConfiguration.INSTANCE ); @Override public ServiceStatusType apply( ServiceId input ) { return transform.apply( input ); } } @TypeMapper public enum ServiceIdToServiceConfiguration implements Function<ServiceId, ServiceConfiguration> { INSTANCE; @Override public ServiceConfiguration apply( final ServiceId arg0 ) { Component comp = null; try { comp = Components.lookup( arg0.getType( ) ); try { return comp.lookup( arg0.getName( ) ); } catch ( final NoSuchElementException ex1 ) { final ServiceBuilder<? extends ServiceConfiguration> builder = ServiceBuilders.lookup( comp.getComponentId( ) ); try { final URI uri = new URI( arg0.getUri( ) ); ServiceConfiguration config = builder.newInstance( arg0.getPartition( ), arg0.getName( ), uri.getHost( ), uri.getPort( ) ); comp.setup( config ); return config; } catch ( final URISyntaxException ex ) { LOG.error( ex, ex ); throw Exceptions.toUndeclared( ex ); } } } catch ( NoSuchElementException ex2 ) {//gracefully handle case where an as-yet unknown component type is referenced ComponentId compId = ComponentIds.createEphemeral( arg0.getType( ) ); try { comp = Components.create( compId ); return comp.lookup( arg0.getName( ) ); } catch ( Exception ex ) { try { return ServiceConfigurations.createEphemeral( compId, arg0.getPartition( ), arg0.getName( ), new URI( arg0.getUri( ) ) ); } catch ( URISyntaxException ex1 ) { LOG.error( ex1 ); throw Exceptions.toUndeclared( ex1 ); } } } } } @TypeMapper public enum ServiceConfigurationToServiceId implements Function<ServiceConfiguration, ServiceId> { INSTANCE; private static final Function<InetAddress,Cidr> cidrLookup = CacheBuilder.newBuilder() .maximumSize( 64 ) .expireAfterWrite( 1, TimeUnit.MINUTES ) .build( CacheLoader.from( Functions.compose( CollectionUtils.optionalOr( Cidr.of( 0, 0 ) ), Internets.interfaceCidr() ) ) ); @Override public ServiceId apply( final ServiceConfiguration config ) { return new ServiceId( ) { /** * */ private static final long serialVersionUID = 1L; { this.setPartition( config.getPartition() ); this.setName( config.getName() ); this.setType( config.getComponentId( ).name( ) ); this.setFullName( config.getFullName().toString() ); if ( config.isVmLocal( ) ) { this.setServiceUri(ServiceUris.remote(config.getComponentId(), maphost(Internets.localHostInetAddress()))); } else { this.setServiceUri(ServiceUris.remote(config.getComponentId(), maphost(config.getInetAddress()), config.getPort())); } } }; } @SuppressWarnings( "ConstantConditions" ) private static InetAddress maphost( final InetAddress hostAddress ) { InetAddress result = hostAddress; try { final SocketAddress address = Contexts.lookup( ).getChannel( ).getLocalAddress( ); if ( address instanceof InetSocketAddress ) { final Cidr cidr = cidrLookup.apply( ((InetSocketAddress)address).getAddress( ) ); if ( !cidr.apply( result ) ) { final Host host = Hosts.lookup( hostAddress ); if ( host != null ) { result = Iterables.tryFind( host.getHostAddresses( ), cidr ).or( result ); } } } } catch ( IllegalContextAccessException e ) { // do not map } return result; } } public static ServiceConfiguration createEphemeral( final ComponentId compId, final String partition, final String name, final URI remoteUri ) { return new EphemeralConfiguration( compId, partition, name, remoteUri ); } public static ServiceConfiguration createEphemeral( final ComponentId compId ) { return createEphemeral( compId, Internets.localHostInetAddress( ) ); } public static ServiceConfiguration createEphemeral( final ComponentId compId, final InetAddress host ) { return new EphemeralConfiguration( compId, compId.getPartition( ), host.getHostAddress( ), ServiceUris.remote( compId, host ) ); } public static ServiceConfiguration createEphemeral( final Component component, final InetAddress host ) { return createEphemeral( component.getComponentId( ), host ); } public static ServiceConfiguration createBogus( final Class<? extends ComponentId> compIdClass, final Class<?> ownerType ) { ComponentId compId = ComponentIds.lookup( compIdClass ); return new EphemeralConfiguration( compId, compId.getPartition( ), ownerType.getSimpleName( ), ServiceUris.internal( compId, Internets.localHostInetAddress( ), ownerType.getSimpleName( ) ) ); } public static ServiceConfiguration createBogus( final ServiceConfiguration serviceConfiguration, final Class<?> ownerType ) { final ComponentId compId = serviceConfiguration.getComponentId(); return new EphemeralConfiguration( compId, compId.getPartition( ), ownerType.getSimpleName( ) + "-" + serviceConfiguration.getHostName( ) + ( serviceConfiguration.getHostName( ).equals( serviceConfiguration.getName( ) ) ? "" : "-" + serviceConfiguration.getName( ) ), ServiceUris.internal( compId, Internets.localHostInetAddress( ), ownerType.getSimpleName( ) ) ); } public static <T extends ServiceConfiguration, C extends ComponentId> Iterable<T> filter( final C componentId, final Predicate<T> pred ) throws PersistenceException { return filter( componentId.getClass( ), pred ); } public static <T extends ServiceConfiguration, C extends ComponentId> Iterable<T> filter( final Class<C> type, final Predicate<T> pred ) throws PersistenceException { List<T> list = ServiceConfigurations.list( type ); return Iterables.filter( list, pred ); } public static <T extends ServiceConfiguration, C extends ComponentId> List<T> list( final Class<C> type ) throws PersistenceException { if ( !ComponentId.class.isAssignableFrom( type ) ) { throw new PersistenceException( "Unknown configuration type passed: " + type.getCanonicalName( ) ); } else { final T example = ( T ) ServiceBuilders.lookup( type ).newInstance( ); return ServiceConfigurations.list( example ); } } public static <T extends ServiceConfiguration, C extends ComponentId> List<T> listPartition( final Class<C> type, final String partition ) throws PersistenceException, NoSuchElementException { if ( !ComponentId.class.isAssignableFrom( type ) ) { throw new PersistenceException( "Unknown configuration type passed: " + type.getCanonicalName( ) ); } final T example = ( T ) ServiceBuilders.lookup( type ).newInstance( ); example.setPartition( partition ); return list( example ); } public static <T extends ServiceConfiguration> T lookupByName( final String name ) { for ( ComponentId c : ComponentIds.list( ) ) { ServiceConfiguration example = ServiceBuilders.lookup( c.getClass( ) ).newInstance( ); if ( example instanceof EphemeralConfiguration ) continue; example.setName( name ); try { return ( T ) lookup( example ); } catch ( Exception ex ) {} } throw new NoSuchElementException( "Failed to lookup any registered component with the name: " + name ); } public static <T extends ServiceConfiguration, C extends ComponentId> T lookupByName( final Class<C> type, final String name ) { if ( !ComponentId.class.isAssignableFrom( type ) ) { throw new PersistenceException( "Unknown configuration type passed: " + type.getCanonicalName( ) ); } final T example = ( T ) ServiceBuilders.lookup( type ).newInstance( ); example.setName( name ); return lookup( example ); } public static <T extends ServiceConfiguration, C extends ComponentId> T lookupByHost( final Class<C> type, final String host ) { if ( !ComponentId.class.isAssignableFrom( type ) ) { throw new PersistenceException( "Unknown configuration type passed: " + type.getCanonicalName( ) ); } final T example = ( T ) ServiceBuilders.lookup( type ).newInstance( ); example.setHostName( host ); return lookup( example ); } public static <T extends ServiceConfiguration, C extends ComponentId> T lookupByAliasHost( final Class<C> type, final String host ) { if ( !ComponentId.class.isAssignableFrom( type ) ) { throw new PersistenceException( "Unknown configuration type passed: " + type.getCanonicalName( ) ); } final T example = ( T ) ServiceBuilders.lookup( type ).newInstance( ); example.setHostName( host ); return lookup( example ); } public static <T extends ServiceConfiguration> List<T> list( final T type ) { return DatabaseProvider.INSTANCE.list( type ); } public static <T extends ServiceConfiguration> T store( final T t ) { return DatabaseProvider.INSTANCE.store( t ); } public static <T extends ServiceConfiguration> T remove( final T t ) { return DatabaseProvider.INSTANCE.remove( t ); } public static <T extends ServiceConfiguration> T lookup( final T type ) { return DatabaseProvider.INSTANCE.lookup( type ); } static void update( final ServiceConfiguration destination, final ServiceConfiguration source ) { update( destination, source.getHostName( ), source.getPort( ) ); } static void update( final ServiceConfiguration configuration, final String host, final Integer port ) { configuration.setHostName( host ); configuration.setPort( port ); } enum ServiceIsHostLocal implements CompatPredicate<ServiceConfiguration> { INSTANCE; @Override public boolean apply( ServiceConfiguration input ) { return Hosts.isServiceLocal( input ); } } enum ServiceIsVmLocal implements CompatPredicate<ServiceConfiguration> { INSTANCE; @Override public boolean apply( ServiceConfiguration input ) { return input!=null && input.isVmLocal( ); } } enum EnabledServiceConfiguration implements CompatPredicate<ServiceConfiguration> { INSTANCE; @Override public boolean apply( final ServiceConfiguration arg0 ) { return Component.State.ENABLED.equals( arg0.lookupState( ) ); } }; @SuppressWarnings( "unchecked" ) public static final <T extends ServiceConfiguration> CompatPredicate<T> filterEnabled( ) { return ( CompatPredicate<T> ) EnabledServiceConfiguration.INSTANCE; } public static CompatPredicate<ServiceConfiguration> filterHostLocal( ) { return ServiceIsHostLocal.INSTANCE; } public static CompatPredicate<ServiceConfiguration> filterVmLocal( ) { return ServiceIsVmLocal.INSTANCE; } /** * Filter for enabled services in the specified partition. * @param partition * @return */ public static CompatPredicate<ServiceConfiguration> filterEnabledByPartition( final Partition partition ) { return new CompatPredicate<ServiceConfiguration>( ) { @Override public boolean apply( ServiceConfiguration arg0 ) { return partition.getName( ).equals( arg0.getPartition( ) ) && Component.State.ENABLED.equals( arg0.lookupState( ) ); } }; } enum ServiceConfigurationToPublicEndpoint implements NonNullFunction<ServiceConfiguration,String> { INSTANCE; @Nonnull @Override public String apply( final ServiceConfiguration serviceConfiguration ) { return ServiceUris.remotePublicify( serviceConfiguration ).toASCIIString( ); } } public static NonNullFunction<ServiceConfiguration,String> remotePublicify( ) { return ServiceConfigurationToPublicEndpoint.INSTANCE; } enum ServiceConfigurationToComponentId implements NonNullFunction<ServiceConfiguration,ComponentId> { INSTANCE; @Nonnull @Override public ComponentId apply( final ServiceConfiguration serviceConfiguration ) { return serviceConfiguration.getComponentId( ); } } public static NonNullFunction<ServiceConfiguration,ComponentId> componentId( ) { return ServiceConfigurationToComponentId.INSTANCE; } @TypeMapper public enum CheckExceptionRecordMapper implements Function<CheckException, ServiceStatusDetail> { INSTANCE; @Override public ServiceStatusDetail apply( final CheckException input ) { ServiceConfiguration config = null; final String serviceFullName = Strings.nullToEmpty( input.getServiceFullName() ); String checkName = Strings.nullToEmpty(input.getServiceName()); try { config = ServiceConfigurations.lookupByName( checkName ); if (!serviceFullName.equals( config.getFullName().toString() )) { //NOTE: throwing this here means we will do the full search in the catch, // but fall back to config as set here if nothing better is found. throw Exceptions.toUndeclared("Mismatched service fullnames, do full component service search" ); } } catch ( RuntimeException e ) { for ( Component c : Components.list( ) ) { for ( ServiceConfiguration s : c.services() ) { if ( serviceFullName.equals( s.getFullName().toString() ) ) { config = s; checkName = s.getName(); break; } } } if(config==null){ throw e; } } final String serviceName = checkName; final ServiceConfiguration finalConfig = config; return new ServiceStatusDetail( ) { { this.setSeverity( input.getSeverity( ).toString( ) ); this.setUuid( input.getCorrelationId( ) ); this.setTimestamp( input.getTimestamp( ).toString( ) ); this.setMessage( input.getMessage( ) != null ? input.getMessage( ) : "No summary information available." ); this.setStackTrace( input.getStackString( ) != null ? input.getStackString( ) : Exceptions.string( new RuntimeException( "Error while mapping service event record: No stack information available" ) ) ); this.setServiceFullName( finalConfig.getFullName().toString( ) ); this.setServiceHost( finalConfig.getHostName() ); this.setServiceName( serviceName ); } }; } } }