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.MavenSession; 029import org.apache.maven.execution.MojoExecutionEvent; 030import org.apache.maven.execution.MojoExecutionListener; 031import org.apache.maven.execution.scope.MojoExecutionScoped; 032import org.apache.maven.execution.scope.WeakMojoExecutionListener; 033import org.apache.maven.plugin.MojoExecution; 034import org.apache.maven.plugin.MojoExecutionException; 035import org.apache.maven.project.MavenProject; 036import org.codehaus.plexus.PlexusContainer; 037import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 038 039import com.google.common.collect.Maps; 040import com.google.inject.AbstractModule; 041import com.google.inject.Key; 042import com.google.inject.Module; 043import com.google.inject.OutOfScopeException; 044import com.google.inject.Provider; 045import com.google.inject.Scope; 046import com.google.inject.util.Providers; 047 048@Named 049@Singleton 050public class MojoExecutionScope 051 implements Scope, MojoExecutionListener 052{ 053 private static final Provider<Object> SEEDED_KEY_PROVIDER = new Provider<Object>() 054 { 055 public Object get() 056 { 057 throw new IllegalStateException(); 058 } 059 }; 060 061 private static final class ScopeState 062 { 063 public final Map<Key<?>, Provider<?>> seeded = Maps.newHashMap(); 064 065 public final Map<Key<?>, Object> provided = Maps.newHashMap(); 066 } 067 068 private final ThreadLocal<LinkedList<ScopeState>> values = new ThreadLocal<LinkedList<ScopeState>>(); 069 070 public MojoExecutionScope() 071 { 072 } 073 074 public void enter() 075 { 076 LinkedList<ScopeState> stack = values.get(); 077 if ( stack == null ) 078 { 079 stack = new LinkedList<ScopeState>(); 080 values.set( stack ); 081 } 082 stack.addFirst( new ScopeState() ); 083 } 084 085 private ScopeState getScopeState() 086 { 087 LinkedList<ScopeState> stack = values.get(); 088 if ( stack == null || stack.isEmpty() ) 089 { 090 throw new IllegalStateException(); 091 } 092 return stack.getFirst(); 093 } 094 095 public void exit() 096 throws MojoExecutionException 097 { 098 final LinkedList<ScopeState> stack = values.get(); 099 if ( stack == null || stack.isEmpty() ) 100 { 101 throw new IllegalStateException(); 102 } 103 stack.removeFirst(); 104 if ( stack.isEmpty() ) 105 { 106 values.remove(); 107 } 108 } 109 110 public <T> void seed( Class<T> clazz, Provider<T> value ) 111 { 112 getScopeState().seeded.put( Key.get( clazz ), value ); 113 } 114 115 public <T> void seed( Class<T> clazz, final T value ) 116 { 117 getScopeState().seeded.put( Key.get( clazz ), Providers.of( value ) ); 118 } 119 120 public <T> Provider<T> scope( final Key<T> key, final Provider<T> unscoped ) 121 { 122 return new Provider<T>() 123 { 124 @SuppressWarnings( "unchecked" ) 125 public T get() 126 { 127 LinkedList<ScopeState> stack = values.get(); 128 if ( stack == null || stack.isEmpty() ) 129 { 130 throw new OutOfScopeException( "Cannot access " + key + " outside of a scoping block" ); 131 } 132 133 ScopeState state = stack.getFirst(); 134 135 Provider<?> seeded = state.seeded.get( key ); 136 137 if ( seeded != null ) 138 { 139 return (T) seeded.get(); 140 } 141 142 T provided = (T) state.provided.get( key ); 143 if ( provided == null && unscoped != null ) 144 { 145 provided = unscoped.get(); 146 state.provided.put( key, provided ); 147 } 148 149 return provided; 150 } 151 }; 152 } 153 154 @SuppressWarnings( { "unchecked" } ) 155 public static <T> Provider<T> seededKeyProvider() 156 { 157 return (Provider<T>) SEEDED_KEY_PROVIDER; 158 } 159 160 public static Module getScopeModule( PlexusContainer container ) 161 throws ComponentLookupException 162 { 163 final MojoExecutionScope scope = container.lookup( MojoExecutionScope.class ); 164 return new AbstractModule() 165 { 166 @Override 167 protected void configure() 168 { 169 bindScope( MojoExecutionScoped.class, scope ); 170 171 // standard scope bindings 172 bind( MavenSession.class ).toProvider( MojoExecutionScope.<MavenSession> seededKeyProvider() ).in( scope ); 173 bind( MavenProject.class ).toProvider( MojoExecutionScope.<MavenProject> seededKeyProvider() ).in( scope ); 174 bind( MojoExecution.class ).toProvider( MojoExecutionScope.<MojoExecution> seededKeyProvider() ).in( scope ); 175 } 176 }; 177 } 178 179 public void beforeMojoExecution( MojoExecutionEvent event ) 180 throws MojoExecutionException 181 { 182 for ( Object provided : getScopeState().provided.values() ) 183 { 184 if ( provided instanceof WeakMojoExecutionListener ) 185 { 186 ( (WeakMojoExecutionListener) provided ).beforeMojoExecution( event ); 187 } 188 } 189 } 190 191 public void afterMojoExecutionSuccess( MojoExecutionEvent event ) 192 throws MojoExecutionException 193 { 194 for ( Object provided : getScopeState().provided.values() ) 195 { 196 if ( provided instanceof WeakMojoExecutionListener ) 197 { 198 ( (WeakMojoExecutionListener) provided ).afterMojoExecutionSuccess( event ); 199 } 200 } 201 } 202 203 public void afterExecutionFailure( MojoExecutionEvent event ) 204 { 205 for ( Object provided : getScopeState().provided.values() ) 206 { 207 if ( provided instanceof WeakMojoExecutionListener ) 208 { 209 ( (WeakMojoExecutionListener) provided ).afterExecutionFailure( event ); 210 } 211 } 212 } 213 214}