diff --git a/features/com.gwtplugins.eclipse.suite.v3.feature/feature.xml b/features/com.gwtplugins.eclipse.suite.v3.feature/feature.xml index 0539aac9..a7ed3125 100644 --- a/features/com.gwtplugins.eclipse.suite.v3.feature/feature.xml +++ b/features/com.gwtplugins.eclipse.suite.v3.feature/feature.xml @@ -177,4 +177,11 @@ version="4.2.0.qualifier" unpack="false"/> + + diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/META-INF/MANIFEST.MF b/plugins/com.gwtplugins.eclipse.jettylauncher/META-INF/MANIFEST.MF new file mode 100644 index 00000000..e20b9f9c --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/META-INF/MANIFEST.MF @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Jettylauncher +Bundle-SymbolicName: com.gwtplugins.eclipse.jettylauncher +Bundle-Version: 4.2.0.qualifier +Automatic-Module-Name: org.gwtproject.jettylauncher +Bundle-RequiredExecutionEnvironment: JavaSE-17 diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/build.properties b/plugins/com.gwtplugins.eclipse.jettylauncher/build.properties new file mode 100644 index 00000000..8947bc7a --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/build.properties @@ -0,0 +1,4 @@ +source.. = src/java/ +output.. = target/classes +bin.includes = META-INF/,\ + . diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/pom.xml b/plugins/com.gwtplugins.eclipse.jettylauncher/pom.xml new file mode 100644 index 00000000..4e8e4805 --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/pom.xml @@ -0,0 +1,134 @@ + + 4.0.0 + + + com.gwtplugins.eclipse + trunk + 4.2.0-SNAPSHOT + ../../ + + + com.gwtplugins.eclipse.jettylauncher + 4.2.0-SNAPSHOT + eclipse-plugin + + + UTF-8 + 11 + true + + + + + org.eclipse.jetty + jetty-server + 12.0.31 + provided + + + org.eclipse.jetty.ee10 + jetty-ee10-servlet + 12.0.31 + provided + + + org.eclipse.jetty.ee10 + jetty-ee10-webapp + 12.0.31 + provided + + + org.eclipse.jetty.ee8 + jetty-ee8-servlet + 12.0.31 + provided + + + org.eclipse.jetty.ee8 + jetty-ee8-webapp + 12.0.31 + provided + + + org.gwtproject + gwt-dev + 2.12.2 + provided + + + + + + + + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + default-testCompile + none + + + + + org.eclipse.tycho + tycho-compiler-plugin + ${tycho.version} + + + + org.eclipse.jetty + jetty-server + 12.0.36 + + + org.eclipse.jetty.ee8 + jetty-ee8-servlet + 12.0.36 + + + org.eclipse.jetty.ee8 + jetty-ee8-webapp + 12.0.36 + + + org.eclipse.jetty.ee10 + jetty-ee10-servlet + 12.0.36 + + + org.eclipse.jetty.ee10 + jetty-ee10-webapp + 12.0.36 + + + org.gwtproject + gwt-dev + 2.12.2 + + + xml-apis + xml-apis + + + xerces + xercesImpl + + + + + true + true + + + + + + + \ No newline at end of file diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/AbstractJetty12Launcher.java b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/AbstractJetty12Launcher.java new file mode 100644 index 00000000..90b6355e --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/AbstractJetty12Launcher.java @@ -0,0 +1,45 @@ +package com.gwtplugins.jettylauncher; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.BindException; + +import com.google.gwt.core.ext.ServletContainer; +import com.google.gwt.core.ext.ServletContainerLauncher; +import com.google.gwt.core.ext.TreeLogger; + +/** + * Base class for the Jetty12Launchers. + */ +public abstract class AbstractJetty12Launcher extends ServletContainerLauncher { + + @Override + public ServletContainer start(TreeLogger logger, int port, File appRootDir) throws BindException, Exception { + // A custom Classloader to separate the classes of the webapp and app server from the rest of the system. + Jetty12ClassLoader cl = new Jetty12ClassLoader(getJEEVersion()); + Thread.currentThread().setContextClassLoader(cl); + //Load and run the Bootstrap in the context of the custom ClassLoader. + Class bsClass = cl.loadClass(getBootstrapClassname()); + Class[] types = new Class[2]; + types[0] = int.class; + types[1] = File.class; + Method method = bsClass.getDeclaredMethod("start", types); + Object[] params = new Object[2]; + params[0] = port; + params[1] = appRootDir; + ServletContainer cont = (ServletContainer) method.invoke(null, params); + return cont; + } + + /** + * The jee Version to load. If jee10 ist activated, the jee8 libraries will not be loaded. + * @return + */ + protected abstract JEEVersion getJEEVersion(); + + /** + * The name of the class that is used to separate the classloader from other eclipse classes. + * @return + */ + abstract protected String getBootstrapClassname(); +} diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/AbstractJetty12ServletContainer.java b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/AbstractJetty12ServletContainer.java new file mode 100644 index 00000000..d0b4e6ae --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/AbstractJetty12ServletContainer.java @@ -0,0 +1,96 @@ +package com.gwtplugins.jettylauncher; + +import java.io.File; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.InetAccessHandler; +import org.eclipse.jetty.util.thread.QueuedThreadPool; + +import com.google.gwt.core.ext.ServletContainer; +import com.google.gwt.core.ext.UnableToCompleteException; + +public abstract class AbstractJetty12ServletContainer extends ServletContainer { + + protected int port; + protected File appRootDir; + + public AbstractJetty12ServletContainer(int port, File appRootDir) + { + super(); + this.port = port; + this.appRootDir = appRootDir; + try + { + startServer(port); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * Create a Thread Pool for the Jetty Server + * @return + */ + protected QueuedThreadPool createThreadPool() + { + // Eigenen ThreadPool um Anzahl der Threads kontrollieren zu können + QueuedThreadPool pool = new QueuedThreadPool(50, 20) + { + @Override + public Thread newThread(Runnable runnable) { + // Threads markieren + Thread t = super.newThread(runnable); + t.setName("Jetty - " + t.getName()); + return t; + } + }; + return pool; + } + + /** + * Starts the Jetty Server on the given Port. + * @param port + * @throws Exception + */ + public void startServer(int port) throws Exception + { + QueuedThreadPool pool = createThreadPool(); + Server server = new Server(pool); + ServerConnector connector = new ServerConnector(server); + connector.setPort(port); + connector.setIdleTimeout(30000); + server.addConnector(connector); + InetAccessHandler ihandler = new InetAccessHandler(); + + Handler.Sequence shandler = createHandler(); + + ihandler.setHandler(shandler); + server.setHandler(ihandler); + server.start(); + } + + /** + * Create a WebAppContext + * @return + */ + abstract protected Handler.Sequence createHandler(); + + @Override + public int getPort() + { + return port; + } + + @Override + public void refresh() throws UnableToCompleteException + { + } + + @Override + public void stop() throws UnableToCompleteException + { + } +} \ No newline at end of file diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/JEEVersion.java b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/JEEVersion.java new file mode 100644 index 00000000..29f7e7df --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/JEEVersion.java @@ -0,0 +1,10 @@ +package com.gwtplugins.jettylauncher; + +/** + * JEE Versions. JEE8 for javax.servlet and JEE10 for jakarta.servlet + */ +public enum JEEVersion +{ + JEE8 + , JEE10 +} \ No newline at end of file diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/Jetty12ClassLoader.java b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/Jetty12ClassLoader.java new file mode 100644 index 00000000..67557dae --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/Jetty12ClassLoader.java @@ -0,0 +1,176 @@ +package com.gwtplugins.jettylauncher; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +/** + * A classloader to load the classes of the Jetty App Server, that are needed to start GWT + */ +public class Jetty12ClassLoader extends URLClassLoader +{ + private ClassLoader parentInt; + + public Jetty12ClassLoader(JEEVersion jeeversion) throws IOException + { + super(new URL[0], null); + URL[] urls = getJettyURLs(jeeversion); + for(URL url : urls) + { + addURL(url); + } + this.parentInt = Thread.currentThread().getContextClassLoader(); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException + { + Class clazz = findLoadedClass(name); + //load these classes by this classloader. + if(clazz == null && + (name.startsWith("com.gwtplugins.jettylauncher") + ) + ) + { + String resName = name.replace('.', '/').concat(".class"); + URL res = parentInt.getResource(resName); + try + { + InputStream in = res.openStream(); + byte[] def = readAll(in); + clazz = defineClass(name, def, 0, def.length); + } + catch (IOException e) + { + throw new ClassNotFoundException("Unable to load class", e); + } + } + if(clazz == null) + { + //load classes of this URLClassLoader or System classes + try + { + clazz = super.loadClass(name); + } + catch(ClassNotFoundException ex) + {} + } + if(clazz == null) + { + if(name.startsWith("com.google.gwt") + || name.startsWith("java.")) + { + //Load classes from parent classloader, that are not in this URLClassloader + return parentInt.loadClass(name); + } + } + if(clazz == null) + { + throw new ClassNotFoundException(name); + } + return clazz; + } + + @Override + public Enumeration getResources(String name) throws IOException + { + return super.getResources(name); + } + + public byte[] readAll(InputStream in) throws IOException + { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + byte[] buffer = new byte[65536]; + int count = in.read(buffer); + while (count != -1) + { + if (count > 0) + { + bout.write(buffer, 0, count); + } + count = in.read(buffer); + } + bout.close(); + return bout.toByteArray(); + } + + + private URL[] getJettyURLs(JEEVersion jeeVersion) throws IOException + { + File jettyHome; + String jhome = System.getProperty("JETTY_HOME"); + if(jhome == null) + { + jhome = System.getenv("JETTY_HOME"); + } + if(jhome == null) + { + throw new IOException("JETTY_HOME not set"); + } + else + { + jettyHome = new File(jhome); + if(jettyHome.exists() == false) + { + throw new IOException("JETTY_HOME not set"); + } + } + List urls = new ArrayList<>(); + File libs = new File(jettyHome, "lib"); + addJarsFrom(urls, libs, jeeVersion); + libs = new File(jettyHome, "lib/logging"); + addJarsFrom(urls, libs); + if(JEEVersion.JEE10.equals(jeeVersion)) + { + libs = new File(jettyHome, "lib/ee10-annotations"); + addJarsFrom(urls, libs); + libs = new File(jettyHome, "lib/ee10-apache-jsp"); + addJarsFrom(urls, libs); + libs = new File(jettyHome, "lib/ee10-jaspi"); + addJarsFrom(urls, libs); + } + else if(JEEVersion.JEE8.equals(jeeVersion)) + { + libs = new File(jettyHome, "lib/ee8-annotations"); + addJarsFrom(urls, libs); + libs = new File(jettyHome, "lib/ee8-apache-jsp"); + addJarsFrom(urls, libs); + } + return urls.toArray(new URL[urls.size()]); + } + + private void addJarsFrom(List urls, File dir) throws IOException + { + addJarsFrom(urls, dir, null); + } + + private void addJarsFrom(List urls, File dir, JEEVersion jeeVersion) throws IOException + { + File[] files = dir.listFiles(); + for(File f : files) + { + if(f.isFile() && f.getName().endsWith(".jar")) + { + if(JEEVersion.JEE8.equals(jeeVersion) + && f.getName().startsWith("jetty-ee10")) + { + continue; + } + else if(JEEVersion.JEE10.equals(jeeVersion) + && f.getName().startsWith("jetty-ee8")) + { + continue; + } + URL url = f.toURI().toURL(); + urls.add(url); + System.out.println("Added jar to classpath: " + f); + } + } + } +} diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee10/Bootstrap.java b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee10/Bootstrap.java new file mode 100644 index 00000000..8cbeff0a --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee10/Bootstrap.java @@ -0,0 +1,17 @@ +package com.gwtplugins.jettylauncher.jee10; + +import java.io.File; + +import com.google.gwt.core.ext.ServletContainer; + +/** + * Bootstrap Class is loaded by Reflection by the Jetty12ClassLoader to separate the ClassLoader of the WebApp + * from anything else on the classpath. + */ +public class Bootstrap +{ + public static ServletContainer start(int port, File appRootDir) + { + return new Jetty12ServletContainer(port, appRootDir); + } +} diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee10/Jetty12Launcher.java b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee10/Jetty12Launcher.java new file mode 100644 index 00000000..1ee7b9d8 --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee10/Jetty12Launcher.java @@ -0,0 +1,28 @@ +package com.gwtplugins.jettylauncher.jee10; + +import com.gwtplugins.jettylauncher.AbstractJetty12Launcher; +import com.gwtplugins.jettylauncher.JEEVersion; + +/** + * Launches the Jetty 12 referenced by JETTY_HOME Environment with JEE10 (jakarta.servlet) API. + *
+ * The full startup follows this order: + *
    + *
  • Create a Jetty12ClassLoader (which initializes its classpath with the libs found in JETTY_HOME. + *
  • Use the classloader to load the Bootstrap Class + *
  • invoke the start method of Bootstrap by reflection + *
  • The start method will then create the Jetty12ServletContainer which is returned by this method. + */ +public class Jetty12Launcher extends AbstractJetty12Launcher +{ + + @Override + protected String getBootstrapClassname() { + return "com.gwtplugins.jettylauncher.jee10.Bootstrap"; + } + + @Override + protected JEEVersion getJEEVersion() { + return JEEVersion.JEE10; + } +} \ No newline at end of file diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee10/Jetty12ServletContainer.java b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee10/Jetty12ServletContainer.java new file mode 100644 index 00000000..4e4fb1cb --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee10/Jetty12ServletContainer.java @@ -0,0 +1,34 @@ +package com.gwtplugins.jettylauncher.jee10; + +import java.io.File; + +import org.eclipse.jetty.ee10.servlet.DefaultServlet; +import org.eclipse.jetty.ee10.servlet.ServletHolder; +import org.eclipse.jetty.ee10.webapp.WebAppContext; +import org.eclipse.jetty.server.Handler; +import com.gwtplugins.jettylauncher.AbstractJetty12ServletContainer; + +class Jetty12ServletContainer extends AbstractJetty12ServletContainer +{ + Jetty12ServletContainer(int port, File appRootDir) + { + super(port, appRootDir); + } + + @Override + protected Handler.Sequence createHandler() + { + WebAppContext webAppHandler = new WebAppContext(appRootDir.getAbsolutePath().replace('\\', '/'), "/"); +// webAppHandler.setDefaultsDescriptor(JavaxWebAppStarter.class.getResource("/webxml/webdefault-ee10.xml").toString()); + + // DefaultServlet hinzufügen um Cache für statische Dateien zu kontrollieren + DefaultServlet defaultServlet = new DefaultServlet(); + ServletHolder holder = new ServletHolder(defaultServlet); + holder.setInitParameter("useFileMappedBuffer", "false"); + holder.setInitParameter("cacheControl", "max-age=600, public"); // 10 Minuten Cachen + webAppHandler.addServlet(holder, "/"); + Handler.Sequence shandler = new Handler.Sequence(); + shandler.addHandler(webAppHandler); + return shandler; + } +} \ No newline at end of file diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee8/Bootstrap.java b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee8/Bootstrap.java new file mode 100644 index 00000000..d1a402df --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee8/Bootstrap.java @@ -0,0 +1,17 @@ +package com.gwtplugins.jettylauncher.jee8; + +import java.io.File; + +import com.google.gwt.core.ext.ServletContainer; + +/** + * Bootstrap Class is loaded by Reflection by the Jetty12ClassLoader to separate the ClassLoader of the WebApp + * from anything else on the classpath. + */ +public class Bootstrap +{ + public static ServletContainer start(int port, File appRootDir) + { + return new Jetty12ServletContainer(port, appRootDir); + } +} diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee8/Jetty12Launcher.java b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee8/Jetty12Launcher.java new file mode 100644 index 00000000..34f38ba9 --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee8/Jetty12Launcher.java @@ -0,0 +1,28 @@ +package com.gwtplugins.jettylauncher.jee8; + +import com.gwtplugins.jettylauncher.AbstractJetty12Launcher; +import com.gwtplugins.jettylauncher.JEEVersion; + +/** + * Launches the Jetty 12 referenced by JETTY_HOME Environment with JEE8 (javax.servlet) API. + *
    + * The full startup follows this order: + *
      + *
    • Create a Jetty12ClassLoader (which initializes its classpath with the libs found in JETTY_HOME. + *
    • Use the classloader to load the Bootstrap Class + *
    • invoke the start method of Bootstrap by reflection + *
    • The start method will then create the Jetty12ServletContainer which is returned by this method. + */ +public class Jetty12Launcher extends AbstractJetty12Launcher +{ + + @Override + protected String getBootstrapClassname() { + return "com.gwtplugins.jettylauncher.jee8.Bootstrap"; + } + + @Override + protected JEEVersion getJEEVersion() { + return JEEVersion.JEE8; + } +} \ No newline at end of file diff --git a/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee8/Jetty12ServletContainer.java b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee8/Jetty12ServletContainer.java new file mode 100644 index 00000000..8a894db7 --- /dev/null +++ b/plugins/com.gwtplugins.eclipse.jettylauncher/src/java/com/gwtplugins/jettylauncher/jee8/Jetty12ServletContainer.java @@ -0,0 +1,49 @@ +package com.gwtplugins.jettylauncher.jee8; + +import java.io.File; + +import org.eclipse.jetty.ee8.servlet.DefaultServlet; +import org.eclipse.jetty.ee8.servlet.ServletHolder; +import org.eclipse.jetty.ee8.webapp.WebAppContext; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.Handler.Sequence; +import org.eclipse.jetty.server.handler.InetAccessHandler; +import org.eclipse.jetty.util.thread.QueuedThreadPool; + +import com.gwtplugins.jettylauncher.AbstractJetty12ServletContainer; + +/** + * Implementation of GWTs ServletContainer class, that starts a Jetty 12 from + * JETTY_HOME + */ +class Jetty12ServletContainer extends AbstractJetty12ServletContainer +{ + Jetty12ServletContainer(int port, File appRootDir) + { + super(port, appRootDir); + } + + @Override + protected Handler.Sequence createHandler() + { + WebAppContext webAppHandler = new WebAppContext(appRootDir.getAbsolutePath().replace('\\', '/'), "/") { + @Override + public boolean isServerClass(Class clazz) { + return false; + } + }; + // DefaultServlet to control Cache + DefaultServlet defaultServlet = new DefaultServlet(); + ServletHolder holder = new ServletHolder(defaultServlet); + holder.setInitParameter("useFileMappedBuffer", "false"); + holder.setInitParameter("cacheControl", "max-age=600, public"); // 10 Minutes Cache + webAppHandler.addServlet(holder, "/"); + + Handler.Sequence shandler = new Handler.Sequence(); + shandler.addHandler(webAppHandler); + return shandler; + } + +} \ No newline at end of file diff --git a/plugins/com.gwtplugins.gdt.eclipse.core/META-INF/MANIFEST.MF b/plugins/com.gwtplugins.gdt.eclipse.core/META-INF/MANIFEST.MF index 206cddc3..3e2a456e 100644 --- a/plugins/com.gwtplugins.gdt.eclipse.core/META-INF/MANIFEST.MF +++ b/plugins/com.gwtplugins.gdt.eclipse.core/META-INF/MANIFEST.MF @@ -84,7 +84,8 @@ Require-Bundle: com.gwtplugins.gdt.eclipse.platform, org.eclipse.wst.sse.ui, org.eclipse.wst.xml.core, org.eclipse.wst.xml.ui, - org.eclipse.jdt.core.manipulation;bundle-version="1.16.100" + org.eclipse.jdt.core.manipulation;bundle-version="1.16.100", + com.gwtplugins.eclipse.jettylauncher;bundle-version="1.0.0" diff --git a/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchAttributes.java b/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchAttributes.java index 61473310..30995572 100644 --- a/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchAttributes.java +++ b/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchAttributes.java @@ -17,7 +17,7 @@ import com.google.gdt.eclipse.core.CorePlugin; /** - * + * */ public enum WebAppLaunchAttributes implements ILaunchConfigurationAttribute { /** @@ -30,6 +30,16 @@ public enum WebAppLaunchAttributes implements ILaunchConfigurationAttribute { */ SERVER_PORT("8888"), + /** + * Server class to use. + */ + SERVER_CLASS("com.google.gwt.dev.shell.jetty.JettyLauncher"), + + /** + * Server class to use. + */ + JETTY_HOME(""), + /** * Run a built-in server. */ @@ -41,10 +51,12 @@ public enum WebAppLaunchAttributes implements ILaunchConfigurationAttribute { this.defaultValue = defaultValue; } + @Override public Object getDefaultValue() { return defaultValue; } + @Override public String getQualifiedName() { return CorePlugin.PLUGIN_ID + "." + name(); } diff --git a/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchConfiguration.java b/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchConfiguration.java index 66345351..65477293 100644 --- a/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchConfiguration.java +++ b/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchConfiguration.java @@ -46,4 +46,10 @@ public static String getServerPort(ILaunchConfiguration launchConfiguration) return LaunchConfigurationAttributeUtilities.getString(launchConfiguration, WebAppLaunchAttributes.SERVER_PORT); } + + public static String getServerClass(ILaunchConfiguration launchConfiguration) + throws CoreException { + return LaunchConfigurationAttributeUtilities.getString(launchConfiguration, + WebAppLaunchAttributes.SERVER_CLASS); + } } \ No newline at end of file diff --git a/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchConfigurationWorkingCopy.java b/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchConfigurationWorkingCopy.java index 76d50a67..55d3da65 100644 --- a/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchConfigurationWorkingCopy.java +++ b/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/launch/WebAppLaunchConfigurationWorkingCopy.java @@ -17,7 +17,7 @@ import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; /** - * + * */ public class WebAppLaunchConfigurationWorkingCopy extends WebAppLaunchConfiguration { @@ -40,4 +40,10 @@ public static void setServerPort(ILaunchConfigurationWorkingCopy workingCopy, WebAppLaunchAttributes.SERVER_PORT, serverPort); } + public static void setServerClass(ILaunchConfigurationWorkingCopy workingCopy, + String serverClass) { + LaunchConfigurationAttributeUtilities.set(workingCopy, + WebAppLaunchAttributes.SERVER_CLASS, serverClass); + } + } \ No newline at end of file diff --git a/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/sdk/UpdateWebInfFolderCommand.java b/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/sdk/UpdateWebInfFolderCommand.java index aa0e5b4b..8af20082 100644 --- a/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/sdk/UpdateWebInfFolderCommand.java +++ b/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/sdk/UpdateWebInfFolderCommand.java @@ -119,7 +119,20 @@ public final void execute() throws CoreException, FileNotFoundException, // Copy the new files in for (File fileToAdd : filesToAdd) { IFile file = webInfLibFolder.getFile(fileToAdd.getName()); - if (file.exists()) { + if(fileToAdd.getName().equals("gwt-servlet.jar")) + { //check if jakarta version is used and replace gwt-servlet with that if needed. + if(file.exists() == false) + { + File jakartaFileToAdd = new File(fileToAdd.getParent(), "gwt-servlet-jakarta.jar"); + IFile jakartaFile = webInfLibFolder.getFile(jakartaFileToAdd.getName()); + if(jakartaFile.exists()) + { + fileToAdd = jakartaFileToAdd; + file = jakartaFile; + } + } + } + if (fileToAdd.exists()) { file.delete(true, false, new NullProgressMonitor()); } file.create(new FileInputStream(fileToAdd), true, null); diff --git a/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/validators/AbstractProjectValidator.java b/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/validators/AbstractProjectValidator.java index 5e90898f..75d0f1fd 100644 --- a/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/validators/AbstractProjectValidator.java +++ b/plugins/com.gwtplugins.gdt.eclipse.core/src/com/google/gdt/eclipse/core/validators/AbstractProjectValidator.java @@ -103,21 +103,21 @@ protected abstract void doAddSdkFileSizeMismatchMarker( * Given a Java project, validates that it has a classpath container with the * given ID on its build path, and the SDK that the container corresponds to * exists, is valid and supported. - * + * * If any problems are detected with finding or validating the SDK, error * markers with the given ID are created on the Java project's corresponding * IProject, and a value of false will be returned. - * + * * If the project has the Web Application Nature, then warning markers with * the given ID will be generated for each of the SDK's server classpath * libraries which are inconsistent with the contents of WEB-INF/lib. Even if * there are inconsistencies, a value of true will still be returned by this * method. - * + * * TODO: Ensure that only one SDK with the given containerID exists on the * project's build path; right now, this method looks for the first classpath * container entry that matches the containerID * - * + * * @return whether the classpath container refers to an existing and valid * SDK. * @throws CoreException @@ -169,11 +169,24 @@ protected boolean validateSdk(Sdk sdk) throws CoreException { } for (File webAppClasspathFile : sdk.getWebAppClasspathFiles(getProject())) { - IFile webInfLibFile = null; - - if (webInfLibFolder.exists()) { - webInfLibFile = webInfLibFolder.getFile(webAppClasspathFile.getName()); + String javaxName = webAppClasspathFile.getName(); + if("gwt-servlet.jar".equals(javaxName)) + { + if (webInfLibFolder.exists()) { + String jakartaName = javaxName.replace(".jar", "-jakarta.jar"); + IFile javaxFile = webInfLibFolder.getFile(javaxName); + IFile jakartaFile = webInfLibFolder.getFile(jakartaName); + if(jakartaFile.exists()) + { + webInfLibFile = jakartaFile; + webAppClasspathFile = new File(webAppClasspathFile.getParentFile(), jakartaName); + } + else + { + webInfLibFile = javaxFile; + } + } } if (webInfLibFile == null || !webInfLibFile.exists()) { diff --git a/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/WebAppLaunchDelegate.java b/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/WebAppLaunchDelegate.java index 5b32c80b..af12c9ae 100644 --- a/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/WebAppLaunchDelegate.java +++ b/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/WebAppLaunchDelegate.java @@ -32,6 +32,7 @@ import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; @@ -45,8 +46,11 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.wst.server.core.IModule; import org.eclipse.wst.server.core.ServerUtil; +import org.osgi.framework.Bundle; import java.io.File; +import java.io.IOException; +import java.net.URL; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -90,6 +94,56 @@ public static void maybePublishModulesToWarDirectory(ILaunchConfiguration config } } + /* (non-Javadoc) + * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getClasspathAndModulepath(org.eclipse.debug.core.ILaunchConfiguration) + */ + @Override + public String[][] getClasspathAndModulepath(ILaunchConfiguration config) throws CoreException { + String[][] paths = super.getClasspathAndModulepath(config); + try { + String path = getJettyLauncherPath(); + String[] cp = paths[0]; + String[] cpNew = new String[cp.length+1]; + System.arraycopy(cp, 0, cpNew, 0, cp.length); + cpNew[cpNew.length-1] = path; + paths[0] = cpNew; + } catch (Exception e) { + GdtPlugin.getLogger().logError(e, "Could not extend classpath"); + } + return paths; + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#getClasspath(org.eclipse.debug.core.ILaunchConfiguration) + */ + @Override + public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException { + String[] cp = super.getClasspath(configuration); + try { + String path = getJettyLauncherPath(); + String[] cpNew = new String[cp.length+1]; + System.arraycopy(cp, 0, cpNew, 0, cp.length); + cpNew[cpNew.length-1] = path; + cp = cpNew; + } catch (Exception e) { + GdtPlugin.getLogger().logError(e, "Could not extend classpath"); + } + return cp; + } + + /** + * @return + * @throws IOException + * + */ + private String getJettyLauncherPath() throws Exception { + Bundle plugin = org.eclipse.core.runtime.Platform.getBundle("com.gwtplugins.eclipse.jettylauncher"); + URL url = plugin.getResource("/"); + url = FileLocator.toFileURL(url); + String path = new File(url.toURI()).toString(); + return path; + } + @Override public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException { @@ -147,7 +201,7 @@ public void launch(ILaunchConfiguration configuration, String mode, ILaunch laun */ WebAppDebugModel.getInstance().addOrReturnExistingLaunchConfiguration(launch, null, null); } - + String cmd = this.showCommandLine(configuration, mode, launch, monitor); super.launch(configuration, mode, launch, monitor); } diff --git a/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/processors/JettyServerArgumentProcessor.java b/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/processors/JettyServerArgumentProcessor.java new file mode 100644 index 00000000..525f307e --- /dev/null +++ b/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/processors/JettyServerArgumentProcessor.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright 2011 Google Inc. All Rights Reserved. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +package com.google.gdt.eclipse.suite.launch.processors; + +import com.google.gdt.eclipse.core.launch.ILaunchConfigurationProcessor; +import com.google.gdt.eclipse.core.launch.LaunchConfigurationProcessorUtilities; +import com.google.gdt.eclipse.core.launch.WebAppLaunchConfiguration; +import com.google.gwt.eclipse.core.nature.GWTNature; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.jdt.core.IJavaProject; + +import java.util.List; + +/** + * Processes the "-server" argument for Jetty. + */ +public class JettyServerArgumentProcessor implements ILaunchConfigurationProcessor { + + private static final String ARG_SERVER = "-server"; + + @Override + public void update(ILaunchConfigurationWorkingCopy launchConfig, IJavaProject javaProject, List programArgs, + List vmArgs) throws CoreException { + + boolean runServer = WebAppLaunchConfiguration.getRunServer(launchConfig); + int serverArgIndex = programArgs.indexOf(ARG_SERVER); + String serverClass = WebAppLaunchConfiguration.getServerClass(launchConfig); + + IProject project = javaProject.getProject(); + LaunchConfigurationProcessorUtilities.removeArgsAndReturnInsertionIndex(programArgs, serverArgIndex, true); + if (runServer && GWTNature.isGWTProject(project)) { + programArgs.add(0, ARG_SERVER); + programArgs.add(1, serverClass); + } + } + + + @Override + public String validate(ILaunchConfiguration launchConfig, IJavaProject javaProject, List programArgs, + List vmArgs) throws CoreException { + return null; + } +} diff --git a/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/ui/tabs/WebAppServerTab.java b/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/ui/tabs/WebAppServerTab.java index 0d18c2ed..81961a99 100644 --- a/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/ui/tabs/WebAppServerTab.java +++ b/plugins/com.gwtplugins.gdt.eclipse.suite/src/com/google/gdt/eclipse/suite/launch/ui/tabs/WebAppServerTab.java @@ -23,12 +23,12 @@ import com.google.gdt.eclipse.core.launch.WebAppLaunchConfiguration; import com.google.gdt.eclipse.core.launch.WebAppLaunchConfigurationWorkingCopy; import com.google.gdt.eclipse.suite.GdtPlugin; +import com.google.gdt.eclipse.suite.launch.processors.JettyServerArgumentProcessor; import com.google.gdt.eclipse.suite.launch.processors.PortArgumentProcessor; import com.google.gdt.eclipse.suite.launch.processors.PortArgumentProcessor.PortParser; import com.google.gdt.eclipse.suite.resources.GdtImages; import com.google.gwt.eclipse.core.launch.processors.NoServerArgumentProcessor; -import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; @@ -59,11 +59,16 @@ public class WebAppServerTab extends JavaLaunchTab implements WebAppArgumentsTab.ArgumentsListener, UpdateLaunchConfigurationDialogBatcher.Listener { - // TODO: Create a subclass that contains the run server and autoport + private static final String DEFAULT_SERVER_CLASS = "com.google.gwt.dev.shell.jetty.JettyLauncher"; + private static final String JETTY12_JEE10_SERVER_CLASS = "com.gwtplugins.jettylauncher.jee10.Jetty12Launcher"; + private static final String JETTY12_JEE8_SERVER_CLASS = "com.gwtplugins.jettylauncher.jee8.Jetty12Launcher"; + /** - * May be null. */ + private Button noServerButton; private Button runServerButton; + private Button runJetty12Jee10ServerButton; + private Button runJetty12Jee8ServerButton; /** * May be null. @@ -125,13 +130,23 @@ public void dispose() { @Override public void doPerformApply(ILaunchConfigurationWorkingCopy configuration) { if (runServerButton != null) { - WebAppLaunchConfigurationWorkingCopy.setRunServer(configuration, runServerButton.getSelection()); + boolean runServer = ! noServerButton.getSelection(); + WebAppLaunchConfigurationWorkingCopy.setRunServer(configuration, runServer); + String serverClass = DEFAULT_SERVER_CLASS; + if(runJetty12Jee10ServerButton.getSelection()) + { + serverClass = JETTY12_JEE10_SERVER_CLASS; + } + else if(runJetty12Jee8ServerButton.getSelection()) + { + serverClass = JETTY12_JEE8_SERVER_CLASS; + } + WebAppLaunchConfigurationWorkingCopy.setServerClass(configuration, serverClass); } LaunchConfigurationProcessorUtilities.updateViaProcessor(new NoServerArgumentProcessor(), configuration); - // TODO remove and have folks use the CodeServerLauncher - //LaunchConfigurationProcessorUtilities.updateViaProcessor(new ServerArgumentProcessor(), configuration); + LaunchConfigurationProcessorUtilities.updateViaProcessor(new JettyServerArgumentProcessor(), configuration); WebAppLaunchConfigurationWorkingCopy.setServerPort(configuration, serverPortText.getText().trim()); @@ -160,7 +175,24 @@ public void initializeFrom(ILaunchConfiguration config) { super.initializeFrom(config); if (runServerButton != null) { - runServerButton.setSelection(WebAppLaunchConfiguration.getRunServer(config)); + boolean runServer = WebAppLaunchConfiguration.getRunServer(config); + noServerButton.setSelection( ! runServer); + if(runServer) + { + String serverClass = WebAppLaunchConfiguration.getServerClass(config); + if(JETTY12_JEE10_SERVER_CLASS.equals(serverClass)) + { + runJetty12Jee10ServerButton.setSelection(true); + } + else if(JETTY12_JEE8_SERVER_CLASS.equals(serverClass)) + { + runJetty12Jee8ServerButton.setSelection(true); + } + else + { + runServerButton.setSelection(true); + } + } } if (autoPortSelectionButton != null) { @@ -192,14 +224,13 @@ public boolean isValid(ILaunchConfiguration launchConfig) { return false; } - IProject project; try { IJavaProject javaProject = JavaRuntime.getJavaProject(launchConfig); if (javaProject == null) { return false; } - project = javaProject.getProject(); + javaProject.getProject(); } catch (CoreException ce) { // Thrown if the Java project does not exist, which is not of concern in // this tab (the Main tab handles those error messages) @@ -245,17 +276,24 @@ public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { } protected void createServerComponent(Composite parent) { - Group group = SWTFactory.createGroup(parent, "Embedded Jetty Server:", 3, 1, GridData.FILL_HORIZONTAL); + Group group = SWTFactory.createGroup(parent, "Run Server:", 3, 1, GridData.FILL_HORIZONTAL); if (showRunServerButton) { - runServerButton = SWTFactory.createCheckButton(group, "Run built-in server", null, true, 3); - runServerButton.addSelectionListener(new SelectionAdapter() { + noServerButton = SWTFactory.createRadioButton(group, "No server", 3); + SelectionAdapter selectionAdapter = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateEnabledState(); webAppServerTab.updateLaunchConfigurationDialog(); } - }); + }; + noServerButton.addSelectionListener(selectionAdapter); + runServerButton = SWTFactory.createRadioButton(group, "Run built-in server (Jetty 9)", 3); + runServerButton.addSelectionListener(selectionAdapter); + runJetty12Jee10ServerButton = SWTFactory.createRadioButton(group, "Run Jetty 12 JEE 10 server", 3); + runJetty12Jee10ServerButton.addSelectionListener(selectionAdapter); + runJetty12Jee8ServerButton = SWTFactory.createRadioButton(group, "Run Jetty 12 JEE 8 server", 3); + runJetty12Jee8ServerButton.addSelectionListener(selectionAdapter); } Label serverPortLabel = new Label(group, SWT.NONE); @@ -304,11 +342,12 @@ protected void updateLaunchConfigurationDialog() { private void updateEnabledState() { boolean usingAutoPort = autoPortSelectionButton != null && autoPortSelectionButton.getSelection(); - boolean runningServer = runServerButton == null || runServerButton.getSelection(); + boolean runningServer = runServerButton == null || runServerButton.getSelection() + || runJetty12Jee8ServerButton.getSelection() || runJetty12Jee10ServerButton.getSelection(); serverPortText.setEnabled(!usingAutoPort && runningServer); if (autoPortSelectionButton != null) { - autoPortSelectionButton.setEnabled(runServerButton.getSelection()); + autoPortSelectionButton.setEnabled(runningServer); } } } diff --git a/plugins/com.gwtplugins.gwt.eclipse.wtp/.classpath b/plugins/com.gwtplugins.gwt.eclipse.wtp/.classpath index 75ed2ff8..1db08c6b 100644 --- a/plugins/com.gwtplugins.gwt.eclipse.wtp/.classpath +++ b/plugins/com.gwtplugins.gwt.eclipse.wtp/.classpath @@ -1,8 +1,7 @@ - - - - - - - - + + + + + + + diff --git a/pom.xml b/pom.xml index c490fce5..d4192fd5 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ pom - 3.0.1 + 3.0.5 UTF-8 2023-09 @@ -39,6 +39,9 @@ resources + + plugins/com.gwtplugins.eclipse.jettylauncher + features/com.gwtplugins.eclipse.suite.v3.feature @@ -176,8 +179,8 @@ org.eclipse.tycho tycho-compiler-plugin ${tycho.version} - - true + + true diff --git a/resources/pom.xml b/resources/pom.xml index 50469f44..2ac4c8f2 100644 --- a/resources/pom.xml +++ b/resources/pom.xml @@ -32,8 +32,7 @@ wget - - http://goo.gl/t7FQSn + https://github.com/gwtproject/gwt/releases/download/${gwt.version}/gwt-${gwt.version}.zip false true