/************************************************************************* * 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.autoscaling.common; import java.util.Set; import javax.annotation.Nullable; 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; /** * Represents an Auto Scaling specific Amazon Resource Name (ARN) * * arn:aws:<service>:<region>:<namespace>:<relative-id> */ public class AutoScalingResourceName { private static final String prefix = "arn:aws:"; private static final Splitter nameSpliter = Splitter.on(':'); 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_ID_UUID = 6; private static final int PART_RELATIVE_NAME_1 = 7; private static final int PART_RELATIVE_NAME_2 = 8; 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 uuid; private final String name1; @Nullable private final String name2; public enum Type { launchConfiguration( "launch configuration", false ), autoScalingGroup( "auto scaling group", false ), scalingPolicy( "scaling policy", true ); private final String description; private final boolean scoped; private Type( final String description, final boolean scoped ) { this.description = description; this.scoped = scoped; } public String describe() { return description; } public boolean isScoped() { return scoped; } } public AutoScalingResourceName( final String resourceName, final String service, final String namespace, final String type, final String uuid, final String name1, @Nullable final String name2 ) { this.resourceName = resourceName; this.service = service; this.namespace = namespace; this.type = type; this.uuid = uuid; this.name1 = toValue( name1 ); this.name2 = toValue( name2 ); } public static AutoScalingResourceName parse( final String resourceName ) throws InvalidResourceNameException { return parse( resourceName, null ); } public static AutoScalingResourceName 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 < 8 || namePartCount > 9 ) { throw new InvalidResourceNameException( resourceName ); } if ( !"autoscaling".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 AutoScalingResourceName( resourceName, Iterables.get( nameParts, PART_SERVICE ), Iterables.get( nameParts, PART_NAMESPACE ), Iterables.get( nameParts, PART_RELATIVE_ID_TYPE ), Iterables.get( nameParts, PART_RELATIVE_ID_UUID ), Iterables.get( nameParts, PART_RELATIVE_NAME_1 ), namePartCount > PART_RELATIVE_NAME_2 ? Iterables.get( nameParts, PART_RELATIVE_NAME_2 ) : null ); } public String getResourceName() { return resourceName; } public String getService() { return service; } public String getNamespace() { return namespace; } public String getType() { return type; } public String getUuid() { return uuid; } public String getScope( final Type type ) { if ( !type.isScoped() ) throw new IllegalStateException( "Type not scoped" ); return name1; } public String getName( final Type type ) { if ( type.isScoped() ) { if ( name2 == null ) throw new InvalidResourceNameException( resourceName ); return name2; } else { return name1; } } 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 Predicate<String> isResourceName() { return ResourceNamePredicate.INSTANCE; } private String toValue( final String name ) { String value = null; if ( name != null ) { int slashIndex = name.indexOf( '/' ); if ( slashIndex <= 0 || slashIndex == name.length() - 1 ) { throw new InvalidResourceNameException( resourceName ); } value = name.substring( slashIndex + 1 ); } return value; } 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 ); } } }