All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.mojo.nbm.CreateWebstartAppMojo Maven / Gradle / Ivy

Go to download

Maven plugin for creating NetBeans modules. It defines a custom lifecycle called "nbm". During packaging, the module JAR is enhanced with NetBeans-specific manifest entries and, along with other required files, packed into a *.nbm file, ready for distribution. Additionally the plugin provides aggregator goals to create an update site or cluster for your module projects.

There is a newer version: 4.1
Show newest version
/*
 *  Copyright 2008 Johan Andrén.
 *
 *  Licensed 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.
 *  under the License.
 */
package org.codehaus.mojo.nbm;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.jar.JarFile;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.shared.filtering.MavenResourcesExecution;
import org.apache.maven.shared.filtering.MavenResourcesFiltering;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.GenerateKey;
import org.apache.tools.ant.taskdefs.Jar;
import org.apache.tools.ant.taskdefs.Jar.FilesetManifestConfig;
import org.apache.tools.ant.taskdefs.SignJar;
import org.apache.tools.ant.taskdefs.Taskdef;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Parameter;
import org.apache.tools.ant.types.ZipFileSet;
import org.apache.tools.ant.types.selectors.AndSelector;
import org.apache.tools.ant.types.selectors.FilenameSelector;
import org.apache.tools.ant.types.selectors.OrSelector;
import org.codehaus.mojo.nbm.utils.JarUtils;
import org.codehaus.plexus.archiver.zip.ZipArchiver;
import org.codehaus.plexus.components.io.resources.PlexusIoResource;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.InterpolationFilterReader;
import org.netbeans.nbbuild.MakeJnlp2;
import org.netbeans.nbbuild.ModuleSelector;
import org.netbeans.nbbuild.VerifyJNLP;

/**
 * Create webstartable binaries for a 'nbm-application'.
 * @author Johan Andrén
 * @author Milos Kleint
 * @since 3.0
 */
