| package npanday.executable.impl; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Sets; |
| import npanday.ArtifactType; |
| import npanday.InitializationException; |
| import npanday.PathUtil; |
| import npanday.PlatformUnsupportedException; |
| import npanday.executable.*; |
| import npanday.resolver.NPandayArtifactResolver; |
| import npanday.vendor.IllegalStateException; |
| import npanday.vendor.*; |
| import org.apache.maven.artifact.Artifact; |
| import org.apache.maven.artifact.factory.ArtifactFactory; |
| import org.apache.maven.artifact.metadata.ArtifactMetadataSource; |
| import org.apache.maven.artifact.repository.ArtifactRepository; |
| import org.apache.maven.artifact.resolver.ArtifactNotFoundException; |
| import org.apache.maven.artifact.resolver.ArtifactResolutionException; |
| import org.apache.maven.artifact.resolver.ArtifactResolutionResult; |
| import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; |
| import org.apache.maven.artifact.versioning.VersionRange; |
| import org.apache.maven.project.MavenProject; |
| import org.codehaus.plexus.logging.AbstractLogEnabled; |
| import org.codehaus.plexus.util.FileUtils; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.*; |
| |
| /** |
| * Provides an implementation of <code>NetExecutableFactory</code>. |
| * |
| * @author Shane Isbell |
| * @author <a href="mailto:lcorneliussen@apache.org">Lars Corneliussen</a> |
| * @plexus.component role="npanday.executable.NetPluginExecutableFactory" |
| */ |
| public class NetPluginExecutableFactoryImpl |
| extends AbstractLogEnabled |
| implements NetPluginExecutableFactory |
| { |
| /** |
| * @plexus.requirement |
| */ |
| private RepositoryExecutableContext repositoryExecutableContext; |
| |
| /** |
| * @plexus.requirement |
| */ |
| private StateMachineProcessor processor; |
| |
| /** |
| * @plexus.requirement |
| */ |
| private NPandayArtifactResolver artifactResolver; |
| |
| /** |
| * @plexus.requirement |
| */ |
| private ArtifactFactory artifactFactory; |
| |
| /** |
| * @plexus.requirement |
| */ |
| private ArtifactMetadataSource artifactMetadataSource; |
| |
| /** |
| * Returns the path of the artifact within the private application base. |
| * |
| * |
| * |
| * @param artifact the artifact to find the path of. This value should not be null. |
| * @param outputDir |
| * @return the path of the artifact within the private application base or null if either of the specified |
| * parameters is null |
| */ |
| private File getPrivateApplicationBaseFileFor(Artifact artifact, File outputDir) throws ArtifactResolutionException { |
| if ( artifact == null ) |
| { |
| getLogger().warn( "NPANDAY-040-003: Artifact is null - Cannot get application file." ); |
| return null; |
| } |
| |
| outputDir.mkdir(); |
| |
| String filename = artifact.getArtifactId() + "." + artifact.getArtifactHandler().getExtension(); |
| File targetFile = new File(outputDir, filename ); |
| |
| try |
| { |
| FileUtils.copyFile(artifact.getFile(), targetFile); |
| } |
| catch (IOException ioe) |
| { |
| throw new ArtifactResolutionException("NPANDAY-1005-0001: Error copying dependency", artifact, ioe); |
| } |
| |
| return targetFile; |
| } |
| |
| public NetExecutable getPluginRunner( |
| MavenProject project, Artifact pluginArtifact, Set<Artifact> additionalDependencies, |
| VendorRequirement vendorRequirement, ArtifactRepository localRepository, List<String> commands, File targetDir, |
| String npandayVersion ) throws |
| |
| PlatformUnsupportedException, |
| ArtifactResolutionException, |
| ArtifactNotFoundException{ |
| |
| Set dependencies = Sets.newHashSet(pluginArtifact); |
| if (additionalDependencies != null) |
| { |
| dependencies.addAll( additionalDependencies ); |
| } |
| |
| // need to resolve what we can here since we need the path! |
| Set<Artifact> artifacts = makeAvailable( |
| project.getArtifact(), project.getManagedVersionMap(), dependencies, targetDir, localRepository, |
| // TODO: consider, if this must be getRemotePluginRepositories()!! |
| project.getRemoteArtifactRepositories() |
| ); |
| |
| commands.add( "startProcessAssembly=" + pluginArtifact.getFile().getAbsolutePath() ); |
| |
| String pluginArtifactPath = findArtifact( artifacts, "NPanday.Plugin").getFile().getAbsolutePath(); |
| commands.add( "pluginArtifactPath=" + pluginArtifactPath ); |
| |
| return getArtifactExecutable( |
| project, createPluginRunnerArtifact( npandayVersion ), dependencies, vendorRequirement, localRepository, commands, targetDir |
| ); |
| } |
| |
| public NetExecutable getArtifactExecutable( |
| MavenProject project, Artifact executableArtifact, Set<Artifact> additionalDependencies, |
| VendorRequirement vendorRequirement, ArtifactRepository localRepository, List<String> commands, |
| File targetDir ) throws |
| |
| PlatformUnsupportedException, |
| ArtifactResolutionException, |
| ArtifactNotFoundException |
| { |
| Set dependencies = Sets.newHashSet(executableArtifact); |
| if (additionalDependencies != null){ |
| dependencies.addAll( additionalDependencies ); |
| } |
| |
| makeAvailable( |
| project.getArtifact(), project.getManagedVersionMap(), dependencies, targetDir, localRepository, |
| // TODO: consider, if this must be getRemotePluginRepositories()!! |
| project.getRemoteArtifactRepositories() |
| ); |
| |
| File artifactPath = executableArtifact.getFile(); |
| |
| if ( commands == null ) |
| { |
| commands = new ArrayList<String>(); |
| } |
| |
| // TODO: this should be a separate implementation of NetExecutable, configured only for MONO!!! |
| |
| VendorInfo vendorInfo; |
| try |
| { |
| vendorInfo = processor.process( vendorRequirement ); |
| } |
| catch ( IllegalStateException e ) |
| { |
| throw new PlatformUnsupportedException( |
| "NPANDAY-066-010: Illegal State: Vendor Info = " + vendorRequirement, e ); |
| } |
| |
| if ( vendorInfo.getVendor() == null || vendorInfo.getFrameworkVersion() == null ) |
| { |
| throw new PlatformUnsupportedException( "NPANDAY-066-020: Missing Vendor Information: " + vendorInfo ); |
| } |
| getLogger().debug( "NPANDAY-066-003: Found Vendor: " + vendorInfo ); |
| |
| |
| |
| List<String> modifiedCommands = new ArrayList<String>(); |
| String exe = null; |
| |
| if ( vendorInfo.getVendor().equals( Vendor.MONO ) ) |
| { |
| List<File> executablePaths = vendorInfo.getExecutablePaths(); |
| if ( executablePaths != null ) |
| { |
| for ( File executablePath : executablePaths ) |
| { |
| if ( new File( executablePath.getAbsolutePath(), "mono.exe" ).exists() ) |
| { |
| exe = new File( executablePath.getAbsolutePath(), "mono.exe" ).getAbsolutePath(); |
| commands.add( "vendor=MONO" );//if forked process, it needs to know. |
| break; |
| } |
| } |
| } |
| |
| if ( exe == null ) |
| { |
| getLogger().info( |
| "NPANDAY-066-005: Executable path for mono does not exist. Will attempt to execute MONO using" + |
| " the main PATH variable." ); |
| exe = "mono"; |
| commands.add( "vendor=MONO" );//if forked process, it needs to know. |
| } |
| modifiedCommands.add( artifactPath.getAbsolutePath() ); |
| for ( String command : commands ) |
| { |
| modifiedCommands.add( command ); |
| } |
| } |
| else |
| { |
| exe = artifactPath.getAbsolutePath(); |
| modifiedCommands = commands; |
| } |
| //TODO: DotGNU on Linux? |
| ExecutableConfig executableConfig = new ExecutableConfig(); |
| executableConfig.setExecutionPaths( Arrays.asList( exe ) ); |
| executableConfig.setCommands( modifiedCommands ); |
| |
| try |
| { |
| repositoryExecutableContext.init( executableConfig ); |
| } |
| catch ( InitializationException e ) |
| { |
| throw new PlatformUnsupportedException( |
| "NPANDAY-066-006: Unable to initialize the repository executable context", e ); |
| } |
| |
| try |
| { |
| return repositoryExecutableContext.getNetExecutable(); |
| } |
| catch ( ExecutionException e ) |
| { |
| throw new PlatformUnsupportedException( "NPANDAY-066-004: Unable to find net executable", e ); |
| } |
| } |
| |
| public Artifact findArtifact( Set<Artifact> artifacts, String artifactId ) throws ArtifactNotFoundException |
| { |
| List<String> ids = Lists.newArrayList(); |
| for ( Artifact a : artifacts ) |
| { |
| ids.add( a.getArtifactId() ); |
| |
| if ( a.getArtifactId().equalsIgnoreCase( artifactId ) ) |
| { |
| return a; |
| } |
| } |
| |
| throw new ArtifactNotFoundException( |
| "NPANDAY-066-11: Could not find artifact " + artifactId + " among " + ids, "*", artifactId, "*", "*", null, |
| null, null, null, null |
| ); |
| } |
| |
| public NetExecutable getPluginExecutable( |
| MavenProject project, Artifact pluginArtifact, VendorRequirement vendorRequirement, |
| ArtifactRepository localRepository, File parameterFile, String mojoName, File targetDir, String npandayVersion ) throws |
| PlatformUnsupportedException, |
| ArtifactResolutionException, |
| ArtifactNotFoundException |
| { |
| Set<Artifact> dependencies = Sets.newHashSet(pluginArtifact); |
| |
| Artifact loaderArtifact = artifactFactory.createDependencyArtifact( |
| "org.apache.npanday.plugins", "NPanday.Plugin.Loader", |
| VersionRange.createFromVersion( npandayVersion ), |
| ArtifactType.DOTNET_EXECUTABLE.getPackagingType(), null, "runtime" |
| ); |
| dependencies.add( |
| pluginArtifact |
| ); |
| |
| // preresolve this one |
| artifactResolver.resolve( pluginArtifact, project.getRemoteArtifactRepositories(), localRepository ); |
| File pluginArtifactPath = getPrivateApplicationBaseFileFor(pluginArtifact, targetDir); |
| |
| List<String> commands = new ArrayList<String>(); |
| commands.add( "parameterFile=" + parameterFile.getAbsolutePath() ); |
| commands.add( "assemblyFile=" + pluginArtifactPath.getAbsolutePath() ); |
| commands.add( "mojoName=" + mojoName );//ArtifactId = namespace |
| |
| return getPluginRunner( |
| project, loaderArtifact, dependencies, vendorRequirement, localRepository, commands, targetDir, |
| npandayVersion |
| ); |
| } |
| |
| private Artifact createPluginRunnerArtifact( String npandayVersion ) |
| { |
| return artifactFactory.createDependencyArtifact( |
| "org.apache.npanday.plugins", "NPanday.Plugin.Runner", |
| VersionRange.createFromVersion( npandayVersion ), |
| ArtifactType.DOTNET_EXECUTABLE.getPackagingType(), null, "runtime" |
| ); |
| } |
| |
| private Set<Artifact> makeAvailable( |
| Artifact originating, Map managedVersions, Set<Artifact> artifacts, File targetDir, |
| ArtifactRepository localRepository, List remoteArtifactRepositories ) throws |
| ArtifactResolutionException, |
| ArtifactNotFoundException |
| { |
| ArtifactResolutionResult results = artifactResolver.resolveTransitively( |
| artifacts, originating, managedVersions, localRepository, remoteArtifactRepositories, artifactMetadataSource, |
| new ScopeArtifactFilter( "runtime" ) |
| ); |
| |
| for(Object ao : results.getArtifacts()){ |
| Artifact a = (Artifact)ao; |
| a.setFile( getPrivateApplicationBaseFileFor(a, targetDir) ); |
| } |
| |
| return results.getArtifacts(); |
| } |
| } |