blob: 32977cbe6752eb52dc9f83db95ed00985af9d210 [file] [log] [blame]
/*
* 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.
*/
package npanday.resolver.resolvers;
import npanday.ArtifactTypeHelper;
import npanday.executable.ExecutableRequirement;
import npanday.executable.ExecutionResult;
import npanday.executable.NetExecutable;
import npanday.executable.NetExecutableFactory;
import npanday.resolver.ArtifactResolvingContributor;
import npanday.resolver.NPandayResolutionCache;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.Os;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:me@lcorneliussen.de>Lars Corneliussen, Faktum Software</a>
* @plexus.component role="npanday.resolver.ArtifactResolvingContributor" role-hint="com"
*/
public class ComReferenceResolver
extends AbstractLogEnabled
implements ArtifactResolvingContributor
{
/** @plexus.requirement */
NPandayResolutionCache cache;
/** @plexus.requirement */
protected NetExecutableFactory netExecutableFactory;
public void contribute(Artifact artifact, ArtifactRepository localRepository, List remoteRepositories,
Set<Artifact> additionalDependenciesCollector, ArtifactFilter filter)
{
// NO-OP
}
public void tryResolve(Artifact artifact, Set<Artifact> additionalDependenciesCollector, ArtifactFilter filter)
{
// resolve com reference
// flow:
// 1. generate the interop dll in temp folder and resolve to that path during dependency resolution
// 2. cut and paste the dll to buildDirectory and update the paths once we grab the reference of
// MavenProject (CompilerContext.java)
if ( ArtifactTypeHelper.isComReference(artifact.getType()) )
{
if (cache.applyTo(artifact)){
return;
}
String tokenId = artifact.getClassifier();
String interopPath;
try
{
interopPath = generateInteropDll( artifact.getArtifactId(), tokenId );
}
catch ( IOException e )
{
getLogger().error(
"NPANDAY-150-002: Error creating interop dll for " + artifact.getId()
);
return;
}
File f = new File( interopPath );
if ( !f.exists() )
{
getLogger().error(
"NPANDAY-150-001: Dependency com_reference File not found:" + interopPath + " for " + artifact.getId()
);
return;
}
artifact.setFile( f );
artifact.setResolved( true );
cache.put(artifact);
}
}
private String generateInteropDll( String name, String classifier )
throws IOException
{
File tmpDir;
String comReferenceAbsolutePath = "";
try
{
tmpDir = getTempDirectory();
}
catch ( IOException e )
{
throw new IOException( "Unable to create temporary directory" );
}
try
{
comReferenceAbsolutePath = resolveComReferencePath( name, classifier );
}
catch ( Exception e )
{
throw new IOException( e.getMessage() );
}
String interopAbsolutePath = tmpDir.getAbsolutePath() + File.separator + "Interop." + name + ".dll";
List<String> params = getInteropParameters( interopAbsolutePath, comReferenceAbsolutePath, name );
try
{
final NetExecutable executable = netExecutableFactory.getExecutable(
new ExecutableRequirement( "MICROSOFT", null, null, "TLBIMP" ), params, null
);
executable.execute();
}
catch ( Exception e )
{
throw new IOException( e.getMessage() );
}
return interopAbsolutePath;
}
private File getTempDirectory()
throws IOException
{
File tempFile = File.createTempFile( "interop-dll-", "" );
File tmpDir = new File( tempFile.getParentFile(), tempFile.getName() );
tempFile.delete();
tmpDir.mkdir();
return tmpDir;
}
private List<String> getInteropParameters( String interopAbsolutePath, String comRerefenceAbsolutePath,
String namespace )
{
List<String> parameters = new ArrayList<String>();
parameters.add( comRerefenceAbsolutePath );
parameters.add( "/out:" + interopAbsolutePath );
parameters.add( "/namespace:" + namespace );
try
{
// beginning code for checking of strong name key or signing of projects
String key = "";
String keyfile = "";
String currentWorkingDir = System.getProperty( "user.dir" );
// Check if Parent pom
List<String> modules = readPomAttribute( currentWorkingDir + File.separator + "pom.xml", "module" );
if ( !modules.isEmpty() )
{
// check if there is a matching dependency with the namespace
for ( String child : modules )
{
// check each module pom file if there is existing keyfile
String tempDir = currentWorkingDir + File.separator + child;
try
{
List<String> keyfiles = readPomAttribute( tempDir + "\\pom.xml", "keyfile" );
if ( keyfiles.get( 0 ) != null )
{
// PROBLEM WITH MULTIMODULES
boolean hasComRef = false;
List<String> dependencies = readPomAttribute( tempDir + "\\pom.xml", "groupId" );
for ( String item : dependencies )
{
if ( item.equals( namespace ) )
{
hasComRef = true;
break;
}
}
if ( hasComRef )
{
key = keyfiles.get( 0 );
currentWorkingDir = tempDir;
}
}
}
catch ( Exception e )
{
}
}
}
else
{
// not a parent pom, so read project pom file for keyfile value
List<String> keyfiles = readPomAttribute( currentWorkingDir + File.separator + "pom.xml", "keyfile" );
key = keyfiles.get( 0 );
}
if ( key != "" )
{
keyfile = currentWorkingDir + File.separator + key;
parameters.add( "/keyfile:" + keyfile );
}
// end code for checking of strong name key or signing of projects
}
catch ( Exception ex )
{
}
return parameters;
}
private List<String> readPomAttribute( String pomFileLoc, String tag )
{
List<String> attributes = new ArrayList<String>();
try
{
File file = new File( pomFileLoc );
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse( file );
doc.getDocumentElement().normalize();
NodeList nodeLst = doc.getElementsByTagName( tag );
for ( int s = 0; s < nodeLst.getLength(); s++ )
{
Node currentNode = nodeLst.item( s );
NodeList childrenList = currentNode.getChildNodes();
for ( int i = 0; i < childrenList.getLength(); i++ )
{
Node child = childrenList.item( i );
attributes.add( child.getNodeValue() );
}
}
}
catch ( Exception e )
{
}
return attributes;
}
private String resolveComReferencePath( String name, String classifier )
throws Exception
{
String[] classTokens = classifier.split( "}" );
classTokens[1] = classTokens[1].replace( "-", "\\" );
String newClassifier = classTokens[0] + "}" + classTokens[1];
String registryPath = "HKEY_CLASSES_ROOT\\TypeLib\\" + newClassifier;
registryPath += Os.isArch( "x86" ) ? "\\win32\\" : "\\win64\\";
int lineNoOfPath = 1;
List<String> parameters = new ArrayList<String>();
parameters.add( "query" );
parameters.add( registryPath );
parameters.add( "/ve" );
ExecutionResult res;
try
{
final NetExecutable executable = netExecutableFactory.getExecutable(
new ExecutableRequirement( "MICROSOFT", null, null, "REG" ), parameters, null
);
res = executable.execute();
}
catch ( Exception e )
{
throw new Exception( "Cannot find information of [" + name
+ "] ActiveX component in your system, you need to install this component first to continue." );
}
String out = res.getStandardOut();
String tokens[] = out.split( "\n" );
String lineResult = "";
String[] result;
if ( tokens.length >= lineNoOfPath - 1 )
{
lineResult = tokens[lineNoOfPath - 1];
}
result = lineResult.split( "REG_SZ" );
if ( result.length > 1 )
{
return result[1].trim();
}
return null;
}
}