/* * The contents of this file are subject to the terms of the Common Development * and Distribution License (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at http://www.netbeans.org/cddl.html * or http://www.netbeans.org/cddl.txt. * * When distributing Covered Code, include this CDDL Header Notice in each file * and include the License file at http://www.netbeans.org/cddl.txt. * If applicable, add the following below the CDDL Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" */ package org.netbeans.modules.gwt4nb; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.logging.Level; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.project.classpath.ProjectClassPathModifier; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; import org.netbeans.api.project.FileOwnerQuery; import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectInformation; import org.netbeans.api.project.ProjectUtils; import org.netbeans.api.project.libraries.Library; import org.netbeans.api.project.libraries.LibraryManager; import org.netbeans.modules.gwt4nb.settings.GWTSettings; import org.netbeans.modules.j2ee.dd.api.web.DDProvider; import org.netbeans.modules.j2ee.dd.api.web.WebApp; import org.netbeans.modules.j2ee.dd.api.web.WelcomeFileList; import org.netbeans.modules.web.api.webmodule.ExtenderController; import org.netbeans.modules.web.api.webmodule.WebModule; import org.netbeans.modules.web.spi.webmodule.WebModuleExtender; import org.netbeans.spi.project.support.ant.AntProjectHelper; import org.netbeans.spi.project.support.ant.EditableProperties; import org.openide.filesystems.FileLock; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileStateInvalidException; import org.openide.filesystems.FileUtil; import org.openide.loaders.DataFolder; import org.openide.loaders.DataObject; import org.openide.util.Exceptions; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.openide.xml.XMLUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.w3c.dom.Text; /** * Extends a project with GWT support. */ public class GWTWebModuleExtender extends WebModuleExtender { // see http://maven.apache.org/pom.html private static final List<String> POM_ELEMENTS = Arrays.asList( "modelVersion", // NOI18N "groupId", // NOI18N "artifactId", // NOI18N "version", // NOI18N "packaging", // NOI18N "dependencies", // NOI18N "parent", // NOI18N "dependencyManagement", // NOI18N "modules", // NOI18N "properties", // NOI18N "build", // NOI18N "reporting", // NOI18N "name", // NOI18N "description", // NOI18N "url", // NOI18N "inceptionYear", // NOI18N "licenses", // NOI18N "organization", // NOI18N "developers", // NOI18N "contributors", // NOI18N "issueManagement", // NOI18N "ciManagement", // NOI18N "mailingLists", // NOI18N "scm", // NOI18N "prerequisites", // NOI18N "repositories", // NOI18N "pluginRepositories", // NOI18N "distributionManagement", // NOI18N "profiles" // NOI18N ); private static final List<String> BUILD_ELEMENTS = Arrays.asList( "directory", // NOI18N "outputDirectory", // NOI18N "finalName", // NOI18N "testOutputDirectory", // NOI18N "sourceDirectory", // NOI18N "scriptSourceDirectory", // NOI18N "testSourceDirectory", // NOI18N "resources", // NOI18N "testResources", // NOI18N "pluginManagement", // NOI18N "plugins" // NOI18N ); private static final String GWT_USER = "gwt-user.jar"; // NOI18N private static final String GWT_SERVLET = "gwt-servlet.jar"; // NOI18N private static final String GWT_SERVLET_DEPS = "gwt-servlet-deps.jar"; // NOI18N private static final String REQUESTFACTORY_SERVER = "requestfactory-server.jar"; // NOI18N private static final String PATTERN_PRJ_NAME = "__PROJECT_NAME__"; // NOI18N private static final String CLIENT_FOLDER = "client"; // NOI18N private static final String TEMPLATE_JAVA_CLASS = "Templates/Classes/EntryPoint.java"; // NOI18N private static final String LIB_GWT_NAME = "GWT"; // NOI18N private static final String DEFAULT_GWT_VERSION_MAVEN = "2.0.3"; // NOI18N /** * this module will be extended with GWT or null if a new project is being * created */ private WebModule webModule; private GWTConfigPanel pnlConfig = null; private final GWTFrameworkProvider fp; private final ExtenderController ec; private final Set<ChangeListener> listeners = new CopyOnWriteArraySet<ChangeListener>(); /** * @param webModule this module will be extended with GWT or null if a new * project is being created * @param ec ? * @param fp GWT framework provider */ public GWTWebModuleExtender(WebModule webModule, ExtenderController ec, GWTFrameworkProvider fp) { this.webModule = webModule; this.ec = ec; this.fp = fp; boolean defaultValue = webModule == null || !fp.isInWebModule(webModule); Project p = null; if (webModule != null) { p = FileOwnerQuery.getOwner(webModule.getDocumentBase()); } pnlConfig = new GWTConfigPanel(p); pnlConfig.enableComponents(defaultValue); pnlConfig.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { fireChangeEvent(); } }); } @Override public void addChangeListener(ChangeListener l) { listeners.add(l); } @Override public void removeChangeListener(ChangeListener l) { listeners.remove(l); } /** * Fires a ChangeEvent. */ private void fireChangeEvent() { final ChangeEvent ev = new ChangeEvent(this); for (final ChangeListener listener : listeners) { listener.stateChanged(ev); } } @Override public JComponent getComponent() { Project project = null; FileObject pom = null; if (webModule != null) { project = FileOwnerQuery.getOwner(webModule.getDocumentBase()); if (project != null) { pom = project.getProjectDirectory().getFileObject( "pom.xml"); // NOI18N } } if (pom == null) { return (JComponent) pnlConfig.getComponent(); } else { return new JPanel(); } } @Override public HelpCtx getHelp() { return null; } @Override public void update() { // TODO: pnlConfig. } @Override public boolean isValid() { return pnlConfig.isValid(); } @Override public Set<FileObject> extend(final WebModule webModule) { // webModule is never null this.webModule = webModule; if (pnlConfig != null) { pnlConfig.setProject(FileOwnerQuery.getOwner( webModule.getDocumentBase())); } final Set<FileObject> toOpen = new HashSet<FileObject>(); try { enableGWT(toOpen); } catch (Exception ex) { GWT4NBUtil.LOGGER.log(Level.SEVERE, "", ex); // NOI18N } return toOpen; } /** * Creates gwt.properties for Ant projects. * * @param projectDir TODO * @param gwtModule TODO * @param gwtLocation TODO * @return gwt.properties */ private static FileObject createGWTProperties(FileObject projectDir, String gwtModule, String gwtLocation) throws IOException { FileObject propFile = projectDir.createData(GWTProjectInfo.GWT_PROPERTIES); String gwtVersion_ = null; // update the default version with the selected for the project if (gwtLocation != null) { String gwtVersion = GWT4NBUtil.findGWTVersion( new File(gwtLocation)); if (gwtVersion != null) { Version ver = new Version(gwtVersion); gwtVersion_ = ver.getVersionPart(0) + "." + // NOI18N ver.getVersionPart(1); } } if (gwtVersion_ == null) { gwtVersion_ = "2.4.0"; // NOI18N } EditableProperties ep = Gwt4nbModule.createGWTProperties(); ep.setProperty("gwt.module", gwtModule); // NOI18N ep.setProperty("gwt.version", gwtVersion_); // NOI18N OutputStream os = propFile.getOutputStream(); try { ep.store(os); } finally { os.close(); } return propFile; } private static String[] getEntryPointModuleName(String entryPointClass) { if (entryPointClass == null) { return null; } int endIndex = entryPointClass.lastIndexOf('.'); assert endIndex > 0; return new String[]{entryPointClass.substring(0, endIndex), entryPointClass.substring(endIndex + 1)}; } private static void createEntryPoint(Project project, final FileObject srcRoot, final String pkg, final String cls, final Set<FileObject> toOpen, Version gwtversion) throws IOException { FileObject folder; if (pkg.length() > 0) { folder = FileUtil.createFolder( srcRoot, pkg.replace('.', '/')); // NOI18N } else { folder = srcRoot; } assert folder != null; FileObject cf = folder.createFolder(CLIENT_FOLDER); toOpen.add(createModule(folder, pkg, cls)); toOpen.add(createJava(project, cf, cls, gwtversion)); } private static void patchBuildXML(FileObject foBuildXML) { //TODO: provide a better implementation GWT4NBUtil.replaceInFile(foBuildXML, "<import file=\"nbproject/build-impl.xml\"/>", // NOI18N "<import file=\"nbproject/build-gwt.xml\"/>" + // NOI18N System.getProperty("line.separator") + // NOI18N "\t<import file=\"nbproject/build-impl.xml\"/>"); // NOI18N } /** * Changes the index.jsp file. Only when there is <h1>JSP Page</h1> string. */ private void patchIndexJSP(FileObject indexjsp, String gwtModule) throws IOException { String nl = System.getProperty("line.separator"); // NOI18N GWT4NBUtil.replaceInFile(indexjsp, "<h1>JSP Page</h1>", // NOI18N "<h1>JSP Page</h1>" + nl + "\t<h3><a href=\"" + // NOI18N GWTProjectInfo.WELCOME_FILE + "\">GWT page</a></h3>" + nl); // NOI18N } private static FileObject createHtml(final FileObject folder, final String pkg, final String cls) throws IOException { assert folder != null; assert folder.isFolder(); assert pkg != null; assert cls != null; FileObject fo = folder.createData("welcomeGWT.html"); // NOI18N FileLock lock = fo.lock(); try { PrintWriter out = new PrintWriter(new OutputStreamWriter(fo.getOutputStream(lock))); try { String gwtOutputSubDir = pkg + '.' + cls; out.println("<!doctype html>"); // NOI18N out.println("<!--"); // NOI18N out.println("The DOCTYPE declaration above will set the browser's rendering engine into"); // NOI18N out.println("\"Standards Mode\". Replacing this declaration with a \"Quirks Mode\" doctype may"); // NOI18N out.println("lead to some differences in layout."); // NOI18N out.println("-->"); // NOI18N out.println("<html>"); // NOI18N out.println(" <head>"); // NOI18N out.println(" <meta name='gwt:module' content='" + gwtOutputSubDir + "=" + gwtOutputSubDir + "'>"); // NOI18N out.println(" <title>" + cls + "</title>"); // NOI18N out.println(" <script type=\"text/javascript\" src=\"" + gwtOutputSubDir + "/" + gwtOutputSubDir + ".nocache.js\"></script>"); // NOI18N out.println(" </head>"); // NOI18N out.println(" <body>"); // NOI18N out.println(" <iframe src=\"javascript:''\" id=\"__gwt_historyFrame\" style=\"width:0;height:0;border:0\"></iframe>"); out.println(" </body>"); // NOI18N out.println("</html>"); // NOI18N } finally { out.close(); } } finally { lock.releaseLock(); } return fo; } /** * Creates GWT module definition. * * @param folder output directory * @param pkg package or null if default client package should be used * @param cls name of the module without package * @return .gwt.xml file * @throws IOException if the file cannot be created/written */ private static FileObject createModule(final FileObject folder, final String pkg, final String cls) throws IOException { assert folder != null; assert folder.isFolder(); assert cls != null; FileObject fo = folder.createData(cls + ".gwt.xml"); // NOI18N String className = getEntryPointClassName(cls); String entryPoint = (pkg != null ? (pkg + '.') : "") + // NOI18N CLIENT_FOLDER + '.' + className; GWT4NBUtil.copyResource("/org/netbeans/modules/gwt4nb/Module.gwt.xml", // NOI18N fo, new String[]{"ENTRY_POINT"}, new String[]{entryPoint}); // NOI18N return fo; } private static FileObject createJava(Project project, final FileObject folder, final String cls, Version gwtversion) throws IOException { assert folder != null; assert folder.isFolder(); assert cls != null; final FileObject jc = FileUtil.getConfigFile(TEMPLATE_JAVA_CLASS); assert jc != null; final DataObject template = DataObject.find(jc); assert template != null; String className = getEntryPointClassName(cls); final Map<String, Object> templateParameters = new HashMap<String, Object>(3); templateParameters.put("gwtversion", gwtversion); // NOI18N DataObject jdo = template.createFromTemplate( DataFolder.findFolder(folder), className, templateParameters); return jdo.getPrimaryFile(); } private static String getEntryPointClassName(String moduleName) { return moduleName + "EntryPoint"; // NOI18N } private void addGWTLibraries(final Project project, final File gwtFolder) throws FileStateInvalidException, UnsupportedOperationException, IOException { String gwtVersion = GWT4NBUtil.findGWTVersion(gwtFolder); if (gwtVersion == null) { GWT4NBUtil.LOGGER.log(Level.SEVERE, "Cannot determine GWT version for {0}", gwtFolder); return; } // ADD LIBRARY Library libUser = LibraryManager.getDefault().getLibrary( LIB_GWT_NAME + gwtVersion); if (libUser == null) { libUser = createGWTUserLibrary(gwtFolder, LIB_GWT_NAME + gwtVersion); } final FileObject sourcesDir = GWTProjectInfo.getSourcesDir(project); if (libUser != null) { // set global GWTLocation GWTSettings.setGWTLocation(gwtFolder); ProjectClassPathModifier.addLibraries(new Library[]{ libUser}, sourcesDir, ClassPath.COMPILE); } else { GWT4NBUtil.LOGGER.warning("Could not add GWT library"); // NOI18N } // final FileObject gwtRtLib = GWT4NBUtil.getGWTDevArchive(gwtFolder); // assert gwtRtLib != null; // final FileObject gwtServletLib = FileUtil.toFileObject( // FileUtil.normalizeFile(new File(gwtFolder, // "gwt-servlet.jar"))); // NOI18N // // ProjectClassPathModifier.addRoots(new URL[]{ // FileUtil.getArchiveRoot(gwtRtLib.toURL())}, sourcesDir, ClassPath.COMPILE); // // ProjectClassPathModifier.addRoots(new URL[]{ // FileUtil.getArchiveRoot(gwtServletLib.toURL())}, // sourcesDir, ClassPath.COMPILE); final EditableProperties projectProps = GWT4NBUtil.getEditableProperties( project, AntProjectHelper.PROJECT_PROPERTIES_PATH); projectProps.setProperty("j2ee.deploy.on.save", "false"); // NOI18N GWT4NBUtil.storeEditableProperties( project, AntProjectHelper.PROJECT_PROPERTIES_PATH, projectProps); } /** * Enables GWT in a web project. * * @param toOpen files that will be opened in the editor are stored here */ private void enableGWT(Set<FileObject> toOpen) throws IOException { Project project = FileOwnerQuery.getOwner(webModule.getDocumentBase()); assert project != null; FileObject pom = project.getProjectDirectory().getFileObject( "pom.xml"); // NOI18N if (pom != null) { extendMavenProject(); } else { extendAntProject(toOpen); } } /** * Extends an Ant based project with GWT * * @param toOpen files that will be opened in the editor are stored here */ private void extendAntProject(Set<FileObject> toOpen) throws IOException { Project project = FileOwnerQuery.getOwner(webModule.getDocumentBase()); assert project != null; ProjectInformation projectInfo = ProjectUtils.getInformation(project); String projectName = projectInfo.getName(); FileObject nbprj = project.getProjectDirectory().getFileObject( GWTProjectInfo.PRJ_DIR); // COPY build-gwt.xml FileObject buildGwt = nbprj.createData(GWTProjectInfo.BUILD_GWT); GWT4NBUtil.copyResource(GWTProjectInfo.RESOURCE_BASE + GWTProjectInfo.BUILD_GWT, buildGwt, new String[]{PATTERN_PRJ_NAME}, new String[]{projectName}); FileObject foBuildXML = nbprj.getParent().getFileObject( "build.xml"); // NOI18N patchBuildXML(foBuildXML); File gwtFolder = pnlConfig.getGwtFolder(); addGWTLibraries(project, gwtFolder); // create entry point class FileObject src = GWTProjectInfo.getSourcesDir(project); String[] epNames = getEntryPointModuleName(pnlConfig.getGWTModule()); if (epNames != null) { assert epNames.length == 2 && epNames[0] != null && epNames[1] != null; final String version = GWT4NBUtil.findGWTVersion(gwtFolder); if (version != null) { createEntryPoint(project, src, epNames[0], epNames[1], toOpen, new Version(version)); } } String gwtLocation; if (System.getProperty("os.name").contains("Windows")) { // NOI18N gwtLocation = gwtFolder.toString().replace("\\", "/"); // NOI18N } else { gwtLocation = gwtFolder.toString(); } GWT4NBUtil.setProjectGWTDir(project, new File(gwtLocation)); createGWTProperties(nbprj, pnlConfig.getGWTModule(), gwtLocation); // this is necessary, because gwt.properties template // does not contain all properties, some of them are only // created in Gwt4nbModule Gwt4nbModule.updateGWTProject(project); if (epNames != null) { toOpen.add(createHtml(webModule.getDocumentBase(), epNames[0], epNames[1])); } FileObject indexJSP = webModule.getDocumentBase().getFileObject( "index.jsp"); // NOI18N if (indexJSP != null && indexJSP.isData() && indexJSP.canRead() && indexJSP.canWrite()) { patchIndexJSP(indexJSP, pnlConfig.getGWTModule()); } else { GWT4NBUtil.LOGGER.warning("Couldn't patch index.jsp"); // NOI18N } updateWelcomePage(webModule); } /** * Extends a Maven project with GWT. */ private void extendMavenProject() { try { Project project = FileOwnerQuery.getOwner(webModule.getDocumentBase()); FileObject pom = project.getProjectDirectory().getFileObject( "pom.xml"); // NOI18N Document pomDoc = GWT4NBUtil.parseXMLFile(pom); extendPOM(pomDoc); FileLock lock = pom.lock(); try { OutputStream os = pom.getOutputStream(lock); try { XMLUtil.write(pomDoc, os, "UTF-8"); // NOI18N } finally { os.close(); } } finally { lock.releaseLock(); } // create entry point class FileObject src = GWTProjectInfo.getSourcesDir(project); String[] epNames = new String[]{ "org.yournamehere", "Main" // NOI18N }; if (src != null) { Set<FileObject> toOpen = new HashSet<FileObject>(); final String version = DEFAULT_GWT_VERSION_MAVEN; createEntryPoint(project, src, epNames[0], epNames[1], toOpen, new Version(version)); } // create welcomeGWT.html createHtml(webModule.getDocumentBase(), epNames[0], epNames[1]); updateWelcomePage(webModule); } catch (Exception ex) { Exceptions.printStackTrace(ex); } } /** * Extends a pom.xml with elements for GWT. * * @param pomDoc pom.xml */ private void extendPOM(Document pomDoc) { Element doce = pomDoc.getDocumentElement(); Element properties = findOrCreate(doce, "properties", POM_ELEMENTS); // NOI18N appendTextElement(properties, "gwt.version", DEFAULT_GWT_VERSION_MAVEN); // NOI18N appendTextElement(properties, "runTarget", "welcomeGWT.html"); // NOI18N Element dependencies = findOrCreate(doce, "dependencies", // NOI18N POM_ELEMENTS); appendDependencyElement(dependencies, "com.google.gwt", // NOI18N "gwt-servlet", "${gwt.version}", "runtime"); // NOI18N appendDependencyElement(dependencies, "com.google.gwt", // NOI18N "gwt-user", "${gwt.version}", "provided"); // NOI18N Element build = findOrCreate(doce, "build", POM_ELEMENTS); // NOI18N Element plugins = findOrCreate(build, "plugins", BUILD_ELEMENTS); // NOI18N Element plugin = pomDoc.createElement("plugin"); // NOI18N plugins.appendChild(plugin); appendTextElement(plugin, "groupId", "org.codehaus.mojo"); // NOI18N appendTextElement(plugin, "artifactId", "gwt-maven-plugin"); // NOI18N appendTextElement(plugin, "version", "1.2"); // NOI18N Element executions = pomDoc.createElement("executions"); // NOI18N plugin.appendChild(executions); Element execution = pomDoc.createElement("execution"); // NOI18N executions.appendChild(execution); Element goals = pomDoc.createElement("goals"); // NOI18N execution.appendChild(goals); appendTextElement(goals, "goal", "compile"); // NOI18N //appendTextElement(goals, "goal", "generateAsync"); appendTextElement(goals, "goal", "test"); // NOI18N Element configuration = pomDoc.createElement( "configuration"); // NOI18N plugin.appendChild(configuration); appendTextElement(configuration, "hostedWebapp", // NOI18N "${project.build.directory}/${project.build.finalName}"); // NOI18N /* This is added to remove javax.servlet classes from WEB-INF/classes http://jira.codehaus.org/browse/MGWT-166 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <executions> <execution> <id>remove-javax</id> <phase>compile</phase> <configuration> <tasks> <delete dir="${project.build.directory}/classes/javax" /> </tasks> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> */ plugin = pomDoc.createElement("plugin"); // NOI18N plugins.appendChild(plugin); appendTextElement(plugin, "groupId", "org.apache.maven.plugins"); // NOI18N appendTextElement(plugin, "artifactId", "maven-antrun-plugin"); // NOI18N executions = pomDoc.createElement("executions"); // NOI18N plugin.appendChild(executions); execution = pomDoc.createElement("execution"); // NOI18N executions.appendChild(execution); appendTextElement(execution, "id", "remove-javax"); // NOI18N appendTextElement(execution, "phase", "compile"); // NOI18N configuration = pomDoc.createElement("configuration"); // NOI18N plugin.appendChild(configuration); Element tasks = pomDoc.createElement("tasks"); // NOI18N configuration.appendChild(tasks); Element delete = pomDoc.createElement("delete"); // NOI18N delete.setAttribute("dir", // NOI18N "${project.build.directory}/classes/javax"); // NOI18N tasks.appendChild(delete); goals = pomDoc.createElement("goals"); // NOI18N execution.appendChild(goals); appendTextElement(goals, "goal", "run"); // NOI18N } /** * Adds a <dependency> element. * * @param dependencies <dependencies> * @param groupId groupId * @param artifactId artifactId * @param version version * @param scope scope * @return created element */ private Element appendDependencyElement(Element dependencies, String groupId, String artifactId, String version, String scope) { Element dependency = dependencies.getOwnerDocument(). createElement("dependency"); // NOI18N dependencies.appendChild(dependency); appendTextElement(dependency, "groupId", groupId); // NOI18N appendTextElement(dependency, "artifactId", artifactId); // NOI18N appendTextElement(dependency, "version", version); // NOI18N appendTextElement(dependency, "scope", scope); // NOI18N return dependency; } /** * Creates a child element with the given text. * * @param parent parent element * @param name name of the child element * @param value text for the child element * @return child element */ private Element appendTextElement(Element parent, String name, String value) { Element e = parent.getOwnerDocument().createElement(name); parent.appendChild(e); Text t = parent.getOwnerDocument(). createTextNode(value); e.appendChild(t); return e; } /** * Searches child elements for one with a partucular name. Creates it if it * does not yet exist. * * @param parent parent element * @param name name of the new element * @param def names of the elements according to DTD (in the right order * @return the found or inserted element */ private Element findOrCreate(Element parent, String name, List<String> def) { NodeList nl = parent.getElementsByTagName(name); if (nl.getLength() > 0) { return (Element) nl.item(0); } else { int index = def.indexOf(name); nl = parent.getElementsByTagName("*"); // NOI18N Element insertBefore = null; for (int i = 0; i < nl.getLength(); i++) { Element el = (Element) nl.item(i); int eindex = def.indexOf(el.getNodeName()); if (eindex > index) { insertBefore = el; break; } } Element e = parent.getOwnerDocument().createElement(name); if (insertBefore != null) { parent.insertBefore(e, insertBefore); } else { parent.appendChild(e); } return e; } } /** * Changes the GWT directory for a project * * @param webModule a web module * @param newGWTDir new GWT directory * @param progressBar here the progress of the operation will be shown */ public static void upgradeGWTVersion( final WebModule webModule, final File newGWTDir) { try { upgradeGWT(webModule, newGWTDir); } catch (Throwable ex) { GWT4NBUtil.unexpectedException(ex); } } /** * Change GWT directory for a project. * * @param webModule web module * @param newGWTDir new GWT directory */ private static void upgradeGWT(final WebModule webModule, File newGWTDir) throws IOException { ProgressHandle ph = ProgressHandleFactory.createHandle( NbBundle.getMessage(GWTWebModuleExtender.class, "ChangingLoc")); // NOI18N ph.start(100); try { Project project = FileOwnerQuery.getOwner( webModule.getDocumentBase()); assert project != null; // find out the old version File oldGWTDir = GWT4NBUtil.getProjectGWTDir(project); String prevGWTVersion = null; if (oldGWTDir != null) { prevGWTVersion = GWT4NBUtil.findGWTVersion(oldGWTDir); } // fetch upgraded GWT version String newGWTVersion = GWT4NBUtil.findGWTVersion(newGWTDir); if (newGWTVersion == null) { GWT4NBUtil.LOGGER.log( Level.SEVERE, "Cannot determine GWT version for {0}", newGWTDir); return; } // update global gwtLocation GWTSettings.setGWTLocation(newGWTDir); // update gwt properties for the project. String newGWTLocation = newGWTDir.toString(); if (System.getProperty("os.name").contains("Windows")) { // NOI18N newGWTLocation = newGWTLocation.replace("\\", "/"); // NOI18N } GWT4NBUtil.setProjectGWTDir(project, new File(newGWTLocation)); final FileObject sourcesDir = GWTProjectInfo.getSourcesDir(project); // Remove reference to the obsolete GWT lib if present. Library libUserWithoutVersion = LibraryManager.getDefault(). getLibrary(LIB_GWT_NAME); if (libUserWithoutVersion != null) { ProjectClassPathModifier.removeLibraries(new Library[]{ libUserWithoutVersion}, sourcesDir, ClassPath.COMPILE); } // Also remove the reference to the previousGWT${version} lib. // prevGwtVersion may be null, but this only results in the library // not being found Library oldLibUser = LibraryManager.getDefault().getLibrary( LIB_GWT_NAME + prevGWTVersion); if (oldLibUser != null) { try { // this sometimes throws the following: // org.netbeans.modules.masterfs.filebasedfs.utils. // FSException: Cannot get exclusive access to // \nbproject\project.properties // (probably opened for reading). ProjectClassPathModifier.removeLibraries(new Library[]{ oldLibUser}, sourcesDir, ClassPath.COMPILE); } catch (Throwable t) { GWT4NBUtil.unexpectedException(t); } } // Add the newly created GWT${version} lib reference. Library newLibUser = LibraryManager.getDefault().getLibrary( LIB_GWT_NAME + newGWTVersion); if (newLibUser == null) { newLibUser = createGWTUserLibrary( newGWTDir, LIB_GWT_NAME + newGWTVersion); } ProjectClassPathModifier.addLibraries(new Library[]{ newLibUser}, sourcesDir, ClassPath.COMPILE); ph.progress(55); // // remove old gwt-dev...jar // FileObject oldGWTDevJar = GWT4NBUtil.getGWTDevArchive(oldGWTDir); // if (oldGWTDevJar != null) { // ProjectClassPathModifier.removeRoots(new URL[]{ // FileUtil.getArchiveRoot(oldGWTDevJar.toURL())}, // sourcesDir, ClassPath.COMPILE); // } // // add new gwt-dev...jar // FileObject newGWTDevJar = GWT4NBUtil.getGWTDevArchive(newGWTDir); // ProjectClassPathModifier.removeRoots(new URL[]{ // FileUtil.getArchiveRoot(newGWTDevJar.toURL())}, // sourcesDir, ClassPath.COMPILE); // ph.progress(75); // // remove old gwt-servlet...jar // FileObject oldGWTServletJar = FileUtil.toFileObject( // FileUtil.normalizeFile(new File(oldGWTDir, // "gwt-servlet.jar"))); // NOI18N // if (oldGWTServletJar != null) { // ProjectClassPathModifier.removeRoots(new URL[]{ // FileUtil.getArchiveRoot(oldGWTServletJar.toURL())}, // sourcesDir, ClassPath.COMPILE); // } // // add new gwt-servlet...jar // FileObject newGWTServletJar = FileUtil.toFileObject( // FileUtil.normalizeFile(new File(newGWTDir, // "gwt-servlet.jar"))); // NOI18N // ProjectClassPathModifier.addRoots(new URL[]{ // FileUtil.getArchiveRoot(newGWTServletJar.toURL())}, // sourcesDir, ClassPath.COMPILE); // write new version to nbproject/gwt.properties GWTProjectInfo info = GWTProjectInfo.get(project); info.setAntProperty("gwt.version", // NOI18N new Version(newGWTVersion). toString(2, 2)); } finally { ph.finish(); } } /** * Creates a GWTXXX library. * * @param gwtFolder GWT directory * @param libname name of the library * @return created library */ private static Library createGWTUserLibrary(File gwtFolder, String libname) throws IOException { assert gwtFolder != null; final File userJar = new File(gwtFolder, GWT_USER); final File servletDepsJar = new File(gwtFolder, GWT_SERVLET_DEPS); final File servletJar = new File(gwtFolder, GWT_SERVLET); final File requestFactoryServerJar = new File(gwtFolder, REQUESTFACTORY_SERVER); ArrayList<URL> lib = new ArrayList<URL>(); if (userJar.exists()) { lib.add(FileUtil.getArchiveRoot(Utilities.toURI(userJar).toURL())); } if (servletDepsJar.exists()) { lib.add(FileUtil.getArchiveRoot(Utilities.toURI(servletDepsJar).toURL())); } if (servletJar.exists()) { lib.add(FileUtil.getArchiveRoot(Utilities.toURI(servletJar).toURL())); } if (requestFactoryServerJar.exists()) { lib.add(FileUtil.getArchiveRoot(Utilities.toURI(requestFactoryServerJar).toURL())); } Map<String, List<URL>> contents = new HashMap<String, List<URL>>(); contents.put("classpath", lib); contents.put("src", lib); final File gwtJavadoc = FileUtil.normalizeFile( new File(new File(gwtFolder, "doc"), "javadoc")); // NOI18N if (gwtJavadoc.exists() && gwtJavadoc.isDirectory() && gwtJavadoc.canRead()) { contents.put("javadoc", Collections.singletonList( // NOI18N Utilities.toURI(gwtJavadoc).toURL())); } return LibraryManager.getDefault().createLibrary("j2se", // NOI18N libname, contents); } /** * Updates the welcome page in the web.xml (adds welcomeGWT.html). * * @param webModule web module */ private void updateWelcomePage(WebModule webModule) throws IOException { FileObject dd = webModule.getDeploymentDescriptor(); if (dd != null) { WebApp ddRoot = DDProvider.getDefault().getDDRoot(dd); if (ddRoot != null) { try { WelcomeFileList welcomeFiles = ddRoot. getSingleWelcomeFileList(); if (welcomeFiles == null) { welcomeFiles = (WelcomeFileList) ddRoot.createBean( "WelcomeFileList"); // NOI18N ddRoot.setWelcomeFileList(welcomeFiles); } // this "if" (but not it's content) // is only a workaround for // https://netbeans.org/bugzilla/show_bug.cgi?id=178900 if (welcomeFiles != null) { if (welcomeFiles.sizeWelcomeFile() == 0) { String welcomePage = GWTProjectInfo.WELCOME_FILE; welcomeFiles.addWelcomeFile(welcomePage); // NOI18N } } ddRoot.write(dd); } catch (ClassNotFoundException e) { GWT4NBUtil.LOGGER.log(Level.SEVERE, "", e); // NOI18N } } } } }