blob: f9ea06d2806beb856080dd598ed6c49740fa64c6 [file] [log] [blame]
/*
* 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.slider.server.appmaster.web.rest.agent;
import com.google.common.base.Preconditions;
import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.spi.container.WebApplication;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import com.sun.jersey.spi.container.servlet.WebConfig;
import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider;
import org.apache.slider.core.conf.MapOperations;
import org.apache.slider.providers.agent.AgentKeys;
import org.apache.slider.server.appmaster.web.WebAppApi;
import org.apache.slider.server.appmaster.web.rest.RestPaths;
import org.apache.slider.server.services.security.SecurityUtils;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.security.SslSelectChannelConnector;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.ServletHolder;
import org.mortbay.thread.QueuedThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.ext.Provider;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.Set;
/**
*
*/
public class AgentWebApp implements Closeable {
protected static final Logger LOG = LoggerFactory.getLogger(AgentWebApp.class);
private int port;
private int securedPort;
private static Server agentServer;
public static final String BASE_PATH = "slideragent";
public static class Builder {
final String name;
final String wsName;
final WebAppApi application;
MapOperations configsMap;
public Builder(String name, String wsName, WebAppApi application) {
this.name = name;
this.wsName = wsName;
this.application = application;
}
public Builder withComponentConfig(MapOperations appMasterConfig) {
this.configsMap = appMasterConfig;
return this;
}
public AgentWebApp start() throws IOException {
if (configsMap == null) {
throw new IllegalStateException("No SSL Configuration Available");
}
agentServer = new Server();
agentServer.setThreadPool(
new QueuedThreadPool(
configsMap.getOptionInt("agent.threadpool.size.max", 25)));
agentServer.setStopAtShutdown(true);
SslSelectChannelConnector ssl1WayConnector = createSSLConnector(false);
SslSelectChannelConnector ssl2WayConnector =
createSSLConnector(Boolean.valueOf(
configsMap.getOption(AgentKeys.KEY_AGENT_TWO_WAY_SSL_ENABLED,
"false")));
agentServer.setConnectors(new Connector[]{ssl1WayConnector,
ssl2WayConnector});
ServletHolder agent = new ServletHolder(new AgentServletContainer());
Context agentRoot = new Context(agentServer, "/", Context.SESSIONS);
agent.setInitParameter("com.sun.jersey.config.property.resourceConfigClass",
"com.sun.jersey.api.core.PackagesResourceConfig");
agent.setInitParameter("com.sun.jersey.config.property.packages",
"org.apache.slider.server.appmaster.web.rest.agent");
agent.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature",
"true");
// agent.setInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters", "com.sun.jersey.api.container.filter.LoggingFilter");
// agent.setInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters", "com.sun.jersey.api.container.filter.LoggingFilter");
// agent.setInitParameter("com.sun.jersey.config.feature.Trace", "true");
agentRoot.addServlet(agent, "/*");
try {
agentServer.start();
} catch (IOException e) {
LOG.error("Unable to start agent server", e);
throw e;
} catch (Exception e) {
LOG.error("Unable to start agent server", e);
throw new IOException("Unable to start agent server: " + e, e);
}
AgentWebApp webApp = new AgentWebApp();
webApp.setPort(getConnectorPort(agentServer, 0));
webApp.setSecuredPort(getConnectorPort(agentServer, 1));
return webApp;
}
private SslSelectChannelConnector createSSLConnector(boolean needClientAuth) {
SslSelectChannelConnector sslConnector = new
SslSelectChannelConnector();
String keystore = SecurityUtils.getSecurityDir() +
File.separator + "keystore.p12";
String srvrCrtPass = SecurityUtils.getKeystorePass();
sslConnector.setKeystore(keystore);
sslConnector.setTruststore(keystore);
sslConnector.setPassword(srvrCrtPass);
sslConnector.setKeyPassword(srvrCrtPass);
sslConnector.setTrustPassword(srvrCrtPass);
sslConnector.setKeystoreType("PKCS12");
sslConnector.setTruststoreType("PKCS12");
sslConnector.setNeedClientAuth(needClientAuth);
sslConnector.setAcceptors(2);
return sslConnector;
}
@Provider
public class WebAppApiProvider extends
SingletonTypeInjectableProvider<javax.ws.rs.core.Context, WebAppApi> {
public WebAppApiProvider () {
super(WebAppApi.class, application);
}
}
public class AgentServletContainer extends ServletContainer {
public AgentServletContainer() {
super();
}
@Override
protected void configure(WebConfig wc,
ResourceConfig rc,
WebApplication wa) {
super.configure(wc, rc, wa);
Set<Object> singletons = rc.getSingletons();
singletons.add(new WebAppApiProvider());
}
}
private int getConnectorPort(Server webServer, int index) {
Preconditions.checkArgument(index >= 0);
if (index > webServer.getConnectors().length)
throw new IllegalStateException("Illegal connect index requested");
Connector c = webServer.getConnectors()[index];
if (c.getLocalPort() == -1) {
// The connector is not bounded
throw new IllegalStateException("The connector is not bound to a port");
}
return c.getLocalPort();
}
}
public static Builder $for(String name, WebAppApi app, String wsPrefix) {
return new Builder(name, wsPrefix, app);
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public void setSecuredPort(int securedPort) {
this.securedPort = securedPort;
}
public int getSecuredPort() {
return securedPort;
}
public void close() throws IOException{
//need to stop server and reset injector
try {
agentServer.stop();
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException(e.toString(), e);
}
}
}