001package org.apache.maven.execution.scope.internal; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.LinkedList; 023import java.util.Map; 024 025import javax.inject.Named; 026import javax.inject.Singleton; 027 028import org.apache.maven.execution.MojoExecutionEvent; 029import org.apache.maven.execution.MojoExecutionListener; 030import org.apache.maven.execution.scope.MojoExecutionScoped; 031import org.apache.maven.execution.scope.WeakMojoExecutionListener; 032import org.apache.maven.plugin.MojoExecution; 033import org.apache.maven.plugin.MojoExecutionException; 034import org.apache.maven.project.MavenProject; 035import org.codehaus.plexus.PlexusContainer; 036import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 037 038import com.google.common.collect.Maps; 039import com.google.inject.AbstractModule; 040import com.google.inject.Key; 041import com.google.inject.Module; 042import com.google.inject.OutOfScopeException; 043import com.google.inject.Provider; 044import com.google.inject.Scope; 045import com.google.inject.util.Providers; 046 047@Named 048@Singleton 049public class MojoExecutionScope 050 implements Scope, MojoExecutionListener 051{ 052 private static final Provider<Object> SEEDED_KEY_PROVIDER = new Provider<Object>() 053 { 054 public Object get() 055 { 056 throw new IllegalStateException(); 057 } 058 }; 059 060 private static final class ScopeState 061 { 062 public final Map<Key<?>, Provider<?>> seeded = Maps.newHashMap(); 063 064 public final Map<Key<?>, Object> provided = Maps.newHashMap(); 065 } 066 067 private final ThreadLocal<LinkedList<ScopeState>> values = new ThreadLocal<LinkedList<ScopeState>>(); 068 069 public MojoExecutionScope() 070 { 071 } 072 073 public void enter() 074 { 075 LinkedList<ScopeState> stack = values.get(); 076 if ( stack == null ) 077 { 078 stack = new LinkedList<ScopeState>(); 079 values.set( stack ); 080 } 081 stack.addFirst( new ScopeState() ); 082 } 083 084 private ScopeState getScopeState() 085 { 086 LinkedList<ScopeState> stack = values.get(); 087 if ( stack == null || stack.isEmpty() ) 088 { 089 throw new IllegalStateException(); 090 } 091 return stack.getFirst(); 092 } 093 094 public void exit() 095 throws MojoExecutionException 096 { 097 final LinkedList<ScopeState> stack = values.get(); 098 if ( stack == null || stack.isEmpty() ) 099 { 100 throw new IllegalStateException(); 101 } 102 stack.removeFirst(); 103 if ( stack.isEmpty() ) 104 { 105 values.remove(); 106 } 107 } 108 109 public <T> void seed( Class<T> clazz, Provider<T> value ) 110 { 111 getScopeState().seeded.put( Key.get( clazz ), value ); 112 } 113 114 public <T> void seed( Class<T> clazz, final T value ) 115 { 116 getScopeState().seeded.put( Key.get( clazz ), Providers.of( value ) ); 117 } 118 119 public <T> Provider<T> scope( final Key<T> key, final Provider<T> unscoped ) 120 { 121 return new Provider<T>() 122 { 123 @SuppressWarnings( "unchecked" ) 124 public T get() 125 { 126 LinkedList<ScopeState> stack = values.get(); 127 if ( stack == null || stack.isEmpty() ) 128 { 129 throw new OutOfScopeException( "Cannot access " + key + " outside of a scoping block" ); 130 } 131 132 ScopeState state = stack.getFirst(); 133 134 Provider<?> seeded = state.seeded.get( key ); 135 136 if ( seeded != null ) 137 { 138 return (T) seeded.get(); 139 } 140 141 T provided = (T) state.provided.get( key ); 142 if ( provided == null && unscoped != null ) 143 { 144 provided = unscoped.get(); 145 state.provided.put( key, provided ); 146 } 147 148 return provided; 149 } 150 }; 151 } 152 153 @SuppressWarnings( { "unchecked" } ) 154 public static <T> Provider<T> seededKeyProvider() 155 { 156 return (Provider<T>) SEEDED_KEY_PROVIDER; 157 } 158 159 public static Module getScopeModule( PlexusContainer container ) 160 throws ComponentLookupException 161 { 162 final MojoExecutionScope scope = container.lookup( MojoExecutionScope.class ); 163 return new AbstractModule() 164 { 165 @Override 166 protected void configure() 167 { 168 bindScope( MojoExecutionScoped.class, scope ); 169 170 // standard scope bindings 171 bind( MavenProject.class ).toProvider( MojoExecutionScope.<MavenProject> seededKeyProvider() ).in( scope ); 172 bind( MojoExecution.class ).toProvider( MojoExecutionScope.<MojoExecution> seededKeyProvider() ).in( scope ); 173 } 174 }; 175 } 176 177 public void beforeMojoExecution( MojoExecutionEvent event ) 178 throws MojoExecutionException 179 { 180 for ( Object provided : getScopeState().provided.values() ) 181 { 182 if ( provided instanceof WeakMojoExecutionListener ) 183 { 184 ( (WeakMojoExecutionListener) provided ).beforeMojoExecution( event ); 185 } 186 } 187 } 188 189 public void afterMojoExecutionSuccess( MojoExecutionEvent event ) 190 throws MojoExecutionException 191 { 192 for ( Object provided : getScopeState().provided.values() ) 193 { 194 if ( provided instanceof WeakMojoExecutionListener ) 195 { 196 ( (WeakMojoExecutionListener) provided ).afterMojoExecutionSuccess( event ); 197 } 198 } 199 } 200 201 public void afterExecutionFailure( MojoExecutionEvent event ) 202 { 203 for ( Object provided : getScopeState().provided.values() ) 204 { 205 if ( provided instanceof WeakMojoExecutionListener ) 206 { 207 ( (WeakMojoExecutionListener) provided ).afterExecutionFailure( event ); 208 } 209 } 210 } 211 212}