This is an automated email from the ASF dual-hosted git repository.
pdallig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/master by this push:
new 55a614ad16 [ZEPPELIN-5933] Polish jetty (#4621)
55a614ad16 is described below
commit 55a614ad16d220842324f425a159cf41612d76f6
Author: Philipp Dallig <[email protected]>
AuthorDate: Tue Jun 27 09:52:53 2023 +0200
[ZEPPELIN-5933] Polish jetty (#4621)
* Rewrite index.html handling
* Polish initialize of the Rest API
* Don't break the WebApp Classloader Isolation
* Use default SessionHandler
* Add simple session tests
---
.../apache/zeppelin/server/HtmlAddonResource.java | 173 ---------------------
.../apache/zeppelin/server/IndexHtmlServlet.java | 89 +++++++++++
.../apache/zeppelin/server/RestApiApplication.java | 59 +++++++
.../org/apache/zeppelin/server/ZeppelinServer.java | 54 +------
.../apache/zeppelin/rest/SessionRestApiTest.java | 84 ++++++++++
.../zeppelin/server/HtmlAddonResourceTest.java | 71 ---------
.../zeppelin/server/IndexHtmlServletTest.java | 111 +++++++++++++
zeppelin-web-angular/WEB-INF/web.xml | 22 +--
zeppelin-web/src/WEB-INF/web.xml | 9 --
9 files changed, 352 insertions(+), 320 deletions(-)
diff --git
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/HtmlAddonResource.java
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/HtmlAddonResource.java
deleted file mode 100644
index f504bf2007..0000000000
---
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/HtmlAddonResource.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zeppelin.server;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.eclipse.jetty.util.resource.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Resource for enabling html addons in index.html.
- */
-public class HtmlAddonResource extends Resource {
-
- private static final Logger LOGGER =
LoggerFactory.getLogger(HtmlAddonResource.class);
-
- private static final String TAG_BODY_OPENING = "<body"; // ignore bracket
here to support potential html attributes
- private static final String TAG_BODY_CLOSING = "</body>";
- private static final String TAG_HEAD_CLOSING = "</head>";
- private static final String TAG_HTML_CLOSING = "</html>";
-
- public static final String HTML_ADDON_IDENTIFIER =
"zeppelin-index-with-addon";
- public static final String INDEX_HTML_PATH = "/index.html";
-
- private final Resource indexResource;
- private File alteredTempFile = null;
- private byte[] alteredContent;
-
- public HtmlAddonResource(final Resource indexResource, final String
bodyAddon, final String headAddon) {
- LOGGER.info("Enabling html addons in {}: body='{}' head='{}'",
indexResource, bodyAddon, headAddon);
- this.indexResource = indexResource;
- try {
- // read original content from resource
- String content = IOUtils.toString(indexResource.getInputStream(),
StandardCharsets.UTF_8);
-
- // process body addon
- if (bodyAddon != null) {
- if (content.contains(TAG_BODY_CLOSING)) {
- content = content.replace(TAG_BODY_CLOSING, bodyAddon +
TAG_BODY_CLOSING);
- } else if (content.contains(TAG_HTML_CLOSING)) {
- content = content.replace(TAG_HTML_CLOSING, bodyAddon +
TAG_HTML_CLOSING);
- } else {
- content = content + bodyAddon;
- }
- }
-
- // process head addon
- if (headAddon != null) {
- if (content.contains(TAG_HEAD_CLOSING)) {
- content = content.replace(TAG_HEAD_CLOSING, headAddon +
TAG_HEAD_CLOSING);
- } else if (content.contains(TAG_BODY_OPENING)) {
- content = content.replace(TAG_BODY_OPENING, headAddon +
TAG_BODY_OPENING);
- } else {
- LOGGER.error("Unable to process Head html addon. Could not
find proper anchor in index.html.");
- }
- }
-
- this.alteredContent = content.getBytes(StandardCharsets.UTF_8);
-
- // only relevant in development mode: create altered temp file (as
zeppelin web archives are addressed via local
- // filesystem folders)
- if (indexResource.getFile() != null) {
- this.alteredTempFile =
File.createTempFile(HTML_ADDON_IDENTIFIER, ".html");
- this.alteredTempFile.deleteOnExit();
- FileUtils.writeByteArrayToFile(this.alteredTempFile,
this.alteredContent);
- }
-
- } catch (IOException e) {
- LOGGER.error("Error initializing html addons.", e);
- }
-
- }
-
- @Override
- public File getFile() throws IOException {
- return this.alteredTempFile;
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- return new ByteArrayInputStream(this.alteredContent);
- }
-
- @Override
- public String getName() {
- return indexResource.getName();
- }
-
- @Override
- public boolean isContainedIn(Resource r) throws MalformedURLException {
- return indexResource.isContainedIn(r);
- }
-
- @Override
- public boolean exists() {
- return indexResource.exists();
- }
-
- @Override
- public boolean isDirectory() {
- return indexResource.isDirectory();
- }
-
- @Override
- public long lastModified() {
- return indexResource.lastModified();
- }
-
- @Override
- public long length() {
- return alteredContent.length;
- }
-
- @Override
- public URL getURL() {
- return indexResource.getURL();
- }
-
- @Override
- public ReadableByteChannel getReadableByteChannel() throws IOException {
- return Channels.newChannel(new
ByteArrayInputStream(this.alteredContent));
- }
-
- @Override
- public boolean delete() throws SecurityException {
- throw new UnsupportedOperationException("Not supported");
- }
-
- @Override
- public boolean renameTo(Resource dest) throws SecurityException {
- throw new UnsupportedOperationException("Not supported");
- }
-
- @Override
- public String[] list() {
- throw new UnsupportedOperationException("Not supported");
- }
-
- @Override
- public Resource addPath(String path) throws IOException,
MalformedURLException {
- throw new UnsupportedOperationException("Not supported");
- }
-
- @Override
- public void close() {
- }
-
-}
diff --git
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/IndexHtmlServlet.java
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/IndexHtmlServlet.java
new file mode 100644
index 0000000000..10e7cf9d55
--- /dev/null
+++
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/IndexHtmlServlet.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zeppelin.server;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.zeppelin.conf.ZeppelinConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IndexHtmlServlet extends HttpServlet {
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(IndexHtmlServlet.class);
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ private static final String TAG_BODY_OPENING = "<body"; // ignore bracket
here to support potential html attributes
+ private static final String TAG_BODY_CLOSING = "</body>";
+ private static final String TAG_HEAD_CLOSING = "</head>";
+ private static final String TAG_HTML_CLOSING = "</html>";
+
+ final String bodyAddon;
+ final String headAddon;
+
+ public IndexHtmlServlet(ZeppelinConfiguration conf) {
+ this.bodyAddon = conf.getHtmlBodyAddon();
+ this.headAddon = conf.getHtmlHeadAddon();
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ try {
+ URL indexResource = getServletContext().getResource("/index.html");
+ String content = IOUtils.toString(indexResource, StandardCharsets.UTF_8);
+ // read original content from resource
+ if (bodyAddon != null) {
+ if (content.contains(TAG_BODY_CLOSING)) {
+ content = content.replace(TAG_BODY_CLOSING, bodyAddon +
TAG_BODY_CLOSING);
+ } else if (content.contains(TAG_HTML_CLOSING)) {
+ content = content.replace(TAG_HTML_CLOSING, bodyAddon +
TAG_HTML_CLOSING);
+ } else {
+ content = content + bodyAddon;
+ }
+ }
+ // process head addon
+ if (headAddon != null) {
+ if (content.contains(TAG_HEAD_CLOSING)) {
+ content = content.replace(TAG_HEAD_CLOSING, headAddon +
TAG_HEAD_CLOSING);
+ } else if (content.contains(TAG_BODY_OPENING)) {
+ content = content.replace(TAG_BODY_OPENING, headAddon +
TAG_BODY_OPENING);
+ } else {
+ LOGGER.error(
+ "Unable to process Head html addon. Could not find proper anchor
in index.html.");
+ }
+ }
+ resp.setContentType("text/html");
+ resp.setStatus(HttpServletResponse.SC_OK);
+ resp.getWriter().append(content);
+ } catch (IOException e) {
+ LOGGER.error("Error rendering index.html.", e);
+ }
+ }
+}
diff --git
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/RestApiApplication.java
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/RestApiApplication.java
new file mode 100644
index 0000000000..56e29e8742
--- /dev/null
+++
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/RestApiApplication.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zeppelin.server;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+import org.apache.zeppelin.rest.AdminRestApi;
+import org.apache.zeppelin.rest.ClusterRestApi;
+import org.apache.zeppelin.rest.ConfigurationsRestApi;
+import org.apache.zeppelin.rest.CredentialRestApi;
+import org.apache.zeppelin.rest.HeliumRestApi;
+import org.apache.zeppelin.rest.InterpreterRestApi;
+import org.apache.zeppelin.rest.LoginRestApi;
+import org.apache.zeppelin.rest.NotebookRepoRestApi;
+import org.apache.zeppelin.rest.NotebookRestApi;
+import org.apache.zeppelin.rest.SecurityRestApi;
+import org.apache.zeppelin.rest.SessionRestApi;
+import org.apache.zeppelin.rest.ZeppelinRestApi;
+import org.apache.zeppelin.rest.exception.WebApplicationExceptionMapper;
+
+public class RestApiApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ Set<Class<?>> s = new HashSet<>();
+ s.add(AdminRestApi.class);
+ s.add(ClusterRestApi.class);
+ s.add(ConfigurationsRestApi.class);
+ s.add(CredentialRestApi.class);
+ s.add(HeliumRestApi.class);
+ s.add(InterpreterRestApi.class);
+ s.add(LoginRestApi.class);
+ s.add(NotebookRepoRestApi.class);
+ s.add(NotebookRestApi.class);
+ s.add(SecurityRestApi.class);
+ s.add(SessionRestApi.class);
+ s.add(ZeppelinRestApi.class);
+
+ // add ExceptionMapper
+ s.add(WebApplicationExceptionMapper.class);
+ return s;
+ }
+}
diff --git
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java
index ae6846d554..86322ebb3b 100644
---
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java
+++
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java
@@ -20,8 +20,6 @@ import com.codahale.metrics.servlets.HealthCheckServlet;
import com.codahale.metrics.servlets.PingServlet;
import com.google.gson.Gson;
-import static
org.apache.zeppelin.server.HtmlAddonResource.HTML_ADDON_IDENTIFIER;
-
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Tags;
@@ -111,11 +109,8 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.server.session.SessionHandler;
-import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.WebAppContext;
import
org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
@@ -125,13 +120,12 @@ import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.api.ServiceLocatorFactory;
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
-import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Main class of Zeppelin. */
-public class ZeppelinServer extends ResourceConfig {
+public class ZeppelinServer {
private static final Logger LOG =
LoggerFactory.getLogger(ZeppelinServer.class);
private static final String WEB_APP_CONTEXT_NEXT = "/next";
@@ -141,8 +135,6 @@ public class ZeppelinServer extends ResourceConfig {
public ZeppelinServer(ZeppelinConfiguration conf) {
LOG.info("Instantiated ZeppelinServer");
InterpreterOutput.LIMIT =
conf.getInt(ConfVars.ZEPPELIN_INTERPRETER_OUTPUT_LIMIT);
-
- packages("org.apache.zeppelin.rest");
}
public static void main(String[] args) throws IOException {
@@ -549,9 +541,8 @@ public class ZeppelinServer extends ResourceConfig {
final ServletHolder servletHolder =
new ServletHolder(new org.glassfish.jersey.servlet.ServletContainer());
- servletHolder.setInitParameter("javax.ws.rs.Application",
ZeppelinServer.class.getName());
+ servletHolder.setInitParameter("javax.ws.rs.Application",
RestApiApplication.class.getName());
servletHolder.setName("rest");
- webapp.setSessionHandler(new SessionHandler());
webapp.addServlet(servletHolder, "/api/*");
String shiroIniPath = conf.getShiroPath();
@@ -584,7 +575,6 @@ public class ZeppelinServer extends ResourceConfig {
// Development mode, read from FS
// webApp.setDescriptor(warPath+"/WEB-INF/web.xml");
webApp.setResourceBase(warFile.getPath());
- webApp.setParentLoaderPriority(true);
} else {
// use packaged WAR
webApp.setWar(warFile.getAbsolutePath());
@@ -595,7 +585,7 @@ public class ZeppelinServer extends ResourceConfig {
webApp.setTempDirectory(warTempDirectory);
}
// Explicit bind to root
- webApp.addServlet(new ServletHolder(setupServlet(webApp, conf)), "/*");
+ webApp.addServlet(new ServletHolder(new IndexHtmlServlet(conf)),
"/index.html");
contexts.addHandler(webApp);
webApp.addFilter(new FilterHolder(CorsFilter.class), "/*",
EnumSet.allOf(DispatcherType.class));
@@ -606,44 +596,6 @@ public class ZeppelinServer extends ResourceConfig {
return webApp;
}
- private static DefaultServlet setupServlet(
- WebAppContext webApp,
- ZeppelinConfiguration conf) {
-
- // provide DefaultServlet as is in case html addon is not used
- if (conf.getHtmlBodyAddon()==null && conf.getHtmlHeadAddon()==null) {
- return new DefaultServlet();
- }
-
- // override ResourceFactory interface part of DefaultServlet for
intercepting the static index.html properly.
- return new DefaultServlet() {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- public Resource getResource(String pathInContext) {
-
- // proceed for everything but '/index.html'
- if (!HtmlAddonResource.INDEX_HTML_PATH.equals(pathInContext)) {
- return super.getResource(pathInContext);
- }
-
- // create the altered 'index.html' resource and cache it via
webapp attributes
- if (webApp.getAttribute(HTML_ADDON_IDENTIFIER) == null) {
- webApp.setAttribute(
- HTML_ADDON_IDENTIFIER,
- new HtmlAddonResource(
- super.getResource(pathInContext),
- conf.getHtmlBodyAddon(),
- conf.getHtmlHeadAddon()));
- }
-
- return (Resource) webApp.getAttribute(HTML_ADDON_IDENTIFIER);
- }
-
- };
- }
-
private static void initWebApp(WebAppContext webApp, ZeppelinConfiguration
conf, ServiceLocator sharedServiceLocator, PrometheusMeterRegistry
promMetricRegistry) {
webApp.addEventListener(
new ServletContextListener() {
diff --git
a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/SessionRestApiTest.java
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/SessionRestApiTest.java
new file mode 100644
index 0000000000..dfca0202dd
--- /dev/null
+++
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/SessionRestApiTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zeppelin.rest;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.apache.zeppelin.common.SessionInfo;
+import org.apache.zeppelin.server.JsonResponse;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+import javax.ws.rs.core.Response.Status;
+
+class SessionRestApiTest extends AbstractTestRestApi {
+ Gson gson = new Gson();
+
+ @BeforeAll
+ static void init() throws Exception {
+ AbstractTestRestApi.startUp(SessionRestApi.class.getSimpleName());
+ }
+
+ @AfterAll
+ static void destroy() throws Exception {
+ AbstractTestRestApi.shutDown();
+ }
+
+ @Test
+ void testGetNotAvailableSession() throws IOException {
+ try (CloseableHttpResponse get = httpGet("/session/testSession")) {
+ assertEquals(Status.NOT_FOUND.getStatusCode(),
get.getStatusLine().getStatusCode());
+ }
+ }
+
+ @Test
+ void testStartAndStopSession() throws IOException {
+ String interpreter = "testInterpreter";
+ try (CloseableHttpResponse post = httpPost("/session?interpreter=" +
interpreter, "")) {
+ assertEquals(Status.OK.getStatusCode(),
post.getStatusLine().getStatusCode());
+ Type collectionType = new TypeToken<JsonResponse<SessionInfo>>() {
+ }.getType();
+ JsonResponse<SessionInfo> resp = gson
+ .fromJson(EntityUtils.toString(post.getEntity(),
StandardCharsets.UTF_8), collectionType);
+ SessionInfo info = resp.getBody();
+
+ // Get by interpreter name
+ try (CloseableHttpResponse get = httpGet("/session?interpreter" +
interpreter)) {
+ assertEquals(Status.OK.getStatusCode(),
get.getStatusLine().getStatusCode());
+ }
+
+ // Get by sessionId
+ try (CloseableHttpResponse get = httpGet("/session/" +
info.getSessionId())) {
+ assertEquals(Status.OK.getStatusCode(),
get.getStatusLine().getStatusCode());
+ }
+
+ // Delete session
+ try (CloseableHttpResponse delete = httpDelete("/session/" +
info.getSessionId())) {
+ assertEquals(Status.OK.getStatusCode(),
delete.getStatusLine().getStatusCode());
+ }
+ }
+
+ }
+}
diff --git
a/zeppelin-server/src/test/java/org/apache/zeppelin/server/HtmlAddonResourceTest.java
b/zeppelin-server/src/test/java/org/apache/zeppelin/server/HtmlAddonResourceTest.java
deleted file mode 100644
index 65d51d9fe7..0000000000
---
a/zeppelin-server/src/test/java/org/apache/zeppelin/server/HtmlAddonResourceTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.zeppelin.server;
-
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.commons.io.IOUtils;
-import org.eclipse.jetty.util.resource.Resource;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-class HtmlAddonResourceTest {
-
- private final static String TEST_BODY_ADDON = "<!-- foo -->";
- private final static String TEST_HEAD_ADDON = "<!-- bar -->";
-
- private final static String FILE_PATH_INDEX_HTML_ZEPPELIN_WEB =
"../zeppelin-web/dist/index.html";
- private final static String FILE_PATH_INDEX_HTML_ZEPPELIN_WEB_ANGULAR =
"../zeppelin-web-angular/dist/zeppelin/index.html";
-
- @Test
- void testZeppelinWebHtmlAddon() throws IOException {
- final Resource addonResource =
getHtmlAddonResource(FILE_PATH_INDEX_HTML_ZEPPELIN_WEB);
-
- final String content =
IOUtils.toString(addonResource.getInputStream(), StandardCharsets.UTF_8);
-
- assertThat(content, containsString(TEST_BODY_ADDON));
- assertThat(content, containsString(TEST_HEAD_ADDON));
-
- }
-
- @Test
- @Disabled // ignored due to zeppelin-web-angular not build for core tests
- void testZeppelinWebAngularHtmlAddon() throws IOException {
- final Resource addonResource =
getHtmlAddonResource(FILE_PATH_INDEX_HTML_ZEPPELIN_WEB_ANGULAR);
-
- final String content =
IOUtils.toString(addonResource.getInputStream(), StandardCharsets.UTF_8);
-
- assertThat(content, containsString(TEST_BODY_ADDON));
- assertThat(content, containsString(TEST_HEAD_ADDON));
-
- }
-
- private Resource getHtmlAddonResource(final String indexHtmlPath) {
- return getHtmlAddonResource(indexHtmlPath, TEST_BODY_ADDON,
TEST_HEAD_ADDON);
- }
-
- private Resource getHtmlAddonResource(final String indexHtmlPath, final
String bodyAddon, final String headAddon) {
- final Resource indexResource = Resource.newResource(new
File(indexHtmlPath));
- return new HtmlAddonResource(indexResource, TEST_BODY_ADDON,
TEST_HEAD_ADDON);
- }
-
-}
diff --git
a/zeppelin-server/src/test/java/org/apache/zeppelin/server/IndexHtmlServletTest.java
b/zeppelin-server/src/test/java/org/apache/zeppelin/server/IndexHtmlServletTest.java
new file mode 100644
index 0000000000..5e8173df96
--- /dev/null
+++
b/zeppelin-server/src/test/java/org/apache/zeppelin/server/IndexHtmlServletTest.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zeppelin.server;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URL;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.zeppelin.conf.ZeppelinConfiguration;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+class IndexHtmlServletTest {
+
+ private final static String TEST_BODY_ADDON = "<!-- foo -->";
+ private final static String TEST_HEAD_ADDON = "<!-- bar -->";
+
+ private final static String FILE_PATH_INDEX_HTML_ZEPPELIN_WEB =
"../zeppelin-web/dist/index.html";
+ private final static String FILE_PATH_INDEX_HTML_ZEPPELIN_WEB_ANGULAR =
"../zeppelin-web-angular/dist/zeppelin/index.html";
+
+
+ @Test
+ void testZeppelinWebHtmlAddon() throws IOException, ServletException {
+ ZeppelinConfiguration conf = mock(ZeppelinConfiguration.class);
+ when(conf.getHtmlBodyAddon()).thenReturn(TEST_BODY_ADDON);
+ when(conf.getHtmlHeadAddon()).thenReturn(TEST_HEAD_ADDON);
+
+ ServletConfig sc = mock(ServletConfig.class);
+ ServletContext ctx = mock(ServletContext.class);
+ when(ctx.getResource("/index.html"))
+ .thenReturn(new URL("file:" + FILE_PATH_INDEX_HTML_ZEPPELIN_WEB));
+ when(sc.getServletContext()).thenReturn(ctx);
+
+ IndexHtmlServlet servlet = new IndexHtmlServlet(conf);
+ servlet.init(sc);
+
+ HttpServletResponse mockResponse = mock(HttpServletResponse.class);
+ HttpServletRequest mockRequest = mock(HttpServletRequest.class);
+
+ // Catch content in ByteArrayOutputStream
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ PrintWriter writer = new PrintWriter(out);
+ when(mockResponse.getWriter()).thenReturn(writer);
+
+ servlet.doGet(mockRequest, mockResponse);
+ writer.flush();
+ // Get Content
+ String content = new String(out.toString());
+
+ assertThat(content, containsString(TEST_BODY_ADDON));
+ assertThat(content, containsString(TEST_HEAD_ADDON));
+
+ }
+
+ @Test
+ @Disabled("ignored due to zeppelin-web-angular not build for core tests")
+ void testZeppelinWebAngularHtmlAddon() throws IOException,
ServletException {
+ ZeppelinConfiguration conf = mock(ZeppelinConfiguration.class);
+ when(conf.getHtmlBodyAddon()).thenReturn(TEST_BODY_ADDON);
+ when(conf.getHtmlHeadAddon()).thenReturn(TEST_HEAD_ADDON);
+
+ ServletConfig sc = mock(ServletConfig.class);
+ ServletContext ctx = mock(ServletContext.class);
+ when(ctx.getResource("/index.html"))
+ .thenReturn(new URL("file:" +
FILE_PATH_INDEX_HTML_ZEPPELIN_WEB_ANGULAR));
+ when(sc.getServletContext()).thenReturn(ctx);
+
+ IndexHtmlServlet servlet = new IndexHtmlServlet(conf);
+ servlet.init(sc);
+
+ HttpServletResponse mockResponse = mock(HttpServletResponse.class);
+ HttpServletRequest mockRequest = mock(HttpServletRequest.class);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ PrintWriter writer = new PrintWriter(out);
+ when(mockResponse.getWriter()).thenReturn(writer);
+
+ servlet.doGet(mockRequest, mockResponse);
+ writer.flush();
+ // Get Content
+ String content = new String(out.toString());
+
+ assertThat(content, containsString(TEST_BODY_ADDON));
+ assertThat(content, containsString(TEST_HEAD_ADDON));
+
+ }
+}
diff --git a/zeppelin-web-angular/WEB-INF/web.xml
b/zeppelin-web-angular/WEB-INF/web.xml
index f40bf86173..43524f4f90 100644
--- a/zeppelin-web-angular/WEB-INF/web.xml
+++ b/zeppelin-web-angular/WEB-INF/web.xml
@@ -12,25 +12,15 @@
-->
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
- version="3.0">
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
<display-name>zeppelin-web-angular</display-name>
- <servlet>
- <servlet-name>default</servlet-name>
-
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
- <init-param>
- <param-name>jersey.config.server.provider.packages</param-name>
- <param-value>org.apache.zeppelin.rest</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <context-param>
- <param-name>configuration</param-name>
- <param-value>deployment</param-value>
- </context-param>
+ <context-param>
+ <param-name>configuration</param-name>
+ <param-value>deployment</param-value>
+ </context-param>
<session-config>
<cookie-config>
diff --git a/zeppelin-web/src/WEB-INF/web.xml b/zeppelin-web/src/WEB-INF/web.xml
index f7094028fe..179bd02818 100644
--- a/zeppelin-web/src/WEB-INF/web.xml
+++ b/zeppelin-web/src/WEB-INF/web.xml
@@ -22,15 +22,6 @@
version="3.0">
<display-name>zeppelin-web</display-name>
- <servlet>
- <servlet-name>restServlet</servlet-name>
-
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
- <init-param>
- <param-name>jersey.config.server.provider.packages</param-name>
- <param-value>org.apache.zeppelin.rest</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
<error-page>
<error-code>404</error-code>