@Mojo(name="webstart-app", defaultPhase= LifecyclePhase.PACKAGE )
public class CreateWebstartAppMojo
    extends AbstractNbmMojo
{

    /**
     * The Maven project.

     */
    @org.apache.maven.plugins.annotations.Parameter(required=true, readonly=true, property="project")
    private MavenProject project;

    @Component
    protected MavenProjectHelper projectHelper;

    /**
     * The branding token for the application based on NetBeans platform.
     */
    @org.apache.maven.plugins.annotations.Parameter(required=true, property="netbeans.branding.token")
    protected String brandingToken;

    /**
     * output directory where the the NetBeans application will be created.
     */
    @org.apache.maven.plugins.annotations.Parameter(required=true, defaultValue="${project.build.directory}")
    private File outputDirectory;

    /**
     * Ready-to-deploy WAR containing application in JNLP packaging.
     *
     */
    @org.apache.maven.plugins.annotations.Parameter(required=true, defaultValue="${project.build.directory}/${project.artifactId}-${project.version}-jnlp.war")
    private File destinationFile;

    /**
     * Artifact Classifier to use for the webstart distributable zip file.
     * @since 3.1
     */
    @org.apache.maven.plugins.annotations.Parameter(defaultValue="webstart", property="nbm.webstart.classifier")
    private String webstartClassifier;

    /**
     * Codebase value within *.jnlp files.
     * Defining this parameter is generally a bad idea.
     */
    @org.apache.maven.plugins.annotations.Parameter(property="nbm.webstart.codebase")
    private String codebase;

    /**
     * A custom master JNLP file. If not defined, the
     * default one is used.
     * The following expressions can be used within the file and will
     * be replaced when generating content.
     * 
    *
  • ${jnlp.resources}
  • *
  • ${jnlp.codebase} - the 'codebase' parameter value is passed in.
  • *
  • ${app.name}
  • *
  • ${app.title}
  • *
  • ${app.vendor}
  • *
  • ${app.description}
  • *
  • ${branding.token} - the 'brandingToken' parameter value is passed in.
  • *
  • ${netbeans.jnlp.fixPolicy}
  • *
*/ @org.apache.maven.plugins.annotations.Parameter private File masterJnlpFile; /** * The basename (minus .jnlp extension) of the master JNLP file in the output. * This file will be the entry point for javaws. * Defaults to the branding token. * @since 3.5 */ @org.apache.maven.plugins.annotations.Parameter(property="master.jnlp.file.name") private String masterJnlpFileName; /** * keystore location for signing the nbm file */ @org.apache.maven.plugins.annotations.Parameter(property="keystore") private String keystore; /** * keystore password */ @org.apache.maven.plugins.annotations.Parameter(property="keystorepass") private String keystorepassword; /** * keystore alias */ @org.apache.maven.plugins.annotations.Parameter(property="keystorealias") private String keystorealias; /** * keystore type * @since 3.5 */ @org.apache.maven.plugins.annotations.Parameter(property="keystoretype") private String keystoretype; /** * If set true, build-jnlp target creates versioning info in jnlp descriptors and version.xml files. * This allows for incremental updates of Webstart applications, but requires download via * JnlpDownloadServlet * Defaults to false, which means versioning * info is not generated (see * http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/downloadservletguide.html#resources). * */ @org.apache.maven.plugins.annotations.Parameter(defaultValue="false", property="nbm.webstart.versions") private boolean processJarVersions; @org.apache.maven.plugins.annotations.Parameter(defaultValue="false", property="nbm.webstart.signWar") private boolean signWar; @org.apache.maven.plugins.annotations.Parameter(defaultValue="false", property="nbm.webstart.generateJnlpApplicationTemplate") private boolean generateJnlpApplicationTemplate; /** * additional command line arguments. Eg. * -J-Xdebug -J-Xnoagent -J-Xrunjdwp:transport=dt_socket,suspend=n,server=n,address=8888 * can be used to debug the IDE. */ @org.apache.maven.plugins.annotations.Parameter(property="netbeans.run.params") private String additionalArguments; @org.apache.maven.plugins.annotations.Parameter(property="nbm.signing.threads", defaultValue="0") private int signingThreads; @org.apache.maven.plugins.annotations.Parameter(property="nbm.signing.force", defaultValue="true") private boolean signingForce; @org.apache.maven.plugins.annotations.Parameter(property="nbm.signing.tsacert") private String signingTsaCert; @org.apache.maven.plugins.annotations.Parameter(property="nbm.signing.tsaurl") private String signingTsaUrl; @org.apache.maven.plugins.annotations.Parameter( property="nbm.signing.removeExistingSignatures", defaultValue="false") private boolean signingRemoveExistingSignatures; @org.apache.maven.plugins.annotations.Parameter(property="nbm.signing.maxMemory") private String signingMaxMemory = "96m"; @org.apache.maven.plugins.annotations.Parameter( property="nbm.signing.retryCount", defaultValue="5") private int signingRetryCount; @org.apache.maven.plugins.annotations.Parameter(property="encoding", defaultValue="${project.build.sourceEncoding}") protected String encoding; @org.apache.maven.plugins.annotations.Parameter(property="session", readonly=true, required=true) protected MavenSession session; @Component protected MavenResourcesFiltering mavenResourcesFiltering; @org.apache.maven.plugins.annotations.Parameter private List webappResources; /** * * @throws org.apache.maven.plugin.MojoExecutionException * @throws org.apache.maven.plugin.MojoFailureException */ @Override public void execute() throws MojoExecutionException, MojoFailureException { if ( signingThreads < 1 ) { signingThreads = Runtime.getRuntime().availableProcessors(); } if ( !"nbm-application".equals( project.getPackaging() ) ) { throw new MojoExecutionException( "This goal only makes sense on project with nbm-application packaging." ); } final Project antProject = antProject(); getLog().warn( "WARNING: Unsigned and self-signed WebStart applications are deprecated from JDK7u21 onwards. To ensure future correct functionality please use trusted certificate."); if ( keystore != null && keystorealias != null && keystorepassword != null ) { File ks = new File( keystore ); if ( !ks.exists() ) { throw new MojoFailureException( "Cannot find keystore file at " + ks.getAbsolutePath() ); } else { //proceed.. } } else if ( keystore != null || keystorepassword != null || keystorealias != null ) { throw new MojoFailureException( "If you want to sign the jnlp application, you need to define all three keystore related parameters." ); } else { File generatedKeystore = new File( outputDirectory, "generated.keystore" ); if ( ! generatedKeystore.exists() ) { getLog().warn( "Keystore related parameters not set, generating a default keystore." ); GenerateKey genTask = (GenerateKey) antProject.createTask( "genkey" ); genTask.setAlias( "jnlp" ); genTask.setStorepass( "netbeans" ); genTask.setDname( "CN=" + System.getProperty( "user.name" ) ); genTask.setKeystore( generatedKeystore.getAbsolutePath() ); genTask.execute(); } keystore = generatedKeystore.getAbsolutePath(); keystorepassword = "netbeans"; keystorealias = "jnlp"; } Taskdef taskdef = (Taskdef) antProject.createTask( "taskdef" ); taskdef.setClassname( MakeJnlp2.class.getName() ); taskdef.setName( "makejnlp" ); taskdef.execute(); taskdef = (Taskdef) antProject.createTask( "taskdef" ); taskdef.setClassname( Jar.class.getName() ); taskdef.setName( "jar" ); taskdef.execute(); taskdef = (Taskdef) antProject.createTask( "taskdef" ); taskdef.setClassname( "org.netbeans.nbbuild.VerifyJNLP" ); taskdef.setName( "verifyjnlp" ); taskdef.execute(); try { File webstartBuildDir = new File( outputDirectory + File.separator + "webstart" + File.separator + brandingToken ); if ( webstartBuildDir.exists() ) { FileUtils.deleteDirectory( webstartBuildDir ); } webstartBuildDir.mkdirs(); // P: copy webappResources --[ MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution( webappResources, webstartBuildDir, project, encoding, Collections.EMPTY_LIST, Collections.EMPTY_LIST, session ); mavenResourcesExecution.setEscapeWindowsPaths( true ); mavenResourcesFiltering.filterResources( mavenResourcesExecution ); // ]-- final String localCodebase = codebase != null ? codebase : webstartBuildDir.toURI().toString(); getLog().info( "Generating webstartable binaries at " + webstartBuildDir.getAbsolutePath() ); File nbmBuildDirFile = new File( outputDirectory, brandingToken ); // FileUtils.copyDirectoryStructureIfModified( nbmBuildDirFile, webstartBuildDir ); MakeJnlp2 jnlpTask = (MakeJnlp2) antProject.createTask( "makejnlp" ); jnlpTask.setDir( webstartBuildDir ); jnlpTask.setCodebase( localCodebase ); //TODO, how to figure verify excludes.. jnlpTask.setVerify( false ); jnlpTask.setPermissions( "" ); jnlpTask.setSignJars( true ); jnlpTask.setAlias( keystorealias ); jnlpTask.setKeystore( keystore ); jnlpTask.setStorePass( keystorepassword ); if ( keystoretype != null ) { jnlpTask.setStoreType( keystoretype ); } jnlpTask.setSigningForce( signingForce ); jnlpTask.setSigningTsaCert( signingTsaCert ); jnlpTask.setSigningTsaUrl( signingTsaUrl ); jnlpTask.setSigningRemoveExistingSignatures( signingRemoveExistingSignatures ); jnlpTask.setSigningMaxMemory( signingMaxMemory ); jnlpTask.setSigningRetryCount( signingRetryCount ); jnlpTask.setNbThreads( signingThreads ); jnlpTask.setProcessJarVersions( processJarVersions ); FileSet fs = jnlpTask.createModules(); fs.setDir( nbmBuildDirFile ); OrSelector or = new OrSelector(); AndSelector and = new AndSelector(); FilenameSelector inc = new FilenameSelector(); inc.setName( "*/modules/**/*.jar" ); or.addFilename( inc ); inc = new FilenameSelector(); inc.setName( "*/lib/**/*.jar" ); or.addFilename( inc ); inc = new FilenameSelector(); inc.setName( "*/core/**/*.jar" ); or.addFilename( inc ); ModuleSelector ms = new ModuleSelector(); Parameter included = new Parameter(); included.setName( "includeClusters" ); included.setValue( "" ); Parameter excluded = new Parameter(); excluded.setName( "excludeClusters" ); excluded.setValue( "" ); Parameter exModules = new Parameter(); exModules.setName( "excludeModules" ); exModules.setValue( "" ); ms.setParameters( new Parameter[] { included, excluded, exModules } ); and.add( or ); and.add( ms ); fs.addAnd( and ); jnlpTask.execute(); //TODO is it really netbeans/ String extSnippet = generateExtensions( fs, antProject, "" ); // "netbeans/" if ( masterJnlpFileName == null ) { masterJnlpFileName = brandingToken; } Properties props = new Properties(); props.setProperty( "jnlp.codebase", localCodebase ); props.setProperty( "app.name", brandingToken ); props.setProperty( "app.title", project.getName() ); if ( project.getOrganization() != null ) { props.setProperty( "app.vendor", project.getOrganization().getName() ); } else { props.setProperty( "app.vendor", "Nobody" ); } String description = project.getDescription() != null ? project.getDescription() : "No Project Description"; props.setProperty( "app.description", description ); props.setProperty( "branding.token", brandingToken ); props.setProperty( "master.jnlp.file.name", masterJnlpFileName ); props.setProperty( "netbeans.jnlp.fixPolicy", "false" ); StringBuilder stBuilder = new StringBuilder(); if ( additionalArguments != null ) { StringTokenizer st = new StringTokenizer( additionalArguments ); while ( st.hasMoreTokens() ) { String arg = st.nextToken(); if ( arg.startsWith( "-J" ) ) { if ( stBuilder.length() > 0 ) { stBuilder.append( ' ' ); } stBuilder.append( arg.substring( 2 ) ); } } } props.setProperty( "netbeans.run.params", stBuilder.toString() ); File masterJnlp = new File( webstartBuildDir.getAbsolutePath() + File.separator + masterJnlpFileName + ".jnlp" ); filterCopy( masterJnlpFile, "master.jnlp", masterJnlp, props ); File startup = copyLauncher( outputDirectory, nbmBuildDirFile ); // P: JNLP-INF/APPLICATION_TEMPLATE.JNLP support --[ // this can be done better if ( generateJnlpApplicationTemplate ) { File jnlpInfDir = new File( outputDirectory, "JNLP-INF" ); getLog().info( "Generate JNLP application template under: " + jnlpInfDir ); jnlpInfDir.mkdirs(); File jnlpTemplate = new File( jnlpInfDir, "APPLICATION_TEMPLATE.JNLP" ); String masterJnlpStr = FileUtils.fileRead( masterJnlp ); masterJnlpStr = masterJnlpStr .replaceAll( "( 0 ) { final File brandingDir = new File( webstartBuildDir, "branding" ); brandingDir.mkdirs(); for ( String incBran : includes ) { File source = new File( nbmBuildDirFile, incBran ); File dest = new File( brandingDir, source.getName() ); FileUtils.copyFile( source, dest ); brandRefs.append( " \n" ); } DirectoryScanner subDs = new DirectoryScanner(); subDs.setBasedir( brandingDir ); subDs.setIncludes( new String[] { "*.jar" } ); subDs.scan(); final ExecutorService executorService = Executors.newFixedThreadPool( signingThreads ); final List threadException = new ArrayList(); for (final String toSign : subDs.getIncludedFiles()) { executorService.execute( new Runnable() { @Override public void run() { try { File toSignFile = new File( brandingDir, toSign ); if ( signingRemoveExistingSignatures ) { getLog().info("Unsigning archive: " + toSignFile); JarUtils.unsignArchive( toSignFile ); } SignJar signTask = (SignJar) antProject.createTask( "signjar" ); signTask.setKeystore( keystore ); signTask.setStorepass( keystorepassword ); signTask.setAlias( keystorealias ); signTask.setForce( signingForce ); signTask.setTsacert( signingTsaCert ); signTask.setTsaurl( signingTsaUrl ); signTask.setMaxmemory( signingMaxMemory ); signTask.setRetryCount( signingRetryCount ); signTask.setJar( toSignFile ); signTask.execute(); } catch ( Exception e ) { threadException.add( e ); } } } ); } executorService.shutdown(); executorService.awaitTermination( Long.MAX_VALUE, TimeUnit.NANOSECONDS ); if ( !threadException.isEmpty() ) { throw threadException.get( 0 ); } } File modulesJnlp = new File( webstartBuildDir.getAbsolutePath() + File.separator + "modules.jnlp" ); props.setProperty( "jnlp.branding.jars", brandRefs.toString() ); props.setProperty( "jnlp.resources", extSnippet ); filterCopy( null, /* filename is historical */"branding.jnlp", modulesJnlp, props ); getLog().info( "Verifying generated webstartable content." ); VerifyJNLP verifyTask = (VerifyJNLP) antProject.createTask( "verifyjnlp" ); FileSet verify = new FileSet(); verify.setFile( masterJnlp ); verifyTask.addConfiguredFileset( verify ); verifyTask.execute(); // create zip archive if ( destinationFile.exists() ) { destinationFile.delete(); } ZipArchiver archiver = new ZipArchiver(); if ( codebase != null ) { getLog().warn( "Defining /${nbm.webstart.codebase} is generally unnecessary" ); archiver.addDirectory( webstartBuildDir ); } else { archiver.addDirectory( webstartBuildDir, null, new String[] { "**/*.jnlp" } ); for ( final File jnlp : webstartBuildDir.listFiles() ) { if ( !jnlp.getName().endsWith( ".jnlp" ) ) { continue; } archiver.addResource( new PlexusIoResource() { public @Override InputStream getContents() throws IOException { return new ByteArrayInputStream( FileUtils.fileRead( jnlp, "UTF-8" ).replace( localCodebase, "$$codebase" ).getBytes( "UTF-8" ) ); } public @Override long getLastModified() { return jnlp.lastModified(); } public @Override boolean isExisting() { return true; } public @Override long getSize() { return UNKNOWN_RESOURCE_SIZE; } public @Override URL getURL() throws IOException { return null; } public @Override String getName() { return jnlp.getAbsolutePath(); } public @Override boolean isFile() { return true; } public @Override boolean isDirectory() { return false; } }, jnlp.getName(), archiver.getDefaultFileMode() ); } } File jdkhome = new File( System.getProperty( "java.home" ) ); File servlet = new File( jdkhome, "sample/jnlp/servlet/jnlp-servlet.jar" ); if ( ! servlet.exists() ) { servlet = new File( jdkhome.getParentFile(), "sample/jnlp/servlet/jnlp-servlet.jar" ); if ( !servlet.exists() ) { servlet = File.createTempFile( "nbm_", "jnlp-servlet.jar" ); FileUtils.copyURLToFile( Thread.currentThread().getContextClassLoader() .getResource( "jnlp-servlet.jar" ), servlet ); } } if ( servlet.exists() ) { archiver.addFile( servlet, "WEB-INF/lib/jnlp-servlet.jar" ); archiver.addResource( new PlexusIoResource() { public @Override InputStream getContents() throws IOException { return new ByteArrayInputStream( ( "" + "\n" + " \n" + " JnlpDownloadServlet\n" + " jnlp.sample.servlet.JnlpDownloadServlet\n" + " \n" + " \n" + " JnlpDownloadServlet\n" + " *.jnlp\n" + " \n" + "\n" ).getBytes() ); } public @Override long getLastModified() { return UNKNOWN_MODIFICATION_DATE; } public @Override boolean isExisting() { return true; } public @Override long getSize() { return UNKNOWN_RESOURCE_SIZE; } public @Override URL getURL() throws IOException { return null; } public @Override String getName() { return "web.xml"; } public @Override boolean isFile() { return true; } public @Override boolean isDirectory() { return false; } }, "WEB-INF/web.xml", archiver.getDefaultFileMode() ); } archiver.setDestFile( destinationFile ); archiver.createArchive(); if (signWar) { signTask = (SignJar) antProject.createTask( "signjar" ); signTask.setKeystore( keystore ); signTask.setStorepass( keystorepassword ); signTask.setAlias( keystorealias ); signTask.setForce( signingForce ); signTask.setTsacert( signingTsaCert ); signTask.setTsaurl( signingTsaUrl ); signTask.setMaxmemory( signingMaxMemory ); signTask.setRetryCount( signingRetryCount ); signTask.setJar( destinationFile ); signTask.execute(); } // attach standalone so that it gets installed/deployed projectHelper.attachArtifact( project, "war", webstartClassifier, destinationFile ); } catch ( Exception ex ) { throw new MojoExecutionException( "Error creating webstartable binary.", ex ); } } /** * @param standaloneBuildDir * @return The name of the jnlp-launcher jarfile in the build directory */ private File copyLauncher( File standaloneBuildDir, File builtInstallation ) throws IOException { File jnlpStarter = new File( builtInstallation.getAbsolutePath() + File.separator + "harness" + File.separator + "jnlp" + File.separator + "jnlp-launcher.jar" ); // buffer so it isn't reading a byte at a time! InputStream source = null; FileOutputStream outstream = null; try { if ( !jnlpStarter.exists() ) { source = getClass().getClassLoader().getResourceAsStream( "harness/jnlp/jnlp-launcher.jar" ); } else { source = new FileInputStream( jnlpStarter ); } File jnlpDestination = new File( standaloneBuildDir.getAbsolutePath() + File.separator + "jnlp-launcher.jar" ); outstream = new FileOutputStream( jnlpDestination ); IOUtil.copy( source, outstream ); return jnlpDestination; } finally { IOUtil.close( source ); IOUtil.close( outstream ); } } private void filterCopy( File sourceFile, String resourcePath, File destinationFile, Properties filterProperties ) throws IOException { // buffer so it isn't reading a byte at a time! Reader source = null; Writer destination = null; try { InputStream instream; if ( sourceFile != null ) { instream = new FileInputStream( sourceFile ); } else { instream = getClass().getClassLoader().getResourceAsStream( resourcePath ); } FileOutputStream outstream = new FileOutputStream( destinationFile ); source = new BufferedReader( new InputStreamReader( instream, "UTF-8" ) ); destination = new OutputStreamWriter( outstream, "UTF-8" ); // support ${token} Reader reader = new InterpolationFilterReader( source, filterProperties, "${", "}" ); IOUtil.copy( reader, destination ); } finally { IOUtil.close( source ); IOUtil.close( destination ); } } /** * copied from MakeMasterJNLP ant task. * @param files * @param antProject * @param masterPrefix * @return * @throws java.io.IOException */ private String generateExtensions( FileSet files, Project antProject, String masterPrefix ) throws IOException { StringBuilder buff = new StringBuilder(); for ( String nm : files.getDirectoryScanner( antProject ).getIncludedFiles() ) { File jar = new File( files.getDir( antProject ), nm ); if ( !jar.canRead() ) { throw new IOException( "Cannot read file: " + jar ); } JarFile theJar = new JarFile( jar ); String codenamebase = theJar.getManifest().getMainAttributes().getValue( "OpenIDE-Module" ); if ( codenamebase == null ) { throw new IOException( "Not a NetBeans Module: " + jar ); } { int slash = codenamebase.indexOf( '/' ); if ( slash >= 0 ) { codenamebase = codenamebase.substring( 0, slash ); } } String dashcnb = codenamebase.replace( '.', '-' ); buff.append( " \n" ); theJar.close(); } return buff.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy