/************************************************************************* * Copyright 2009-2013 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. ************************************************************************/ package com.eucalyptus.cloudwatch.common; import java.util.Set; import javax.annotation.Nullable; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; /** * */ public class CloudWatchResourceName { private static final int MIN_PARTS = 7; private static final int MAX_PARTS = 7; private static final String prefix = "arn:aws:"; private static final Splitter nameSpliter = Splitter.on(':').limit(MAX_PARTS); private static final int PART_SERVICE = 2; private static final int PART_NAMESPACE = 4; private static final int PART_RELATIVE_ID_TYPE = 5; private static final int PART_RELATIVE_NAME = 6; private final String resourceName; private final String service; private final String namespace; // account number if you don't speak ARN private final String type; private final String name; public enum Type { alarm( "alarm" ), ; private final String description; private Type( final String description ) { this.description = description; } public String describe() { return description; } } public CloudWatchResourceName( final String resourceName, final String service, final String namespace, final String type, final String name ) { this.resourceName = resourceName; this.service = service; this.namespace = namespace; this.type = type; this.name = name; } public static CloudWatchResourceName parse( final String resourceName ) throws InvalidResourceNameException { return parse( resourceName, null ); } public static CloudWatchResourceName parse( final String resourceName, @Nullable final Type type ) throws InvalidResourceNameException { if( !resourceName.startsWith( prefix ) ) { throw new InvalidResourceNameException( resourceName ); } final Iterable<String> nameParts = nameSpliter.split( resourceName ); final int namePartCount = Iterables.size( nameParts ); if ( namePartCount < MIN_PARTS || namePartCount > MAX_PARTS ) { throw new InvalidResourceNameException( resourceName ); } if ( !"cloudwatch".equals( Iterables.get( nameParts, PART_SERVICE ) ) ) { throw new InvalidResourceNameException( resourceName ); } if ( type != null && !type.name().equals( Iterables.get( nameParts, PART_RELATIVE_ID_TYPE ) ) ) { throw new InvalidResourceNameException( resourceName ); } return new CloudWatchResourceName( resourceName, Iterables.get( nameParts, PART_SERVICE ), Iterables.get( nameParts, PART_NAMESPACE ), Iterables.get( nameParts, PART_RELATIVE_ID_TYPE ), Iterables.get( nameParts, PART_RELATIVE_NAME ) ); } public String getResourceName() { return resourceName; } public String getService() { return service; } public String getNamespace() { return namespace; } public String getType() { return type; } public String getName() { return name; } public String toString() { return resourceName; } public static Set<String> simpleNames( final Iterable<String> namesAndArns ) { return Sets.newHashSet( Iterables.filter( namesAndArns, Predicates.not( isResourceName() ) ) ); } public static Set<String> arns( final Iterable<String> namesAndArns ) { return Sets.newHashSet( Iterables.filter( namesAndArns, isResourceName() ) ); } public static Function<String,Optional<CloudWatchResourceName>> asArnOfType( final Type type ) { return new Function<String,Optional<CloudWatchResourceName>>() { @Override public Optional<CloudWatchResourceName> apply( final String value ) { Optional<CloudWatchResourceName> name = Optional.absent( ); if ( isResourceName().apply( value ) ) try { name = Optional.of( parse( value, type ) ); } catch ( InvalidResourceNameException e ) { // absent } return name; } }; } public static Predicate<String> isResourceName() { return ResourceNamePredicate.INSTANCE; } public static Function<CloudWatchResourceName,String> toName() { return StringProperties.NAME; } public static Function<CloudWatchResourceName,String> toNamespace() { return StringProperties.NAMESPACE; } private enum StringProperties implements Function<CloudWatchResourceName,String> { NAME { @Override public String apply( @Nullable final CloudWatchResourceName input ) { return input == null ? null : input.getName( ); } }, NAMESPACE { @Override public String apply( @Nullable final CloudWatchResourceName input ) { return input == null ? null : input.getNamespace( ); } } } private enum ResourceNamePredicate implements Predicate<String> { INSTANCE; @Override public boolean apply( final String value ) { return value != null && value.startsWith( prefix ); } } public static final class InvalidResourceNameException extends RuntimeException { private static final long serialVersionUID = 1L; public InvalidResourceNameException( final String resourceName ) { super( "Invalid resource name: " + resourceName ); } } }