diff --git a/ant.browsetask/antsrc/org/netbeans/modules/ant/browsetask/NbBrowse.java b/ant.browsetask/antsrc/org/netbeans/modules/ant/browsetask/NbBrowse.java --- a/ant.browsetask/antsrc/org/netbeans/modules/ant/browsetask/NbBrowse.java +++ b/ant.browsetask/antsrc/org/netbeans/modules/ant/browsetask/NbBrowse.java @@ -51,6 +51,11 @@ import org.apache.tools.ant.*; import org.openide.awt.HtmlBrowser; +import org.netbeans.modules.web.browser.api.BrowserSupport; +import org.netbeans.modules.web.clientproject.spi.URLDisplayerImplementation; +import org.netbeans.api.project.FileOwnerQuery; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; /** * Opens a web browser. @@ -68,6 +73,21 @@ file = f; } + private boolean advanced; + public void setAdvanced(boolean advanced) { + this.advanced = advanced; + } + + private File context; + public void setContext(File f) { + context = f; + } + + private String urlPath; + public void setUrlPath(String s) { + urlPath = s; + } + public void execute() throws BuildException { if (url != null ^ file == null) throw new BuildException("You must define the url or file attributes", getLocation()); if (url == null) { @@ -75,7 +95,35 @@ } log("Browsing: " + url); try { - HtmlBrowser.URLDisplayer.getDefault().showURL(new URL(url)); + URL u = new URL(url); + URL appRoot = null; + if (advanced) { + FileObject fo = FileUtil.toFileObject(context); + if (context == null) { + throw new BuildException("You must define the context attribute", getLocation()); + } + if (fo == null) { + throw new BuildException("The context file must exist", getLocation()); + } + if (urlPath != null && urlPath.length() > 0) { + if (!url.endsWith(urlPath)) { + throw new BuildException("The urlPath("+urlPath+") is not part of the url("+url+")", getLocation()); + } + appRoot = new URL(url.substring(0, url.length()-urlPath.length())); + } + org.netbeans.api.project.Project p = FileOwnerQuery.getOwner(fo); + if (p != null) { + URLDisplayerImplementation urlDisplayer = (URLDisplayerImplementation) + p.getLookup().lookup(URLDisplayerImplementation.class); + if (urlDisplayer != null) { + urlDisplayer.showURL(appRoot != null ? appRoot : u, u, fo); + return; + } + } + HtmlBrowser.URLDisplayer.getDefault().showURL(u); + } else { + HtmlBrowser.URLDisplayer.getDefault().showURL(u); + } } catch (MalformedURLException e) { throw new BuildException(e, getLocation()); } diff --git a/ant.browsetask/nbproject/project.properties b/ant.browsetask/nbproject/project.properties --- a/ant.browsetask/nbproject/project.properties +++ b/ant.browsetask/nbproject/project.properties @@ -45,4 +45,8 @@ antsrc.cp=\ ${ant.core.lib}:\ ${openide.filesystems.dir}/core/org-openide-filesystems.jar:\ - ${openide.awt.dir}/modules/org-openide-awt.jar + ${openide.awt.dir}/modules/org-openide-awt.jar:\ + ${openide.util.lookup.dir}/lib/org-openide-util-lookup.jar:\ + ${projectapi.dir}/modules/org-netbeans-modules-projectapi.jar:\ + ${web.clientproject.api.dir}/modules/org-netbeans-modules-web-clientproject-api.jar:\ + ${web.browser.api.dir}/modules/org-netbeans-modules-web-browser-api.jar diff --git a/ant.browsetask/nbproject/project.xml b/ant.browsetask/nbproject/project.xml --- a/ant.browsetask/nbproject/project.xml +++ b/ant.browsetask/nbproject/project.xml @@ -58,6 +58,23 @@ + org.netbeans.modules.projectapi + + + + 1 + 1.50 + + + + org.netbeans.modules.web.browser.api + + + + 1.4 + + + org.openide.awt @@ -69,6 +86,22 @@ + + org.openide.util.lookup + + + + 8.19 + + + + org.netbeans.modules.web.clientproject.api + + + + 1.13 + + diff --git a/j2eeserver/src/org/netbeans/modules/j2ee/deployment/config/ConfigSupportImpl.java b/j2eeserver/src/org/netbeans/modules/j2ee/deployment/config/ConfigSupportImpl.java --- a/j2eeserver/src/org/netbeans/modules/j2ee/deployment/config/ConfigSupportImpl.java +++ b/j2eeserver/src/org/netbeans/modules/j2ee/deployment/config/ConfigSupportImpl.java @@ -1009,22 +1009,4 @@ return allRelativePaths; } - // XXX commented out - there does not seem to be any client for 7.3 - // once this is going to be used move to J2eeModuleProvider - /** - * The listener interface to listen for deploy on save operations. - * - * @since 1.91 - */ - public static interface DeployOnSaveListener { - - /** - * Invoked when a deploy on save operation has been successfully - * performed by the infrastructure. - * - * @param artifacts artifacts affected by the deploy - */ - public void deployed(Iterable artifacts); - - } } diff --git a/j2eeserver/src/org/netbeans/modules/j2ee/deployment/devmodules/spi/J2eeModuleProvider.java b/j2eeserver/src/org/netbeans/modules/j2ee/deployment/devmodules/spi/J2eeModuleProvider.java --- a/j2eeserver/src/org/netbeans/modules/j2ee/deployment/devmodules/spi/J2eeModuleProvider.java +++ b/j2eeserver/src/org/netbeans/modules/j2ee/deployment/devmodules/spi/J2eeModuleProvider.java @@ -533,8 +533,7 @@ * @param listener listener to add * @since 1.91 */ - // XXX commented out - there does not seem to be any client for 7.3 - //public void addDeployOnSaveListener( DeployOnSaveListener listener ); + public void addDeployOnSaveListener( DeployOnSaveListener listener ); /** * Removes the listener listening for deploy on save. @@ -543,8 +542,7 @@ * @see #addDeployOnSaveListener(org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider.DeployOnSaveListener) * @since 1.91 */ - // XXX commented out - there does not seem to be any client for 7.3 - //public void removeDeployOnSaveListener( DeployOnSaveListener listener ); + public void removeDeployOnSaveListener( DeployOnSaveListener listener ); /** * Retrieves message destinations stored in the module. @@ -723,6 +721,25 @@ */ public void bindEjbReferenceForEjb(String ejbName, String ejbType, String referenceName, String jndiName) throws ConfigurationException; + + /** + * The listener interface to listen for deploy on save operations. + * + * @since 1.91 + */ + public static interface DeployOnSaveListener { + + /** + * Invoked when a deploy on save operation has been successfully + * performed by the infrastructure. + * + * @param artifacts artifacts affected by the deploy + */ + public void deployed(Iterable artifacts); + + } + + } /** diff --git a/web.browser.api/nbproject/project.xml b/web.browser.api/nbproject/project.xml --- a/web.browser.api/nbproject/project.xml +++ b/web.browser.api/nbproject/project.xml @@ -124,6 +124,7 @@ org.netbeans.core.browser.webview + org.netbeans.modules.ant.browsetask org.netbeans.modules.cordova org.netbeans.modules.extbrowser org.netbeans.modules.html diff --git a/web.clientproject.api/nbproject/project.xml b/web.clientproject.api/nbproject/project.xml --- a/web.clientproject.api/nbproject/project.xml +++ b/web.clientproject.api/nbproject/project.xml @@ -118,6 +118,7 @@ + org.netbeans.modules.ant.browsetask org.netbeans.modules.cordova org.netbeans.modules.cordova.platforms org.netbeans.modules.cordova.platforms.android @@ -130,6 +131,7 @@ org.netbeans.modules.web.inspect org.netbeans.modules.web.javascript.debugger org.netbeans.modules.web.livehtml + org.netbeans.modules.web.project org.netbeans.modules.web.clientproject.api org.netbeans.modules.web.clientproject.api.network org.netbeans.modules.web.clientproject.spi diff --git a/web.clientproject.api/src/org/netbeans/modules/web/clientproject/spi/URLDisplayerImplementation.java b/web.clientproject.api/src/org/netbeans/modules/web/clientproject/spi/URLDisplayerImplementation.java new file mode 100644 --- /dev/null +++ b/web.clientproject.api/src/org/netbeans/modules/web/clientproject/spi/URLDisplayerImplementation.java @@ -0,0 +1,61 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.web.clientproject.spi; + +import java.net.URL; +import org.openide.filesystems.FileObject; + +/** + * Contract allowing different project types to implement opening of project files + * in a browser. At the moment used only by Java Web project type. + */ +public interface URLDisplayerImplementation { + + /** + * + * @param applicationRootURL root of application to which urlToOpenInBrowser belongs + * @param urlToOpenInBrowser URL of a file to open in browser + * @param context either file corresponding to urlToOpenInBrowser or project's folder + */ + void showURL(URL applicationRootURL, URL urlToOpenInBrowser, FileObject context); + +} diff --git a/web.project/nbproject/project.xml b/web.project/nbproject/project.xml --- a/web.project/nbproject/project.xml +++ b/web.project/nbproject/project.xml @@ -336,6 +336,14 @@ + org.netbeans.modules.web.browser.api + + + + 1.4 + + + org.netbeans.modules.web.common @@ -514,6 +522,14 @@ 6.2 + + org.netbeans.modules.web.clientproject.api + + + + 1.13 + + diff --git a/web.project/src/org/netbeans/modules/web/project/WebActionProvider.java b/web.project/src/org/netbeans/modules/web/project/WebActionProvider.java --- a/web.project/src/org/netbeans/modules/web/project/WebActionProvider.java +++ b/web.project/src/org/netbeans/modules/web/project/WebActionProvider.java @@ -303,6 +303,17 @@ @Override public String[] getTargetNames(String command, Lookup context, Properties p, boolean doJavaChecks) throws IllegalArgumentException { + + if (WebProject.isEaselEnable()) { + p.setProperty("browser.advanced", "true"); + FileObject fo = context.lookup(FileObject.class); + if (fo == null) { + fo = getProject().getProjectDirectory(); + } + String ctx = FileUtil.toFile(fo).getAbsolutePath(); + p.setProperty("browser.context", ctx); + } + if (command.equals(COMMAND_RUN_SINGLE) ||command.equals(COMMAND_RUN) || command.equals(WebProjectConstants.COMMAND_REDEPLOY) ||command.equals(COMMAND_DEBUG) || command.equals(COMMAND_DEBUG_SINGLE) || command.equals(JavaProjectConstants.COMMAND_DEBUG_FIX) || diff --git a/web.project/src/org/netbeans/modules/web/project/WebProject.java b/web.project/src/org/netbeans/modules/web/project/WebProject.java --- a/web.project/src/org/netbeans/modules/web/project/WebProject.java +++ b/web.project/src/org/netbeans/modules/web/project/WebProject.java @@ -49,6 +49,8 @@ import java.io.*; import java.lang.ref.Reference; import java.lang.ref.WeakReference; +import java.net.MalformedURLException; +import java.net.URL; import java.util.*; import java.util.ArrayList; import java.util.concurrent.CopyOnWriteArrayList; @@ -149,12 +151,18 @@ import org.netbeans.modules.j2ee.deployment.devmodules.api.InstanceRemovedException; import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eeModule.Type; import org.netbeans.modules.j2ee.deployment.devmodules.spi.ArtifactListener; +import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider.ConfigSupport.DeployOnSaveListener; import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider.DeployOnSaveSupport; import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel; import org.netbeans.modules.j2ee.spi.ejbjar.EjbJarFactory; import org.netbeans.modules.j2ee.spi.ejbjar.support.EjbJarSupport; import org.netbeans.modules.java.api.common.project.ProjectProperties; import org.netbeans.modules.web.api.webmodule.WebProjectConstants; +import org.netbeans.modules.web.browser.api.BrowserSupport; +import org.netbeans.modules.web.browser.spi.PageInspectorCustomizer; +import org.netbeans.modules.web.clientproject.spi.URLDisplayerImplementation; +import org.netbeans.modules.web.common.api.WebUtils; +import org.netbeans.modules.web.common.spi.ServerURLMappingImplementation; import org.netbeans.modules.web.project.api.WebProjectUtilities; import org.netbeans.modules.web.project.classpath.ClassPathSupportCallbackImpl; import org.netbeans.modules.web.project.classpath.DelagatingProjectClassPathModifierImpl; @@ -177,7 +185,6 @@ import org.netbeans.spi.project.support.ant.PropertyUtils; import org.netbeans.spi.queries.FileEncodingQueryImplementation; import org.openide.filesystems.FileLock; -import org.openide.filesystems.FileSystem; import org.openide.filesystems.FileSystem.AtomicAction; import org.openide.loaders.DataObject; import org.openide.util.Exceptions; @@ -600,7 +607,8 @@ ExtraSourceJavadocSupport.createExtraJavadocQueryImplementation(this, helper, eval), LookupMergerSupport.createJFBLookupMerger(), QuerySupport.createBinaryForSourceQueryImplementation(sourceRoots, testRoots, helper, eval), - new ProjectWebRootProviderImpl() + new ProjectWebRootProviderImpl(), + new ClientSideDevelopmentSupport(), }); Lookup ee6 = Lookups.fixed(new Object[]{ @@ -1506,7 +1514,7 @@ * Class should not request project lock from FS listener methods * (deadlock prone). */ - private class CopyOnSaveSupport extends FileChangeAdapter implements PropertyChangeListener { + private class CopyOnSaveSupport extends FileChangeAdapter implements PropertyChangeListener, DeployOnSaveListener { private FileObject docBase = null; @@ -1556,36 +1564,33 @@ resources = getWebModule().getResourceDirectory(); buildWeb = evaluator().getProperty(WebProjectProperties.BUILD_WEB_DIR); - FileSystem docBaseFileSystem = null; if (docBase != null) { - docBaseFileSystem = docBase.getFileSystem(); - docBaseFileSystem.addFileChangeListener(this); + docBase.addRecursiveListener(this); } - if (webInf != null) { - if (!webInf.getFileSystem().equals(docBaseFileSystem)) { - webInf.getFileSystem().addFileChangeListener(this); - } + if (webInf != null && !FileUtil.isParentOf(docBase, webInf)) { + webInf.addRecursiveListener(this); } if (resources != null) { FileUtil.addFileChangeListener(this, resources); } + // Add deployed resources notification listener + if (isEaselEnable()) { + webModule.getConfigSupport().addDeployOnSaveListener(this); + } + LOGGER.log(Level.FINE, "Web directory is {0}", docBaseValue); LOGGER.log(Level.FINE, "WEB-INF directory is {0}", webInfValue); } public void cleanup() throws FileStateInvalidException { - FileSystem docBaseFileSystem = null; if (docBase != null) { - docBaseFileSystem = docBase.getFileSystem(); - docBaseFileSystem.removeFileChangeListener(this); + docBase.removeRecursiveListener(this); } - if (webInf != null) { - if (!webInf.getFileSystem().equals(docBaseFileSystem)) { - webInf.getFileSystem().removeFileChangeListener(this); - } + if (webInf != null && !FileUtil.isParentOf(docBase, webInf)) { + webInf.removeRecursiveListener(this); } if (resources != null) { FileUtil.removeFileChangeListener(this, resources); @@ -1593,6 +1598,10 @@ } WebProject.this.evaluator().removePropertyChangeListener(this); + + if (isEaselEnable()) { + webModule.getConfigSupport().removeDeployOnSaveListener(this); + } } public void propertyChange(PropertyChangeEvent evt) { @@ -1902,6 +1911,54 @@ assert current != null : "webBuildBase: " + webBuildBase + ", path: " + path + ", isFolder: " + isFolder; return current; } + + public void deployed(Iterable artifacts) { + for (Artifact artifact : artifacts) { + FileObject fileObject = getReloadFileObject(artifact); + if (fileObject != null) { + reload(fileObject); + } + } + } + + private void reload(FileObject fo) { + URL u = getBrowserSupport().getBrowserURL(fo, true); + if (u != null) { + assert getBrowserSupport().canReload(u) : u; + getBrowserSupport().reload(u); + } + } + + private FileObject getReloadFileObject(Artifact artifact) { + File file = artifact.getFile(); + FileObject fileObject = FileUtil.toFileObject(FileUtil.normalizeFile(file)); + if (fileObject == null) { + return null; + } + return getWebDocFileObject(fileObject); + } + + private FileObject getWebDocFileObject(FileObject artifact) { + FileObject webBuildBase = buildWeb == null ? null : helper.resolveFileObject(buildWeb); + if (docBase != null && webBuildBase != null) { + if (!FileUtil.isParentOf(webBuildBase, artifact)) { + return null; + } else { + String path = FileUtil.getRelativePath(webBuildBase, artifact); + return docBase.getFileObject(path); + } + } else { + return null; + } + } + } + + private BrowserSupport getBrowserSupport() { + return BrowserSupport.getDefault(); + } + + public static boolean isEaselEnable() { + return Boolean.getBoolean("easel.everywhere"); } private class ArtifactCopySupport extends ArtifactCopyOnSaveSupport { @@ -2290,4 +2347,79 @@ } + private class ClientSideDevelopmentSupport implements ServerURLMappingImplementation, + URLDisplayerImplementation, PageInspectorCustomizer { + + private String projectRootURL = null; + private FileObject webDocumentRoot; + private boolean initialized = false; + + public ClientSideDevelopmentSupport() { + } + + @Override + public void showURL(URL applicationRootURL, URL urlToOpenInBrowser, FileObject context) { + projectRootURL = WebUtils.urlToString(applicationRootURL); + if (projectRootURL != null && !projectRootURL.endsWith("/")) { + projectRootURL += "/"; + } + getBrowserSupport().load(urlToOpenInBrowser, context); + } + + @Override + public URL toServer(int projectContext, FileObject projectFile) { + init(); + if (projectRootURL == null || webDocumentRoot == null) { + return null; + } + String relPath = FileUtil.getRelativePath(webDocumentRoot, projectFile); + try { + return new URL(projectRootURL + relPath); + } catch (MalformedURLException ex) { + Exceptions.printStackTrace(ex); + return null; + } + } + + @Override + public FileObject fromServer(int projectContext, URL serverURL) { + init(); + if (projectRootURL == null || webDocumentRoot == null) { + return null; + } + String u = WebUtils.urlToString(serverURL); + if (u.startsWith(projectRootURL)) { + return webDocumentRoot.getFileObject(u.substring(projectRootURL.length())); + } + return null; + } + + private FileObject getWebRoot() { + WebModule webModule = WebModule.getWebModule(getProjectDirectory()); + return webModule != null ? webModule.getDocumentBase() : null; + } + + private void init() { + if (initialized) { + return; + } + webDocumentRoot = getWebRoot(); + initialized = true; + } + + @Override + public boolean isHighlightSelectionEnabled() { + return true; + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener l) { + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener l) { + } + + } + } diff --git a/web.project/src/org/netbeans/modules/web/project/resources/build-impl.xsl b/web.project/src/org/netbeans/modules/web/project/resources/build-impl.xsl --- a/web.project/src/org/netbeans/modules/web/project/resources/build-impl.xsl +++ b/web.project/src/org/netbeans/modules/web/project/resources/build-impl.xsl @@ -2139,7 +2139,8 @@ - + +