/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package ca.weblite.netbeans.mirah.maven; import ca.weblite.netbeans.mirah.support.spi.MirahExtenderImplementation; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.jar.JarOutputStream; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import java.util.zip.ZipEntry; import org.apache.maven.model.Build; import org.apache.maven.model.Dependency; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginExecution; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectUtils; import org.netbeans.spi.project.ProjectServiceProvider; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileSystem; import org.openide.filesystems.FileUtil; import org.openide.util.Exceptions; /** * * @author Martin Janicek */ @ProjectServiceProvider( service = { MirahExtenderImplementation.class }, projectType = { "org-netbeans-modules-maven" } ) public class MavenMirahExtender implements MirahExtenderImplementation{ private static final String MIRAH_GROUP_ID = "ca.weblite"; // NOI18N private static final String MIRAH_ARTIFACT_ID = "maven-mirah-plugin"; // NOI18N private static final String MIRAH_PLUGIN_VERSION = "1.0.1"; private final FileObject pom; public MavenMirahExtender(Project project) { this.pom = project.getProjectDirectory().getFileObject("pom.xml"); //NOI18N } @Override public boolean isActive() { final Boolean[] retValue = new Boolean[1]; retValue[0] = false; try { pom.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() { @Override public void run() throws IOException { ModelOperation op = new ModelOperation() { @Override public void performOperation(Model model) { if (hasModelDependency(model, MIRAH_GROUP_ID, MIRAH_ARTIFACT_ID)) { retValue[0] = true; } else { retValue[0] = false; } if ( !retValue[0] ){ return; } if (hasModelDependency(model, MIRAH_GROUP_ID , "mirah-tmp-classes")) { retValue[0] = true; } else { retValue[0] = false; } if ( !retValue[0] ){ return; } if (hasModelDependency(model, MIRAH_GROUP_ID, "mirah-tmp-classes-test")) { retValue[0] = true; } else { retValue[0] = false; } if ( !retValue[0] ){ return; } File libDir = new File(FileUtil.toFile(pom.getParent()), "lib"); if ( !libDir.exists() ){ retValue[0] = false; return; } File mirahClassesJar = new File(libDir, "mirah-tmp-classes.jar"); if ( !mirahClassesJar.exists()){ retValue[0] = false; return; } File mirahTestClassesJar = new File(libDir, "mirah-tmp-classes-test.jar"); if ( !mirahTestClassesJar.exists()){ retValue[0] = false; return; } } }; try { Utilities.performPOMModelOperations(pom, Collections.singletonList(op)); } catch (XmlPullParserException ex) { throw new IOException(ex); } } }); } catch (IOException ex) { return retValue[0]; } return retValue[0]; } @Override public boolean activate() { try { pom.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() { @Override public void run() throws IOException { List<ModelOperation> operations = new ArrayList<ModelOperation>(); operations.add(new AddMirahCompilerPlugin()); try { Utilities.performPOMModelOperations(pom, operations); } catch (XmlPullParserException ex) { throw new IOException(ex); } } }); } catch (IOException ex) { return false; } return true; } @Override public boolean deactivate() { throw new UnsupportedOperationException("Not supported yet."); } @Override public boolean isCurrent() { return isActive(); } @Override public boolean update() { return activate(); } public boolean hasModelDependency(Model model, String groupId, String artifactId){ for ( Dependency dep : model.getDependencies()){ if ( groupId.equals(dep.getGroupId()) && artifactId.equals(dep.getArtifactId())){ return true; } } return false; } class AddMirahCompilerPlugin implements ModelOperation { private Model model; @Override public void performOperation(final Model model) { this.model = model; Build build = model.getBuild(); if ( build == null ){ build = new Build(); model.setBuild(build); } Plugin compilerPlugin = mirahCompilerPluginExists(build); if ( compilerPlugin == null ){ compilerPlugin = createMirahCompilerPlugin(); build.addPlugin(compilerPlugin); } else { Plugin newPlugin = createMirahCompilerPlugin(); build.removePlugin(compilerPlugin); build.addPlugin(compilerPlugin); } if (!hasModelDependency(model, "ca.weblite", "mirah-tmp-classes" )) { // Now create an empty mirah-tmp-classes jar //System.out.println("About to create mirah-tmp-classes dir"); File libDir = new File(FileUtil.toFile(pom.getParent()), "lib"); File mirahTmpClassesDir = new File(libDir, "mirah-tmp-classes"); if ( !mirahTmpClassesDir.exists()){ //System.out.println("Dir doesn't exist.. creating it"); mirahTmpClassesDir.mkdirs(); } else { //System.out.println("Dir already existed"); } File mirahTmpClassesJar = new File(libDir, "mirah-tmp-classes.jar"); if ( !mirahTmpClassesJar.exists() ){ try { createJar(mirahTmpClassesDir, mirahTmpClassesDir.getPath(), mirahTmpClassesJar); } catch (IOException ex) { Exceptions.printStackTrace(ex); } } //Now add the dependency to the mirah classes jar (for code //completion Dependency dependency = new Dependency(); dependency.setArtifactId("mirah-tmp-classes"); dependency.setGroupId("ca.weblite"); dependency.setVersion("1.0-SNAPSHOT"); dependency.setScope("system"); dependency.setSystemPath("${basedir}/lib/mirah-tmp-classes.jar"); dependency.setOptional(true); model.addDependency(dependency); } if (!hasModelDependency(model, "ca.weblite", "mirah-tmp-classes-test" )) { File libDir = new File(FileUtil.toFile(pom.getParent()), "lib"); File mirahTmpClassesTestDir = new File(libDir, "mirah-tmp-classes-test"); if ( !mirahTmpClassesTestDir.exists()){ mirahTmpClassesTestDir.mkdirs(); } else { //System.out.println("Dir already existed"); } File mirahTmpClassesTestJar = new File(libDir, "mirah-tmp-classes-test.jar"); if ( !mirahTmpClassesTestJar.exists() ){ try { createJar(mirahTmpClassesTestDir, mirahTmpClassesTestDir.getPath(), mirahTmpClassesTestJar); } catch (IOException ex) { Exceptions.printStackTrace(ex); } } Dependency dependency = new Dependency(); dependency.setArtifactId("mirah-tmp-classes-test"); dependency.setGroupId("ca.weblite"); dependency.setVersion("1.0-SNAPSHOT"); dependency.setScope("system"); dependency.setSystemPath("${basedir}/lib/mirah-tmp-classes-test.jar"); dependency.setOptional(true); model.addDependency(dependency); } } private void createJar(File source, String sourceRoot, File jarFile) throws IOException { FileOutputStream fos = null; JarOutputStream jos = null; try { fos = new FileOutputStream(jarFile); jos = new JarOutputStream(fos); jos.setLevel(0); addToJar(source, sourceRoot, jos); } finally { try { if ( jos != null ) jos.close(); } catch ( Throwable t ){} try { if ( fos != null ) fos.close(); } catch ( Throwable t){} } } private void addToJar(File source, String sourceRoot, JarOutputStream jos) throws IOException { if ( source.getName().endsWith(".class")){ String fileName = formatEntry(source, sourceRoot, false); //System.out.println("Adding file "+fileName+" to jar ("+source+")"); ZipEntry entry = new ZipEntry(fileName); jos.putNextEntry(entry); InputStream fis = null; try { fis = new FileInputStream(source); byte[] buf = new byte[4096]; int len; while ( (len = fis.read(buf)) != -1 ){ //System.out.println("Writing "+len+" bytes"); jos.write(buf, 0, len); } jos.closeEntry(); } finally { try { if ( fis != null ){ fis.close(); } } catch ( Exception ex){} } } else if ( source.isDirectory() ){ String dirName = formatEntry(source, sourceRoot, true); //System.out.println("Adding "+dirName+" to jar"); //ZipEntry entry = new ZipEntry(dirName); //jos.putNextEntry(entry); for ( File child : source.listFiles()){ addToJar(child, sourceRoot, jos); } //jos.closeEntry(); } } private String formatEntry(File f, String sourceRoot, boolean directory){ if ( directory ){ String name = f.getPath().substring(sourceRoot.length()); name = name.replace("\\", "/"); if ( !name.endsWith("/")){ name += "/"; } if ( name.startsWith("/")){ name = name.substring(1); } return name; } else { String name = f.getPath().substring(sourceRoot.length()); name = name.replace("\\", "/"); if ( name.startsWith("/")){ name = name.substring(1); } return name; } } private void updatePluginVersion(final Plugin plugin) { plugin.setVersion(MIRAH_PLUGIN_VERSION); } private Plugin mirahCompilerPluginExists(final Build build) { List<Plugin> plugins = build.getPlugins(); if (plugins != null) { for (Plugin plugin : plugins) { if (MIRAH_GROUP_ID.equals(plugin.getGroupId()) && MIRAH_ARTIFACT_ID.equals(plugin.getArtifactId())) { return plugin; } } } return null; } private Plugin createMirahCompilerPlugin() { Plugin plugin = new Plugin(); plugin.setArtifactId(MIRAH_ARTIFACT_ID); plugin.setVersion(MIRAH_PLUGIN_VERSION); plugin.setGroupId(MIRAH_GROUP_ID); PluginExecution execution = new PluginExecution(); execution.setId("Compile Mirah Sources"); execution.setPhase("process-sources"); execution.addGoal("compile"); plugin.addExecution(execution); execution = new PluginExecution(); execution.setId("Compile Mirah Tests"); execution.setPhase("process-test-sources"); execution.addGoal("testCompile"); plugin.addExecution(execution); return plugin; } } }