diff --git a/maven.j2ee/nbproject/project.xml b/maven.j2ee/nbproject/project.xml --- a/maven.j2ee/nbproject/project.xml +++ b/maven.j2ee/nbproject/project.xml @@ -263,7 +263,7 @@ 2 - 2.88 + 2.97 diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ExecutionChecker.java b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ExecutionChecker.java --- a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ExecutionChecker.java +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ExecutionChecker.java @@ -41,41 +41,23 @@ */ package org.netbeans.modules.maven.j2ee; -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.concurrent.Callable; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.apache.maven.model.Build; import org.netbeans.api.project.Project; -import org.netbeans.api.project.ProjectUtils; import org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment; import org.netbeans.modules.j2ee.deployment.devmodules.api.InstanceRemovedException; import org.netbeans.modules.j2ee.deployment.devmodules.api.ServerInstance; import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider; -import org.netbeans.modules.j2ee.deployment.plugins.api.ServerDebugInfo; import org.netbeans.modules.maven.api.NbMavenProject; import org.netbeans.modules.maven.api.execute.ExecutionContext; import org.netbeans.modules.maven.api.execute.ExecutionResultChecker; import org.netbeans.modules.maven.api.execute.PrerequisitesChecker; import org.netbeans.modules.maven.api.execute.RunConfig; -import org.netbeans.modules.maven.api.execute.RunUtils; import org.netbeans.modules.maven.j2ee.ui.SelectAppServerPanel; -import org.netbeans.modules.maven.j2ee.ui.customizer.impl.CustomizerRunWeb; -import org.netbeans.modules.maven.j2ee.utils.MavenProjectSupport; -import org.netbeans.modules.maven.spi.debug.MavenDebugger; -import org.netbeans.modules.web.browser.spi.URLDisplayerImplementation; import org.netbeans.spi.project.ProjectServiceProvider; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; -import org.openide.awt.HtmlBrowser; -import org.openide.filesystems.FileObject; -import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; -import org.openide.windows.OutputWriter; import static org.netbeans.modules.maven.j2ee.Bundle.*; +import org.netbeans.modules.maven.j2ee.execution.DeploymentHelper; import org.openide.util.Exceptions; @@ -94,14 +76,11 @@ public class ExecutionChecker implements ExecutionResultChecker, PrerequisitesChecker { public static final String CLIENTURLPART = "netbeans.deploy.clientUrlPart"; //NOI18N - public static final String MODULEURI = "netbeans.deploy.clientModuleUri"; //NOI18N public static final String DEV_NULL = "DEV-NULL"; //NOI18N - private static final Logger LOGGER = Logger.getLogger(ExecutionChecker.class.getName()); - private static final String NB_COS = ".netbeans_automatic_build"; //NOI18N private final Project project; - + public ExecutionChecker(Project prj) { project = prj; @@ -112,151 +91,10 @@ public void executionResult(RunConfig config, ExecutionContext res, int resultCode) { boolean depl = Boolean.parseBoolean(config.getProperties().get(MavenJavaEEConstants.ACTION_PROPERTY_DEPLOY)); if (depl && resultCode == 0) { - if (RunUtils.hasApplicationCompileOnSaveEnabled(config)) { - //dump the nb java support's timestamp fil in output directory.. - touchCoSTimeStamp(config, System.currentTimeMillis()); - } - String moduleUri = config.getProperties().get(MODULEURI); - String clientUrl = config.getProperties().get(CLIENTURLPART); - if (clientUrl == null) { - clientUrl = ""; // NOI18N - } - String _redeploy = config.getProperties().get(MavenJavaEEConstants.ACTION_PROPERTY_DEPLOY_REDEPLOY); - boolean redeploy = _redeploy != null ? Boolean.parseBoolean(_redeploy) : true; - boolean debugmode = Boolean.parseBoolean(config.getProperties().get(MavenJavaEEConstants.ACTION_PROPERTY_DEPLOY_DEBUG_MODE)); - boolean profilemode = Boolean.parseBoolean(config.getProperties().get("netbeans.deploy.profilemode")); //NOI18N - String openInBrowser = config.getProperties().get(MavenJavaEEConstants.ACTION_PROPERTY_DEPLOY_OPEN); - boolean showInBrowser = openInBrowser == null ? true : Boolean.parseBoolean(openInBrowser); - - performDeploy(res, debugmode, profilemode, moduleUri, clientUrl, redeploy, showInBrowser); + DeploymentHelper.perform(config, res); } } - private void performDeploy( - final ExecutionContext res, - boolean debugmode, - boolean profilemode, - String clientModuleUri, - String clientUrlPart, - boolean forceRedeploy, - boolean showInBrowser) { - - FileUtil.refreshFor(FileUtil.toFile(project.getProjectDirectory())); - OutputWriter err = res.getInputOutput().getErr(); - OutputWriter out = res.getInputOutput().getOut(); - final J2eeModuleProvider jmp = project.getLookup().lookup(J2eeModuleProvider.class); - if (jmp == null) { - err.println(); - err.println(); - err.println("NetBeans: Application Server deployment not available for Maven project '" + ProjectUtils.getInformation(project).getDisplayName() + "'"); // NOI18N - return; - } - - String serverInstanceID = null; - - // First check if the one-time deployment server is set - OneTimeDeployment oneTimeDeployment = project.getLookup().lookup(OneTimeDeployment.class); - if (oneTimeDeployment != null) { - serverInstanceID = oneTimeDeployment.getServerInstanceId(); - } - - if (serverInstanceID == null) { - serverInstanceID = jmp.getServerInstanceID(); - if (DEV_NULL.equals(serverInstanceID) || serverInstanceID == null) { - err.println(); - err.println(); - err.println("NetBeans: No suitable Deployment Server is defined for the project or globally."); // NOI18N - return; - } - } - ServerInstance si = Deployment.getDefault().getServerInstance(serverInstanceID); - try { - out.println("NetBeans: Deploying on " + (si != null ? si.getDisplayName() : serverInstanceID)); //NOI18N - no localization in maven build now. - } catch (InstanceRemovedException ex) { - out.println("NetBeans: Deploying on " + serverInstanceID); // NOI18N - } - try { - out.println(" profile mode: " + profilemode); // NOI18N - out.println(" debug mode: " + debugmode); // NOI18N - out.println(" force redeploy: " + forceRedeploy); //NOI18N - - - Deployment.Mode mode = Deployment.Mode.RUN; - if (debugmode) { - mode = Deployment.Mode.DEBUG; - } else if (profilemode) { - mode = Deployment.Mode.PROFILE; - } - - Callable debuggerHook = null; - if (debugmode) { - debuggerHook = new Callable() { - - @Override - public Void call() throws Exception { - ServerDebugInfo sdi = jmp.getServerDebugInfo(); - - if (sdi != null) { //fix for bug 57854, this can be null - String h = sdi.getHost(); - String transport = sdi.getTransport(); - String address; - - if (transport.equals(ServerDebugInfo.TRANSPORT_SHMEM)) { - address = sdi.getShmemName(); - } else { - address = Integer.toString(sdi.getPort()); - } - MavenDebugger deb = project.getLookup().lookup(MavenDebugger.class); - try { - deb.attachDebugger(res.getInputOutput(), "Debug Deployed app", transport, h, address); // NOI18N - } catch (Exception ex) { - // See issue #235796 --> We were not able to attach debugger because - // it's already attached, BUT we still want to deploy the application - LOGGER.log(Level.FINE, "Exception occured while trying to attach debugger", ex); //NOI18N - } - } - return null; - } - }; - - } - - String clientUrl = Deployment.getDefault().deploy(jmp, mode, clientModuleUri, - clientUrlPart, forceRedeploy, new DLogger(out), debuggerHook); - if (clientUrl != null) { - FileObject fo = project.getProjectDirectory(); - boolean show = showInBrowser; - if (fo != null && show) { - String browser = (String) fo.getAttribute(CustomizerRunWeb.PROP_SHOW_IN_BROWSER); - show = browser != null ? Boolean.parseBoolean(browser) : true; - } - if (show) { - URL url = new URL(clientUrl); - URLDisplayerImplementation urlDisplayer = project.getLookup().lookup(URLDisplayerImplementation.class); - if (urlDisplayer != null) { - URL appRoot = url; - if (clientUrlPart != null && clientUrlPart.length() > 0) { - if (clientUrl.endsWith(clientUrlPart)) { - appRoot = new URL(clientUrl.substring(0, clientUrl.length() - clientUrlPart.length())); - } - } - urlDisplayer.showURL(appRoot, url, fo); - } else { - HtmlBrowser.URLDisplayer.getDefault().showURL(url); - } - } - } - } catch (Deployment.DeploymentException | MalformedURLException ex) { - LOGGER.log(Level.FINE, "Exception occured wile deploying to Application Server.", ex); //NOI18N - } - - // Reset the value of the one-time server - if (oneTimeDeployment != null) { - oneTimeDeployment.reset(); - MavenProjectSupport.changeServer(project, false); - } - } - @Override public boolean checkRunConfig(RunConfig config) { if (!isSupported()) { // #234767 @@ -316,52 +154,4 @@ } return serverInstanceID; } - - private boolean touchCoSTimeStamp(RunConfig rc, long stamp) { - if (rc.getProject() == null) { - return false; - } - Build build = rc.getMavenProject().getBuild(); - if (build == null || build.getOutputDirectory() == null) { - return false; - } - File fl = new File(build.getOutputDirectory()); - fl = FileUtil.normalizeFile(fl); - if (!fl.exists()) { - //the project was not built - return false; - } - File check = new File(fl, NB_COS); - if (!check.exists()) { - try { - return check.createNewFile(); - } catch (IOException ex) { - return false; - } - } - return check.setLastModified(stamp); - } - - public static boolean hasCoSTimeStamp(Project prj) { - NbMavenProject nbprj = prj.getLookup().lookup(NbMavenProject.class); - if (nbprj == null) { - return false; - } - return new File(nbprj.getOutputDirectory(false), NB_COS).exists(); - } - - - static class DLogger implements Deployment.Logger { - - private final OutputWriter logger; - - public DLogger(OutputWriter log) { - logger = log; - } - - @Override - public void log(String string) { - logger.println(string); - } - } } diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/J2EEPrerequisitesChecker.java b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/J2EEPrerequisitesChecker.java --- a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/J2EEPrerequisitesChecker.java +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/J2EEPrerequisitesChecker.java @@ -54,6 +54,8 @@ import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider; import org.netbeans.modules.maven.api.NbMavenProject; import org.netbeans.modules.maven.api.execute.LateBoundPrerequisitesChecker; +import org.netbeans.modules.maven.j2ee.execution.DeploymentLogger; +import static org.netbeans.modules.maven.j2ee.ui.customizer.impl.CustomizerRunWeb.PROP_ALWAYS_BUILD_BEFORE_RUNNING; import org.netbeans.spi.project.ActionProvider; import org.netbeans.spi.project.ProjectServiceProvider; import org.openide.util.Exceptions; @@ -86,6 +88,16 @@ @Override public boolean checkRunConfig(RunConfig config) { + // To be able to skip standard run behavior we need to set this property + // with respect to the current CoS/DoS setting --> See issue 230565 + Boolean alwaysBuild = (Boolean) config.getProject().getProjectDirectory().getAttribute(PROP_ALWAYS_BUILD_BEFORE_RUNNING); + if (alwaysBuild == null) { + alwaysBuild = Boolean.FALSE; + } + + // If we don't want to build always, set skip.build property + config.setInternalProperty("skip.build", !alwaysBuild); //NOI18N + String actionName = config.getActionName(); if (!applicableActions.contains(actionName)) { return true; @@ -134,7 +146,7 @@ return true; } try { - Deployment.getDefault ().undeploy(provider, false, new ExecutionChecker.DLogger(con.getInputOutput().getOut())); + Deployment.getDefault ().undeploy(provider, false, new DeploymentLogger(con.getInputOutput().getOut())); } catch (DeploymentException ex) { Exceptions.printStackTrace(ex); } diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/execution/AlternativeExecutorImpl.java b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/execution/AlternativeExecutorImpl.java new file mode 100644 --- /dev/null +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/execution/AlternativeExecutorImpl.java @@ -0,0 +1,86 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, 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-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2013 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.maven.j2ee.execution; + +import org.netbeans.modules.maven.api.NbMavenProject; +import org.netbeans.modules.maven.api.execute.ExecutionContext; +import org.netbeans.modules.maven.api.execute.RunConfig; +import org.netbeans.modules.maven.spi.execute.AlternativeExecutorImplementation; +import org.netbeans.spi.project.ProjectServiceProvider; + +/** + * Implementation of the {@link AlternativeExecutorImplementation} enables to changes the default run/debug/profile + * behavior and does not force rebuild of application when one of these action is invoked. + * + *

+ * In combination with CoS/DoS feature this save time that was earlier needed for rebuild + * application started before actual redeployment. + * + *

+ * See issue 230565 for some details about why this was needed. + * + *

+ * This class is immutable and thus thread safe. + * + * @author Martin Janicek + * @since 2.97 + */ +@ProjectServiceProvider( + service = { + AlternativeExecutorImplementation.class + }, + projectType = { + "org-netbeans-modules-maven/" + NbMavenProject.TYPE_WAR, + "org-netbeans-modules-maven/" + NbMavenProject.TYPE_EJB, + "org-netbeans-modules-maven/" + NbMavenProject.TYPE_APPCLIENT, + "org-netbeans-modules-maven/" + NbMavenProject.TYPE_EAR, + "org-netbeans-modules-maven/" + NbMavenProject.TYPE_OSGI + } +) +public class AlternativeExecutorImpl implements AlternativeExecutorImplementation { + + @Override + public boolean execute(RunConfig config, ExecutionContext executionContext) { + return DeploymentHelper.perform(config, executionContext); + } +} diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/execution/DeploymentHelper.java b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/execution/DeploymentHelper.java new file mode 100644 --- /dev/null +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/execution/DeploymentHelper.java @@ -0,0 +1,287 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, 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-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2013 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.maven.j2ee.execution; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.concurrent.Callable; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apache.maven.model.Build; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectUtils; +import org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment; +import org.netbeans.modules.j2ee.deployment.devmodules.api.InstanceRemovedException; +import org.netbeans.modules.j2ee.deployment.devmodules.api.ServerInstance; +import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider; +import org.netbeans.modules.j2ee.deployment.plugins.api.ServerDebugInfo; +import org.netbeans.modules.maven.api.execute.ExecutionContext; +import org.netbeans.modules.maven.api.execute.RunConfig; +import org.netbeans.modules.maven.api.execute.RunUtils; +import static org.netbeans.modules.maven.j2ee.ExecutionChecker.DEV_NULL; +import org.netbeans.modules.maven.j2ee.MavenJavaEEConstants; +import org.netbeans.modules.maven.j2ee.OneTimeDeployment; +import org.netbeans.modules.maven.j2ee.ui.customizer.impl.CustomizerRunWeb; +import org.netbeans.modules.maven.j2ee.utils.MavenProjectSupport; +import org.netbeans.modules.maven.spi.debug.MavenDebugger; +import org.netbeans.modules.web.browser.spi.URLDisplayerImplementation; +import org.openide.awt.HtmlBrowser; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.windows.OutputWriter; + +/** + * General helper class encapsulating behavior needed to perform deployment execution. + * + *

+ * This class is immutable and thus thread safe. + *

+ * + * @author Martin Janicek + */ +public final class DeploymentHelper { + + private static final String MODULEURI = "netbeans.deploy.clientModuleUri"; //NOI18N + private static final String NB_COS = ".netbeans_automatic_build"; //NOI18N + private static final Logger LOGGER = Logger.getLogger(DeploymentHelper.class.getName()); + + public static final String CLIENTURLPART = "netbeans.deploy.clientUrlPart"; //NOI18N + + private DeploymentHelper() { + } + + + /** + * Performs deploy based on the given arguments. + * + * @param config configuration + * @param executionContext execution context + * @return {@code true} if the execution was successful, {@code false} otherwise + */ + public static boolean perform(final RunConfig config, final ExecutionContext executionContext) { + final Project project = config.getProject(); + + if (RunUtils.isCompileOnSaveEnabled(config)) { + //dump the nb java support's timestamp fil in output directory.. + touchCoSTimeStamp(config, System.currentTimeMillis()); + } + String moduleUri = config.getProperties().get(MODULEURI); + String clientUrlPart = config.getProperties().get(CLIENTURLPART); + if (clientUrlPart == null) { + clientUrlPart = ""; // NOI18N + } + boolean redeploy = isRedeploy(config); + boolean debugmode = isDebugMode(config); + boolean profilemode = isProfileMode(config); + boolean showInBrowser = showInBrowser(config); + + FileUtil.refreshFor(FileUtil.toFile(project.getProjectDirectory())); + OutputWriter err = executionContext.getInputOutput().getErr(); + OutputWriter out = executionContext.getInputOutput().getOut(); + final J2eeModuleProvider jmp = project.getLookup().lookup(J2eeModuleProvider.class); + if (jmp == null) { + err.println(); + err.println(); + err.println("NetBeans: Application Server deployment not available for Maven project '" + ProjectUtils.getInformation(project).getDisplayName() + "'"); // NOI18N + return false; + } + + String serverInstanceID = null; + + // First check if the one-time deployment server is set + OneTimeDeployment oneTimeDeployment = project.getLookup().lookup(OneTimeDeployment.class); + if (oneTimeDeployment != null) { + serverInstanceID = oneTimeDeployment.getServerInstanceId(); + } + + if (serverInstanceID == null) { + serverInstanceID = jmp.getServerInstanceID(); + if (DEV_NULL.equals(serverInstanceID) || serverInstanceID == null) { + err.println(); + err.println(); + err.println("NetBeans: No suitable Deployment Server is defined for the project or globally."); // NOI18N + return false; + } + } + ServerInstance si = Deployment.getDefault().getServerInstance(serverInstanceID); + try { + out.println("NetBeans: Deploying on " + (si != null ? si.getDisplayName() : serverInstanceID)); //NOI18N - no localization in maven build now. + } catch (InstanceRemovedException ex) { + out.println("NetBeans: Deploying on " + serverInstanceID); // NOI18N + } + try { + out.println(" profile mode: " + profilemode); // NOI18N + out.println(" debug mode: " + debugmode); // NOI18N + out.println(" force redeploy: " + redeploy); //NOI18N + + + Deployment.Mode mode = Deployment.Mode.RUN; + if (debugmode) { + mode = Deployment.Mode.DEBUG; + } else if (profilemode) { + mode = Deployment.Mode.PROFILE; + } + + Callable debuggerHook = null; + if (debugmode) { + debuggerHook = new Callable() { + + @Override + public Void call() throws Exception { + ServerDebugInfo sdi = jmp.getServerDebugInfo(); + + if (sdi != null) { //fix for bug 57854, this can be null + String h = sdi.getHost(); + String transport = sdi.getTransport(); + String address; + + if (transport.equals(ServerDebugInfo.TRANSPORT_SHMEM)) { + address = sdi.getShmemName(); + } else { + address = Integer.toString(sdi.getPort()); + } + MavenDebugger deb = project.getLookup().lookup(MavenDebugger.class); + try { + deb.attachDebugger(executionContext.getInputOutput(), "Debug Deployed app", transport, h, address); // NOI18N + } catch (Exception ex) { + // See issue #235796 --> We were not able to attach debugger because + // it's already attached, BUT we still want to deploy the application + LOGGER.log(Level.FINE, "Exception occured while trying to attach debugger", ex); //NOI18N + } + } + return null; + } + }; + + } + + String clientUrl = Deployment.getDefault().deploy(jmp, mode, moduleUri, clientUrlPart, redeploy, new DeploymentLogger(out), debuggerHook); + if (clientUrl != null) { + if (showInBrowser) { + URL url = new URL(clientUrl); + URLDisplayerImplementation urlDisplayer = project.getLookup().lookup(URLDisplayerImplementation.class); + if (urlDisplayer != null) { + URL appRoot = url; + if (clientUrlPart.length() > 0 && clientUrl.endsWith(clientUrlPart)) { + appRoot = new URL(clientUrl.substring(0, clientUrl.length() - clientUrlPart.length())); + } + urlDisplayer.showURL(appRoot, url, project.getProjectDirectory()); + } else { + HtmlBrowser.URLDisplayer.getDefault().showURL(url); + } + } + } + } catch (Deployment.DeploymentException | MalformedURLException ex) { + LOGGER.log(Level.FINE, "Exception occured wile deploying to Application Server.", ex); //NOI18N + } + + // Reset the value of the one-time server + if (oneTimeDeployment != null) { + oneTimeDeployment.reset(); + MavenProjectSupport.changeServer(project, false); + } + return true; + } + + private static boolean isRedeploy(RunConfig config) { + return readBooleanValue(config, MavenJavaEEConstants.ACTION_PROPERTY_DEPLOY_REDEPLOY, true); + } + + private static boolean isDebugMode(RunConfig config) { + return readBooleanValue(config, MavenJavaEEConstants.ACTION_PROPERTY_DEPLOY_DEBUG_MODE, false); + } + + private static boolean isProfileMode(RunConfig config) { + return readBooleanValue(config, "netbeans.deploy.profilemode", false); //NOI18N + } + + private static boolean showInBrowser(RunConfig config) { + if (!readBooleanValue(config, MavenJavaEEConstants.ACTION_PROPERTY_DEPLOY_OPEN, true)) { + return false; + } + + FileObject projectDir = config.getProject().getProjectDirectory(); + if (projectDir != null) { + String browser = (String) projectDir.getAttribute(CustomizerRunWeb.PROP_SHOW_IN_BROWSER); + if (browser != null && Boolean.parseBoolean(browser)) { + return false; + } + } + return true; + } + + private static boolean readBooleanValue(RunConfig config, String key, boolean defaultValue) { + String value = config.getProperties().get(key); + if (value != null) { + return Boolean.parseBoolean(value); + } + return defaultValue; + } + + private static boolean touchCoSTimeStamp(RunConfig rc, long stamp) { + if (rc.getProject() == null) { + return false; + } + Build build = rc.getMavenProject().getBuild(); + if (build == null || build.getOutputDirectory() == null) { + return false; + } + File fl = new File(build.getOutputDirectory()); + fl = FileUtil.normalizeFile(fl); + if (!fl.exists()) { + //the project was not built + return false; + } + File check = new File(fl, NB_COS); + if (!check.exists()) { + try { + return check.createNewFile(); + } catch (IOException ex) { + return false; + } + } + return check.setLastModified(stamp); + } +} diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/execution/DeploymentLogger.java b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/execution/DeploymentLogger.java new file mode 100644 --- /dev/null +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/execution/DeploymentLogger.java @@ -0,0 +1,69 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, 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-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2013 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.maven.j2ee.execution; + +import org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment; +import org.openide.windows.OutputWriter; + +/** + * Simple implementation of the {@link Deployment.Logger} used by the infrastructure to log deployment messages. + * + *

+ * This class is immutable and thus thread safe. + *

+ * + * @author Martin Janicek + */ +public class DeploymentLogger implements Deployment.Logger { + + private final OutputWriter logger; + + public DeploymentLogger(OutputWriter logger) { + this.logger = logger; + } + + @Override + public void log(String string) { + logger.println(string); + } +} diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/BaseRunCustomizer.java b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/BaseRunCustomizer.java --- a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/BaseRunCustomizer.java +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/BaseRunCustomizer.java @@ -57,8 +57,12 @@ import org.netbeans.modules.maven.j2ee.ExecutionChecker; import org.netbeans.modules.maven.j2ee.utils.Server; import static org.netbeans.modules.maven.j2ee.ui.customizer.Bundle.*; +import org.netbeans.modules.maven.j2ee.ui.util.WarningPanel; +import org.netbeans.modules.maven.j2ee.ui.util.WarningPanelSupport; import org.netbeans.modules.maven.j2ee.utils.MavenProjectSupport; import org.netbeans.modules.maven.j2ee.utils.ServerUtils; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; import org.openide.util.HelpCtx; import org.openide.util.NbBundle.Messages; @@ -79,15 +83,46 @@ this.project = project; } + @Messages({ + "WARNING_ChangingAutomaticBuild=You are trying to turn deploy on save feature off. Please be aware about " + + "possible consequences. Your files won't be redeployed immediately after the save which means you " + + "will be responsible for redeployment of the application content every time when you want to see actual " + + "state of sources on server.

Because of that it is highly recommended to turn option called \"Always " + + "perform build\" on, so you will need only to Run application and NetBeans will take care about automatic rebuild " + + "of sources before deployment.." + }) protected void initDeployOnSave(final JCheckBox dosCheckBox, final JLabel dosDescription) { boolean isDoS = MavenProjectSupport.isDeployOnSave(project); - deployOnSaveUpdater = CheckBoxUpdater.create(dosCheckBox, isDoS, new CheckBoxUpdater.Store() { + + CheckBoxUpdater.Store store = new CheckBoxUpdater.Store() { @Override public void storeValue(boolean value) { MavenProjectSupport.setDeployOnSave(project, value); } - }); + }; + + CheckBoxUpdater.Verify verifier = new CheckBoxUpdater.Verify() { + + @Override + public boolean verifyValue(boolean value) { + if (!value && WarningPanelSupport.isAutomaticBuildWarningActivated()) { + WarningPanel panel = new WarningPanel(WARNING_ChangingAutomaticBuild()); + NotifyDescriptor dd = new NotifyDescriptor.Confirmation(panel, NotifyDescriptor.OK_CANCEL_OPTION); + DialogDisplayer.getDefault().notify(dd); + + if (dd.getValue() == NotifyDescriptor.CANCEL_OPTION) { + return false; + } + if (panel.disabledWarning()) { + WarningPanelSupport.dontShowAutomaticBuildWarning(); + } + } + return true; + } + }; + + deployOnSaveUpdater = CheckBoxUpdater.create(dosCheckBox, isDoS, store, verifier); addAncestorListener(new AncestorListener() { diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/CheckBoxUpdater.java b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/CheckBoxUpdater.java --- a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/CheckBoxUpdater.java +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/CheckBoxUpdater.java @@ -66,6 +66,7 @@ * * @see ComboBoxUpdater * @see Store + * @see Verify * * @author Martin Janicek */ @@ -89,8 +90,27 @@ void storeValue(boolean value); } + /** + * Interface used by the updater to verify if the new value can be stored in the combo box. + *

+ * + * Please be aware that if this method returns {@code false}, the {@link Store#storeValue(java.lang.Object)} + * won't be called. + */ + public interface Verify { + + /** + * Verifies value given by the parameter. + * + * @param value to be verified + * @return {@code true} if the value is OK, {@code false} otherwise + */ + boolean verifyValue(boolean value); + } + private final Store store; + private final Verify verifier; private final JCheckBox checkBox; private final boolean defaultValue; @@ -103,18 +123,40 @@ * be called. * * @param checkBox we want to decorate + * @param defaultValue default value for the check box * @param store implementation used to store check box value - * @param defaultValue default value for the check box * @return instance of the {@link CheckBoxUpdater} */ public static CheckBoxUpdater create(JCheckBox checkBox, boolean defaultValue, Store store) { - CheckBoxUpdater instance = new CheckBoxUpdater(checkBox, defaultValue, store); + return create(checkBox, defaultValue, store, null); + } + + /** + * Creates an instance of the {@link CheckBoxUpdater}. + * + *

+ * The check box will be initialized using the given default value. If the client + * want to store current value, {@link CheckBoxUpdater#storeValue()} method has to + * be called. + * + *

+ * For the value verification, pass instance of {@link CheckBoxUpdater.Verify} which + * will be called before the new value will be set into the check box. + * + * @param checkBox we want to decorate + * @param defaultValue default value for the check box + * @param store implementation used to store check box value + * @param verifier implementation used to verify new check box value + * @return instance of the {@link CheckBoxUpdater} + */ + public static CheckBoxUpdater create(JCheckBox checkBox, boolean defaultValue, Store store, Verify verifier) { + CheckBoxUpdater instance = new CheckBoxUpdater(checkBox, defaultValue, store, verifier); instance.checkBox.addItemListener(instance); return instance; } - private CheckBoxUpdater(JCheckBox checkBox, boolean defaultValue, Store store) { + private CheckBoxUpdater(JCheckBox checkBox, boolean defaultValue, Store store, Verify verifier) { assert (checkBox != null); assert (store != null); @@ -122,6 +164,7 @@ this.checkBox.setSelected(defaultValue); this.defaultValue = defaultValue; this.store = store; + this.verifier = verifier; setValue(defaultValue); } @@ -138,11 +181,27 @@ @Override public void itemStateChanged(ItemEvent e) { - setValue(checkBox.isSelected()); + if (ItemEvent.DESELECTED == e.getStateChange()) { + boolean isSelected = checkBox.isSelected(); + if (verifier != null) { + if (verifier.verifyValue(isSelected)) { + setValue(isSelected); + } + } else { + // If there is no defined verifier, simply change the value + setValue(isSelected); + } + } } @NbBundle.Messages("MSG_CheckBox_Value_Changed=This value had been changed from the default one") private void setValue(boolean value) { + // We don't want to notify listeners about state changes made in this method + ItemListener[] itemListeners = checkBox.getItemListeners(); + for (ItemListener listener : itemListeners) { + checkBox.removeItemListener(listener); + } + if (defaultValue == value) { checkBox.setFont(checkBox.getFont().deriveFont(Font.PLAIN)); checkBox.setToolTipText(null); @@ -150,5 +209,11 @@ checkBox.setFont(checkBox.getFont().deriveFont(Font.BOLD)); checkBox.setToolTipText(MSG_CheckBox_Value_Changed()); } + checkBox.setSelected(value); + + // Register listeners back to have them consistent + for (ItemListener listener : itemListeners) { + checkBox.addItemListener(listener); + } } } diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/Bundle.properties b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/Bundle.properties --- a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/Bundle.properties +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/Bundle.properties @@ -53,3 +53,6 @@ CustomizerRunWeb.jCBCopyStaticResources.toolTipText=If selected, static resources (like jsp, html etc.) are copied to the target directory when you save them. CustomizerRunWeb.jCBCopyStaticResources.text=Copy Static Resources on Save CustomizerRunWeb.jCBDeployOnSave.text=D&eploy on Save +CustomizerRunWeb.jCBAlwaysBuild.toolTipText=If selected, IDE will perform mvn package everytime when running application +CustomizerRunWeb.jCBAlwaysBuild.text=Always perform build before running application +CustomizerRunWeb.btnLearnMore.text=Learn More about Deploy On Save feature in Maven projects diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/CustomizerRunWeb.form b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/CustomizerRunWeb.form --- a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/CustomizerRunWeb.form +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/CustomizerRunWeb.form @@ -38,17 +38,24 @@ - - - - - - - + + + + + + + + + + + + + + @@ -94,6 +101,10 @@ + + + + @@ -234,5 +245,25 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/CustomizerRunWeb.java b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/CustomizerRunWeb.java --- a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/CustomizerRunWeb.java +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/customizer/impl/CustomizerRunWeb.java @@ -43,7 +43,12 @@ package org.netbeans.modules.maven.j2ee.ui.customizer.impl; import java.awt.Component; +import java.awt.Cursor; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; import java.util.List; import java.util.Set; import java.util.TreeSet; @@ -83,6 +88,7 @@ import org.netbeans.spi.project.ActionProvider; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; +import org.openide.awt.HtmlBrowser; import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; @@ -95,11 +101,13 @@ public class CustomizerRunWeb extends BaseRunCustomizer { public static final String PROP_SHOW_IN_BROWSER = "netbeans.deploy.showBrowser"; //NOI18N + public static final String PROP_ALWAYS_BUILD_BEFORE_RUNNING = "netbeans.always.build"; // NOI18N private static final Set WEB_PROFILES; private static final Set FULL_PROFILES; private final CheckBoxUpdater copyStaticResourcesUpdater; private final CheckBoxUpdater showBrowserUpdater; + private final CheckBoxUpdater alwaysBuildUpdater; private final ComboBoxUpdater versionUpdater; private final boolean noServer; @@ -141,6 +149,18 @@ super(handle, project); initComponents(); + btnLearnMore.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + btnLearnMore.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + HtmlBrowser.URLDisplayer.getDefault().showURL(new URL("http://wiki.netbeans.org/FaqDeployOnSave")); + } catch (MalformedURLException ex) { + Exceptions.printStackTrace(ex); + } + } + }); + module = WebModule.getWebModule(project.getProjectDirectory()); if (module != null) { contextPathTField.setText(module.getContextPath()); @@ -178,6 +198,26 @@ } }); + Boolean alwaysBuild = (Boolean) project.getProjectDirectory().getAttribute(PROP_ALWAYS_BUILD_BEFORE_RUNNING); + if (alwaysBuild == null) { + alwaysBuild = Boolean.FALSE; + } + alwaysBuildUpdater = CheckBoxUpdater.create(jCBAlwaysBuild, alwaysBuild, new CheckBoxUpdater.Store() { + + @Override + public void storeValue(boolean value) { + try { + if (value) { + project.getProjectDirectory().setAttribute(PROP_ALWAYS_BUILD_BEFORE_RUNNING, true); + } else { + project.getProjectDirectory().setAttribute(PROP_ALWAYS_BUILD_BEFORE_RUNNING, false); + } + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + }); + versionUpdater = createVersionUpdater(J2eeModule.Type.WAR); } @@ -198,6 +238,7 @@ serverUpdater.storeValue(); versionUpdater.storeValue(); + alwaysBuildUpdater.storeValue(); deployOnSaveUpdater.storeValue(); copyStaticResourcesUpdater.storeValue(); @@ -297,7 +338,7 @@ public boolean verifyValue(Object value) { if (WarningPanelSupport.isJavaEEChangeWarningActivated()) { WarningPanel panel = new WarningPanel(WARNING_ChangingJavaEEVersion()); - NotifyDescriptor dd = new NotifyDescriptor.Message(panel, NotifyDescriptor.OK_CANCEL_OPTION); + NotifyDescriptor dd = new NotifyDescriptor.Confirmation(panel, NotifyDescriptor.OK_CANCEL_OPTION); DialogDisplayer.getDefault().notify(dd); if (dd.getValue() == NotifyDescriptor.CANCEL_OPTION) { @@ -402,6 +443,8 @@ browserLabel = new javax.swing.JLabel(); jCBBrowser = createBrowserComboBox(); jCBCopyStaticResources = new javax.swing.JCheckBox(); + jCBAlwaysBuild = new javax.swing.JCheckBox(); + btnLearnMore = new javax.swing.JButton(); org.openide.awt.Mnemonics.setLocalizedText(serverLabel, org.openide.util.NbBundle.getMessage(CustomizerRunWeb.class, "LBL_Server")); // NOI18N @@ -438,6 +481,14 @@ org.openide.awt.Mnemonics.setLocalizedText(jCBCopyStaticResources, org.openide.util.NbBundle.getMessage(CustomizerRunWeb.class, "CustomizerRunWeb.jCBCopyStaticResources.text")); // NOI18N jCBCopyStaticResources.setToolTipText(org.openide.util.NbBundle.getMessage(CustomizerRunWeb.class, "CustomizerRunWeb.jCBCopyStaticResources.toolTipText")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jCBAlwaysBuild, org.openide.util.NbBundle.getMessage(CustomizerRunWeb.class, "CustomizerRunWeb.jCBAlwaysBuild.text")); // NOI18N + jCBAlwaysBuild.setToolTipText(org.openide.util.NbBundle.getMessage(CustomizerRunWeb.class, "CustomizerRunWeb.jCBAlwaysBuild.toolTipText")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(btnLearnMore, org.openide.util.NbBundle.getMessage(CustomizerRunWeb.class, "CustomizerRunWeb.btnLearnMore.text")); // NOI18N + btnLearnMore.setBorderPainted(false); + btnLearnMore.setContentAreaFilled(false); + btnLearnMore.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -461,15 +512,20 @@ .addComponent(txtRelativeUrl, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jCBBrowser, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addGroup(layout.createSequentialGroup() + .addComponent(jCBDeployOnSave) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() .addGap(21, 21, 21) .addComponent(dosDescription, javax.swing.GroupLayout.DEFAULT_SIZE, 609, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() - .addComponent(jCBDeployOnSave) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(jCBshowBrowser, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jCBCopyStaticResources, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(21, 21, 21) + .addComponent(btnLearnMore, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jCBAlwaysBuild) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(jCBshowBrowser, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jCBCopyStaticResources, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addGap(0, 0, Short.MAX_VALUE)))) ); layout.setVerticalGroup( @@ -505,6 +561,10 @@ .addComponent(jCBDeployOnSave) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(dosDescription, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jCBAlwaysBuild) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(btnLearnMore, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); @@ -543,9 +603,11 @@ // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel browserLabel; + private javax.swing.JButton btnLearnMore; private javax.swing.JLabel contextPathLabel; private javax.swing.JTextField contextPathTField; private javax.swing.JLabel dosDescription; + private javax.swing.JCheckBox jCBAlwaysBuild; private javax.swing.JComboBox jCBBrowser; private javax.swing.JCheckBox jCBCopyStaticResources; private javax.swing.JCheckBox jCBDeployOnSave; diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanel.form b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanel.form --- a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanel.form +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanel.form @@ -35,7 +35,7 @@ - + diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanel.java b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanel.java --- a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanel.java +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanel.java @@ -92,7 +92,7 @@ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() - .addComponent(lblText, javax.swing.GroupLayout.DEFAULT_SIZE, 137, Short.MAX_VALUE) + .addComponent(lblText, javax.swing.GroupLayout.DEFAULT_SIZE, 270, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cbNextTime)) ); diff --git a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanelSupport.java b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanelSupport.java --- a/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanelSupport.java +++ b/maven.j2ee/src/org/netbeans/modules/maven/j2ee/ui/util/WarningPanelSupport.java @@ -51,7 +51,8 @@ */ public final class WarningPanelSupport { - private static final String JAVA_EE_VERSION_CHANGE = "showJavaEEVersionChangeWarning"; //NOI18N + private static final String JAVA_EE_VERSION_CHANGE = "showJavaEEVersionChangeWarning"; // NOI18N + private static final String AUTOMATIC_BUILD = "automaticBuildWarning"; // NOI18N private WarningPanelSupport() { } @@ -67,4 +68,12 @@ public static void dontShowJavaEEChangeWarning() { getPreferences().putBoolean(JAVA_EE_VERSION_CHANGE, false); } + + public static boolean isAutomaticBuildWarningActivated() { + return getPreferences().getBoolean(AUTOMATIC_BUILD, true); + } + + public static void dontShowAutomaticBuildWarning() { + getPreferences().putBoolean(AUTOMATIC_BUILD, false); + } } diff --git a/maven/manifest.mf b/maven/manifest.mf --- a/maven/manifest.mf +++ b/maven/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.modules.maven/2 -OpenIDE-Module-Specification-Version: 2.96 +OpenIDE-Module-Specification-Version: 2.97 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/maven/Bundle.properties OpenIDE-Module-Layer: org/netbeans/modules/maven/layer.xml AutoUpdate-Show-In-Client: false diff --git a/maven/nbproject/project.xml b/maven/nbproject/project.xml --- a/maven/nbproject/project.xml +++ b/maven/nbproject/project.xml @@ -478,14 +478,15 @@ org.javeleon.netbeans - org.nbheaven.sqe.core.maven org.nbheaven.sqe.core.maven3 + org.netbeans.modules.android.maven org.netbeans.modules.apisupport.installer.maven org.netbeans.modules.groovy.support org.netbeans.modules.hudson.maven org.netbeans.modules.jbi.fuji.support org.netbeans.modules.kenai.maven + org.netbeans.modules.ko4j.debugging org.netbeans.modules.maven.apisupport org.netbeans.modules.maven.checkstyle org.netbeans.modules.maven.coverage @@ -503,16 +504,11 @@ org.netbeans.modules.maven.repository org.netbeans.modules.maven.samples org.netbeans.modules.maven.spring + org.netbeans.modules.maven.util + org.netbeans.modules.scala.maven org.netbeans.modules.selenium.maven - org.netbeans.modules.ko4j.debugging org.netbeans.modules.testng.maven - - org.netbeans.modules.android.maven - - org.netbeans.modules.scala.maven - org.vaadin.netbeans.maven - org.netbeans.modules.maven.util org.netbeans.modules.maven.api org.netbeans.modules.maven.api.archetype org.netbeans.modules.maven.api.classpath @@ -529,6 +525,7 @@ org.netbeans.modules.maven.spi.cos org.netbeans.modules.maven.spi.customizer org.netbeans.modules.maven.spi.debug + org.netbeans.modules.maven.spi.execute org.netbeans.modules.maven.spi.grammar org.netbeans.modules.maven.spi.nodes org.netbeans.modules.maven.spi.queries diff --git a/maven/src/org/netbeans/modules/maven/api/execute/AlternativeExecutor.java b/maven/src/org/netbeans/modules/maven/api/execute/AlternativeExecutor.java new file mode 100644 --- /dev/null +++ b/maven/src/org/netbeans/modules/maven/api/execute/AlternativeExecutor.java @@ -0,0 +1,80 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, 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-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2013 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.maven.api.execute; + +import org.netbeans.modules.maven.spi.execute.AlternativeExecutorImplementation; + +/** + * API for alternative execution of Maven Run/Debug/Profile actions. + * + * @see AlternativeExecutorImplementation + * + * @author Martin Janicek + * @since 2.97 + */ +public final class AlternativeExecutor { + + private AlternativeExecutor() { + } + + /** + * Perform an alternative execution. + * + *

+ * Using the given {@link RunConfig}, finds {@link AlternativeExecutorImplementation} + * registered for the project and performs it's execute method. + * + * @param config configuration + * @param context execution context + * @return {@code true} if the execution was successful, {@code false} otherwise + */ + public static boolean execute(RunConfig config, ExecutionContext context) { + AlternativeExecutorImplementation alternativeExecutor = config.getProject().getLookup().lookup(AlternativeExecutorImplementation.class); + if (alternativeExecutor != null) { + if (alternativeExecutor.execute(config, context)) { + return false; + } + } + return true; + } +} diff --git a/maven/src/org/netbeans/modules/maven/cos/CosChecker.java b/maven/src/org/netbeans/modules/maven/cos/CosChecker.java --- a/maven/src/org/netbeans/modules/maven/cos/CosChecker.java +++ b/maven/src/org/netbeans/modules/maven/cos/CosChecker.java @@ -158,13 +158,23 @@ touchProject(openprj); } //new style Compile on Save - checkRunMainClass(config, con); + if (!checkRunMainClass(config, con)) { + return false; + } checkRunTest(config, con); } return true; } - private void checkRunMainClass(final RunConfig config, ExecutionContext con) { + /** + * Returns {@code false} if execution should skip standard build phases. + * + * @param config run configuration + * @param con execution context + * @return {@code false} if execution should skip standard build phases, + * {@code true} otherwise + */ + private boolean checkRunMainClass(final RunConfig config, ExecutionContext con) { final String actionName = config.getActionName(); //compile on save stuff if (RunUtils.isCompileOnSaveEnabled(config)) { @@ -179,13 +189,13 @@ //check the COS timestamp against critical files (pom.xml) // if changed, don't do COS. if (checkImportantFiles(stamp, config)) { - return; + return true; } //check the COS timestamp against resources etc. //if changed, perform part of the maven build. (or skip COS) for (CompileOnSaveSkipper skipper : Lookup.getDefault().lookupAll(CompileOnSaveSkipper.class)) { if (skipper.skip(config, false, stamp)) { - return; + return true; } } @@ -193,6 +203,14 @@ if ((javarunnerCheckprops != null && javarunnerCheckprops.containsKey(USE_OLD_COS_EXECUTION)) || config.getProperties().containsKey(USE_OLD_COS_EXECUTION)) { LOG.fine("use.old.cos.execution found, using JavaRunner to execute."); } else { + // #230565 + Object skipBuild = config.getInternalProperties().get("skip.build"); //NOI18N + if (skipBuild instanceof Boolean && (Boolean) skipBuild) { + if (!AlternativeExecutor.execute(config, con)) { + return false; + } + } + //now attempt to extract if (config instanceof BeanRunConfig) { BeanRunConfig brc = (BeanRunConfig) config; @@ -217,6 +235,7 @@ } } } + return true; } private void checkRunTest(final RunConfig config, ExecutionContext con) { diff --git a/maven/src/org/netbeans/modules/maven/spi/execute/AlternativeExecutorImplementation.java b/maven/src/org/netbeans/modules/maven/spi/execute/AlternativeExecutorImplementation.java new file mode 100644 --- /dev/null +++ b/maven/src/org/netbeans/modules/maven/spi/execute/AlternativeExecutorImplementation.java @@ -0,0 +1,87 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, 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-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2013 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.maven.spi.execute; + +import org.netbeans.modules.maven.api.execute.AlternativeExecutor; +import org.netbeans.modules.maven.api.execute.ExecutionContext; +import org.netbeans.modules.maven.api.execute.RunConfig; + +/** + * Alternative executor enables to rewrite default way how run/debug/profile actions + * are performed. + * + *

+ * This can be useful in cases when we don't need to execute standard run behavior. + * For example when re-running Maven Web application with enabled CoS/DoS, we don't + * want to rebuild whole project every-time and simply re-opening index.html is enough. + * + *

+ * If the project want to use {@link AlternativeExecutorImplementation} it should register + * it in it's project {@link Lookup}. + * + *

+ * This class should not be used directly. Use {@link AlternativeExecutor} API class instead. + * + *

+ * See issue 230565 for some details about why this was needed in the first place. + * + * @see AlternativeExecutor + * + * @author Martin Janicek + * @since 2.97 + */ +public interface AlternativeExecutorImplementation { + + /** + * Perform an alternative execution. + * + *

+ * SPI client should perform whatever he wants to do instead of the default execution behavior. + * + * @param config configuration + * @param executionContext execution context + * @return {@code true} if the execution was successful, {@code false} otherwise + */ + boolean execute(RunConfig config, ExecutionContext executionContext); + +}