Java tutorial
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.base.Objects; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import npanday.ArtifactType; import npanday.ArtifactTypeHelper; import npanday.PlatformUnsupportedException; import npanday.RepositoryNotFoundException; import npanday.executable.ExecutionException; import npanday.executable.compiler.CompilerCapability; import npanday.executable.compiler.CompilerConfig; import npanday.executable.compiler.CompilerContext; import npanday.executable.compiler.CompilerExecutable; import npanday.executable.compiler.InvalidArtifactException; import npanday.executable.compiler.KeyInfo; import npanday.registry.Repository; import npanday.registry.RepositoryRegistry; import npanday.vendor.Vendor; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; import org.apache.maven.model.Dependency; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.logging.LogEnabled; import org.codehaus.plexus.logging.Logger; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.PathTool; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Set; /** * Provides an implementation of the Compiler Context. * * @author Shane Isbell * @plexus.component role="npanday.executable.compiler.CompilerContext" */ public final class CompilerContextImpl extends ExecutableContextImpl implements CompilerContext, LogEnabled { private String NEW_LINE = System.getProperty("line.separator"); /** * The maven project */ private MavenProject project; private CompilerConfig config; private CompilerCapability compilerCapability; private List<Artifact> libraries; private List<Artifact> directLibraries; private List<Artifact> modules; /** * @plexus.requirement */ private RepositoryRegistry repositoryRegistry; /** * A logger for writing log messages */ private Logger logger; private List<File> linkedResources; /** * @deprecated */ private List<File> embeddedResources; private List<String> embeddedResourceArgs; private File win32icon; private List<File> win32resources; public List<File> getLinkedResources() { return linkedResources; } @Deprecated public List<File> getEmbeddedResources() { return embeddedResources; } public List<String> getEmbeddedResourceArgs() { return embeddedResourceArgs; } public File getWin32Icon() { return win32icon; } public List<File> getWin32Resources() { return win32resources; } public File getAssemblyPath() { return Objects.firstNonNull(config.getAssemblyPath(), compilerCapability.getAssemblyPath()); } public String getTargetFramework() { // TODO: Target framework could be overridden through the config here... return compilerCapability.getTargetFramework(); } public String getTargetProfile() { return compilerCapability.getProfile(); } public ArtifactType getTargetArtifactType() { return config.getArtifactType(); } public String getFrameworkVersion() { return compilerCapability.getVendorInfo().getFrameworkVersion(); } public boolean isTestCompile() { return config.isTestCompile(); } public boolean shouldCompile() { if (isTestCompile() && getSourceFiles().size() == 0) { logger.info("NPANDAY-061-017: Skipping test compile; no sources found"); return false; } return true; } public void enableLogging(Logger logger) { this.logger = logger; } public List<String> getCoreAssemblyNames() { return compilerCapability.getCoreAssemblies(); } public List<Artifact> getModuleDependencies() { return modules; } public List<Artifact> getDirectModuleDependencies() { List<Artifact> artifacts = Lists.newArrayList(); if (config.isTestCompile() && ArtifactTypeHelper.isDotnetModule(config.getArtifactType())) { artifacts.add(project.getArtifact()); } if (config.isTestCompile() && ArtifactTypeHelper.isDotnetModule(project.getArtifact().getType()) && project.getArtifact().getFile() != null && project.getArtifact().getFile().exists()) { artifacts.add(project.getArtifact()); } return artifacts; } public KeyInfo getKeyInfo() { if ((compilerCapability.getVendorInfo().getVendor().equals(Vendor.MICROSOFT) && compilerCapability.getVendorInfo().getFrameworkVersion().equals("1.1.4322")) || config.getKeyInfo() == null) { return KeyInfo.Factory.createDefaultKeyInfo(); } else { return config.getKeyInfo(); } } public List<Artifact> getLibraryDependencies() { addProjectArtifactForTestCompile(libraries); return libraries; } private void addProjectArtifactForTestCompile(List<Artifact> libraries) { if (config.isTestCompile() && (ArtifactTypeHelper.isDotnetLibrary(config.getArtifactType()) || ArtifactTypeHelper.isDotnetMavenPlugin(config.getArtifactType())) && project.getArtifact().getFile() != null && project.getArtifact().getFile().exists() && !libraries.contains(project.getArtifact()) && !ArtifactTypeHelper.isDotnetModule(project.getArtifact().getType())) { libraries.add(project.getArtifact()); } } public List<Artifact> getDirectLibraryDependencies() { for (Iterator i = project.getDependencyArtifacts().iterator(); i.hasNext();) { Artifact artifact = (Artifact) i.next(); if (!new ScopeArtifactFilter(isTestCompile() ? "test" : "compile").include(artifact)) { continue; } // TODO: use isAddedToClassPath instead? May need to annotate types if (!ArtifactTypeHelper.isDotnetLibrary(artifact.getType()) && !ArtifactTypeHelper.isDotnetExecutable(artifact.getType()) && !ArtifactTypeHelper.isDotnetAnyGac(artifact.getType())) { continue; } if (!hasArtifact(artifact)) { directLibraries.add(artifact); } boolean found = false; for (Iterator j = project.getDependencies().iterator(); j.hasNext() && !found;) { Dependency dependency = (Dependency) j.next(); if (dependency.getGroupId().equals(artifact.getGroupId()) && dependency.getArtifactId().equals(artifact.getArtifactId()) && dependency.getVersion().equals(artifact.getBaseVersion())) { found = true; } } if (!found) { directLibraries.remove(artifact); } } addProjectArtifactForTestCompile(directLibraries); return directLibraries; } private boolean hasArtifact(Artifact artifact) { for (Artifact art : directLibraries) { if (art.getArtifactId().equals(artifact.getArtifactId())) { return true; } } return false; } public Logger getLogger() { return logger; } public File getGeneratedSourcesDirectory() { return (config.isTestCompile()) ? new File(project.getBuild().getDirectory(), "build-test-sources") : new File(project.getBuild().getDirectory(), "build-sources"); } public File getTargetDirectory() { return new File(project.getBuild().getDirectory()); } /** * This method will return a File where File.isExist() returns false, if NetCompile.compile has not been * invoked. * * @return * @throws InvalidArtifactException */ public File getArtifact() throws InvalidArtifactException { ArtifactType artifactType = config.getArtifactType(); if (artifactType == null || artifactType.equals(ArtifactType.NULL)) { throw new InvalidArtifactException("NPANDAY-061-001: Artifact Type cannot be null"); } //TODO: The test-plugin has a dependency on this fileName/dir. If we change it here, // it will break the plugin. Fix this encapsulation issue. String fileName = (config.isTestCompile()) ? project.getBuild().getDirectory() + File.separator + project.getArtifactId() + "-test.dll" : project.getBuild().getDirectory() + File.separator + project.getArtifactId() + "." + artifactType.getExtension(); return new File(fileName); } public CompilerExecutable getCompilerExecutable() throws ExecutionException { return (CompilerExecutable) getNetExecutable(); } public Repository find(String repositoryName) throws RepositoryNotFoundException { Repository repository = repositoryRegistry.find(repositoryName); if (repository == null) { throw new RepositoryNotFoundException( "NPANDAY-061-002: Could not find repository: Name = " + repositoryName); } return repository; } public void init(CompilerCapability capability, CompilerConfig config, MavenProject project) throws PlatformUnsupportedException { this.project = project; this.config = config; libraries = new ArrayList<Artifact>(); directLibraries = new ArrayList<Artifact>(); modules = new ArrayList<Artifact>(); compilerCapability = capability; // initialize base class super.init(compilerCapability, config); Set<Artifact> artifacts = project.getDependencyArtifacts();//Can add WFC deps prior if (artifacts != null) { for (Artifact artifact : artifacts) { String type = artifact.getType(); logger.debug("NPANDAY-061-006: Artifact Type:" + type); logger.debug("NPANDAY-061-007: Artifact Type:" + ArtifactTypeHelper.isDotnetGenericGac(type)); ArtifactType artifactType = ArtifactType.getArtifactTypeForPackagingName(type); if (ArtifactTypeHelper.isDotnetModule(type)) { modules.add(artifact); } else if (ArtifactTypeHelper.isDotnetAssembly(artifactType)) { libraries.add(artifact); } if (type.equals(ArtifactType.COM_REFERENCE.getPackagingType())) { moveInteropDllToBuildDirectory(artifact); } } } String basedir = project.getBuild().getDirectory() + File.separator + "assembly-resources" + File.separator; linkedResources = new File(basedir, "linkresource").exists() ? Arrays.asList(new File(basedir, "linkresource").listFiles()) : new ArrayList<File>(); getEmbeddedResources(new File(basedir, "resource")); win32resources = new File(basedir, "win32res").exists() ? Arrays.asList(new File(basedir, "win32res").listFiles()) : new ArrayList<File>(); File win32IconDir = new File(basedir, "win32icon"); if (win32IconDir.exists()) { File[] icons = win32IconDir.listFiles(); if (icons.length > 1) { throw new PlatformUnsupportedException( "NPANDAY-061-008: There is more than one win32icon in resource directory: Number = " + icons.length); } if (icons.length == 1) { win32icon = icons[0]; } } } Set<File> expandedSourceFiles; public Set<File> getSourceFiles() { // TODO: cache source files - but it seems that this instance is reused... ?? /*if (expandedSourceFiles == null) expandedSourceFiles = expandSourceFiles();*/ return expandSourceFiles(); } private Set<File> expandSourceFiles() { Set<File> files = Sets.newHashSet(); files.addAll(expandSources(getGeneratedSourcesDirectory())); String defaultSourceRoot = isTestCompile() ? project.getBuild().getTestSourceDirectory() : project.getBuild().getSourceDirectory(); Set<String> additionalRoots = Sets.newHashSet(); List bareRoots = isTestCompile() ? project.getTestCompileSourceRoots() : project.getCompileSourceRoots(); if (bareRoots != null) { for (Object root : bareRoots) { if (!root.equals(defaultSourceRoot)) { additionalRoots.add((String) root); } } } if (additionalRoots.size() > 0) { getLogger().debug("NPANDAY-061-009: Adding additional compile source roots: " + additionalRoots); for (String root : additionalRoots) { files.addAll(expandSources(new File(root))); } } if (isTestCompile()) { files.addAll(expandTestSourceFilePatterns()); } else if (!isSourceAndTestsTogether()) { files.addAll(expandMainSourceFilePatterns()); } else { List<File> mainSources = expandMainSourceFilePatterns(); List<File> testSources = expandTestSourceFilePatterns(); getLogger().debug("NPANDAY-061-014: Since tests (" + testSources.size() + " files) reside in same folder as main sources (" + mainSources.size() + " files)," + " they will be excluded from main sources"); List<File> sources = Lists.newArrayList(); sources.addAll(mainSources); sources.removeAll(testSources); files.addAll(sources); } logger.info("NPANDAY-061-011: Found " + files.size() + " source files for " + (isTestCompile() ? "test" : "main") + " compile"); return files; } private List<File> expandMainSourceFilePatterns() { getLogger().debug("NPANDAY-061-012: Expanding main sources"); List<String> includes = Lists.newArrayList(); if (config.getDeprecatedIncludeSourcesConfiguration() != null) { includes.addAll(Lists.newArrayList(config.getDeprecatedIncludeSourcesConfiguration())); } if (config.getIncludes() != null) { includes.addAll(Lists.newArrayList(config.getIncludes())); } List<String> excludes = Lists.newArrayList(); if (config.getExcludes() != null) { excludes.addAll(Lists.newArrayList(config.getExcludes())); } if (includes.size() == 0) { includes.add("**/*." + config.getLanguageFileExtension()); } //target files excludes.add("**/obj/**"); excludes.add("**/bin/**"); excludes.add("**/target/**"); File root = new File(project.getBuild().getSourceDirectory()); return expandSources(root, includes, excludes); } private List<File> expandTestSourceFilePatterns() { getLogger().debug("NPANDAY-061-013: Expanding test sources"); List<String> includes = Lists.newArrayList(); if (config.getDeprecatedIncludeTestSourcesConfiguration() != null) { includes.addAll(Lists.newArrayList(config.getDeprecatedIncludeTestSourcesConfiguration())); } if (config.getTestIncludes() != null) { includes.addAll(Lists.newArrayList(config.getTestIncludes())); } List<String> excludes = Lists.newArrayList(); if (config.getTestExcludes() != null) { excludes.addAll(Lists.newArrayList(config.getTestExcludes())); } if (includes.size() == 0) { if (!isSourceAndTestsTogether()) { includes.add("**/*." + config.getLanguageFileExtension()); } else { getLogger().debug("NPANDAY-061-014: Since source and tests reside in same folder, " + "and no default includes are stated, conventions for finding tests will be applied."); includes.add("**/Test/**/*.*" + config.getLanguageFileExtension()); includes.add("**/Tests/**/*.*" + config.getLanguageFileExtension()); includes.add("**/*Tests." + config.getLanguageFileExtension()); includes.add("**/*Test." + config.getLanguageFileExtension()); } } //target files excludes.add("**/obj/**"); excludes.add("**/bin/**"); excludes.add("**/target/**"); File root = new File(project.getBuild().getTestSourceDirectory()); return expandSources(root, includes, excludes); } private List<File> expandSources(File directory) { return expandSources(directory, Lists.newArrayList("**/*." + config.getLanguageFileExtension()), null); } private List<File> expandSources(File directory, Iterable<String> includes, Iterable<String> excludes) { if (!directory.exists() || directory.list().length == 0) { getLogger().debug("NPANDAY-061-015: " + directory + " is empty; no sources found"); return Lists.newArrayList(); } DirectoryScanner scanner = createScanner(directory, includes, excludes); scanner.scan(); List<File> files = Lists.newArrayList(); for (String fs : scanner.getIncludedFiles()) { if (!fs.endsWith("." + config.getLanguageFileExtension())) { continue; } files.add(new File(directory, fs)); } if (getLogger().isDebugEnabled()) { getLogger().debug("NPANDAY-061-016: scanned for source files:" + NEW_LINE + " - directory: " + directory.getAbsolutePath() + NEW_LINE + " - includes: " + includes + NEW_LINE + " - excludes: " + excludes + NEW_LINE + " - included (*.*): " + scanner.getIncludedFiles().length + NEW_LINE + " - included sources (*." + config.getLanguageFileExtension() + "): " + files.size() + NEW_LINE + " - excluded: " + scanner.getExcludedFiles().length + NEW_LINE + " - ignored: " + scanner.getNotIncludedFiles().length); } return files; } private DirectoryScanner createScanner(File root, Iterable<String> includes, Iterable<String> excludes) { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(root); if (includes != null) { scanner.setIncludes(Iterables.toArray(includes, String.class)); } if (excludes != null) { scanner.setExcludes(Iterables.toArray(excludes, String.class)); } // TODO: NPANDAY-210 Maven is usually case sensitive, right? scanner.setCaseSensitive(false); scanner.addDefaultExcludes(); return scanner; } public File getOutputDirectory() { return config.getOutputDirectory(); } private void getEmbeddedResources(File basedir) { List<File> embeddedResources = new ArrayList<File>(); List<String> embeddedResourceArgs = new ArrayList<String>(); if (basedir.exists()) { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(basedir); scanner.scan(); for (String file : scanner.getIncludedFiles()) { File f = new File(basedir, file); embeddedResources.add(f); String executionRoot = System.getProperty("user.dir"); // TODO: ideally, all execution would happen from the project basedir, not the user.dir //String executionRoot = project.getBasedir().getAbsolutePath(); String path = PathTool.getRelativeFilePath(executionRoot, f.getPath()); if (f.getName().endsWith(".resources")) { embeddedResourceArgs.add(path); } else { String resourceName = project.getArtifactId() + "." + file.replace(File.separatorChar, '.'); embeddedResourceArgs.add(path + "," + resourceName); } } } this.embeddedResources = embeddedResources; this.embeddedResourceArgs = embeddedResourceArgs; } private void moveInteropDllToBuildDirectory(Artifact artifact) throws PlatformUnsupportedException { try { File file = artifact.getFile(); String oldPath = file.getAbsolutePath(); String target = project.getBuild().getDirectory(); String newPath = target + File.separator + "Interop." + artifact.getArtifactId() + ".dll"; if (oldPath.contains(target)) //already copied to target { return; } logger.info("NPANDAY-000-000:[COM Reference] copying file [" + oldPath + "] to [" + target + "]"); FileUtils.copyFileToDirectory(file, new File(target)); logger.info("NPANDAY-000-000:[COM Reference] deleting directory [" + file.getParentFile() + "]"); FileUtils.deleteDirectory(file.getParentFile()); logger.info("NPANDAY-000-000:[COM Reference] updating artifact path to [" + newPath + "]"); artifact.setFile(new File(newPath)); } catch (Exception e) { throw new PlatformUnsupportedException(e); } } public boolean isSourceAndTestsTogether() { return project.getBuild().getSourceDirectory().equals(project.getBuild().getTestSourceDirectory()); } }