diff options
Diffstat (limited to 'sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org')
6 files changed, 663 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/ContainerLoader.java b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/ContainerLoader.java new file mode 100644 index 0000000000..60c9a7961f --- /dev/null +++ b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/ContainerLoader.java @@ -0,0 +1,100 @@ +/** + * + * Copyright 2005 The Apache Software Foundation + * + * Licensed 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.tuscany.tomcat; + +import java.beans.PropertyChangeListener; + +import org.apache.catalina.Container; +import org.apache.catalina.Loader; + +/** + * Implementation of a TomcatLoader that allows privileged servlets from the container + * classloader to be loaded into an unprivileged application. This allows the Tuscany + * integration code to add servlets to the application, for example, to handle web + * services requests. + * + * @version $Rev$ $Date$ + */ +public class ContainerLoader implements Loader { + private static final String INFO = ContainerLoader.class.getName() + "/SNAPSHOT"; + private final ClassLoader cl; + private Container container; + + /** + * Constructor specifying the classloader to be used. + * + * @param cl the classloader this Loader wraps, typically the container classloader + */ + public ContainerLoader(ClassLoader cl) { + this.cl = cl; + } + + public void backgroundProcess() { + } + + public ClassLoader getClassLoader() { + return cl; + } + + public Container getContainer() { + return container; + } + + public void setContainer(Container container) { + this.container = container; + } + + public boolean getDelegate() { + return false; + } + + public void setDelegate(boolean delegate) { + throw new UnsupportedOperationException(); + } + + public String getInfo() { + return INFO; + } + + public boolean getReloadable() { + return false; + } + + public void setReloadable(boolean reloadable) { + throw new UnsupportedOperationException(); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + throw new UnsupportedOperationException(); + } + + public void addRepository(String repository) { + throw new UnsupportedOperationException(); + } + + public String[] findRepositories() { + throw new UnsupportedOperationException(); + } + + public boolean modified() { + throw new UnsupportedOperationException(); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + throw new UnsupportedOperationException(); + } +} diff --git a/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TomcatHost.java b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TomcatHost.java new file mode 100644 index 0000000000..8351da8edd --- /dev/null +++ b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TomcatHost.java @@ -0,0 +1,53 @@ +/** + * + * Copyright 2006 The Apache Software Foundation + * + * Licensed 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.tuscany.tomcat; + +import javax.servlet.Servlet; + +import org.osoa.sca.annotations.Scope; + +import org.apache.tuscany.core.webapp.ServletHost; + +/** + * SCA Component that acts as a proxy for the Tomcat Host container that created the runtime. + * + * @version $Rev$ $Date$ + */ +@Scope("MODULE") +public class TomcatHost implements ServletHost { + private TuscanyHost host; + + public void setHost(TuscanyHost host) { + this.host = host; + } + + public TuscanyHost getHost() { + return host; + } + + public void registerMapping(String mapping, Servlet servlet) { + host.registerMapping(mapping, servlet); + } + + public void unregisterMapping(String mapping) { + host.unregisterMapping(mapping); + } + + public Servlet getMapping(String mapping) { + return host.getMapping(mapping); + } +} diff --git a/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyContextListener.java b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyContextListener.java new file mode 100644 index 0000000000..7e3edf67f9 --- /dev/null +++ b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyContextListener.java @@ -0,0 +1,152 @@ +/** + * + * Copyright 2005 The Apache Software Foundation + * + * Licensed 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.tuscany.tomcat; + +import javax.servlet.ServletContext; + +import org.apache.catalina.Context; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleEvent; +import org.apache.catalina.LifecycleListener; +import org.apache.catalina.util.StringManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tuscany.common.resource.ResourceLoader; +import org.apache.tuscany.common.resource.impl.ResourceLoaderImpl; +import org.apache.tuscany.core.client.BootstrapHelper; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.config.ModuleComponentConfigurationLoader; +import org.apache.tuscany.core.context.CompositeContext; +import org.apache.tuscany.core.context.EventException; +import org.apache.tuscany.core.context.event.ModuleStart; +import org.apache.tuscany.core.context.event.ModuleStop; +import org.apache.tuscany.core.runtime.RuntimeContext; +import org.apache.tuscany.model.assembly.AssemblyFactory; +import org.apache.tuscany.model.assembly.ModuleComponent; +import org.apache.tuscany.model.assembly.impl.AssemblyContextImpl; +import org.apache.tuscany.model.assembly.loader.AssemblyModelLoader; + +/** + * @version $Rev$ $Date$ + */ +public class TuscanyContextListener implements LifecycleListener { + private static final Log log = LogFactory.getLog(TuscanyContextListener.class); + private static final StringManager sm = StringManager.getManager("org.apache.tuscany.tomcat"); + private static final String TUSCANY_RUNTIME_NAME = RuntimeContext.class.getName(); + public static final String MODULE_COMPONENT_NAME = "org.apache.tuscany.core.webapp.ModuleComponentContext"; + + private final AssemblyFactory modelFactory; + private final AssemblyModelLoader modelLoader; + private final RuntimeContext runtime; + private CompositeContext moduleContext; + private TuscanyValve valve; + + public TuscanyContextListener(RuntimeContext runtimeContext, AssemblyFactory modelFactory, AssemblyModelLoader modelLoader) { + this.runtime = runtimeContext; + this.modelFactory = modelFactory; + this.modelLoader = modelLoader; + } + + public void lifecycleEvent(LifecycleEvent event) { + String type = event.getType(); + if (Lifecycle.AFTER_START_EVENT.equals(type)) { + startContext((Context) event.getLifecycle()); + } else if (Lifecycle.STOP_EVENT.equals(type)) { + stopContext((Context) event.getLifecycle()); + } + } + + private void startContext(Context ctx) { + ClassLoader appLoader = ctx.getLoader().getClassLoader(); + if (appLoader.getResource("sca.module") == null) { + return; + } + + log.info(sm.getString("context.configLoad", ctx.getName())); + try { + loadContext(ctx); + } catch (ConfigurationException e) { + log.error(sm.getString("context.configError"), e); + // todo mark application as unavailable + return; + } + + try { + moduleContext.publish(new ModuleStart(this)); + } catch (EventException e) { + log.error(sm.getString("context.moduleStartError"), e); + // todo unload module component from runtime + // todo mark application as unavailable + return; + } catch (RuntimeException e) { + log.error(sm.getString("context.unknownRuntimeException"), e); + // todo unload module component from runtime + throw e; + } + + // add a valve to this context's pipeline that will associate the request with the runtime + if (valve == null) { + valve = new TuscanyValve(moduleContext); + } else { + valve.setContext(moduleContext); + valve.setEnabled(true); + } + ctx.getPipeline().addValve(valve); + // add the RuntimeContext in as a servlet context parameter + ServletContext servletContext = ctx.getServletContext(); + servletContext.setAttribute(TUSCANY_RUNTIME_NAME, runtime); + servletContext.setAttribute(MODULE_COMPONENT_NAME, moduleContext); + } + + private void loadContext(Context ctx) throws ConfigurationException { + ResourceLoader resourceLoader = new ResourceLoaderImpl(ctx.getLoader().getClassLoader()); + ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + try { + AssemblyContextImpl modelContext = new AssemblyContextImpl(modelFactory, modelLoader, resourceLoader, ctx.getName()); + + ModuleComponentConfigurationLoader loader = BootstrapHelper.getConfigurationLoader(runtime.getSystemContext(), modelContext); + + // Load the SCDL configuration of the application module + ModuleComponent moduleComponent = loader.loadModuleComponent(ctx.getName(), ctx.getPath()); + + // Register it under the root application context + CompositeContext rootContext = runtime.getRootContext(); + rootContext.registerModelObject(moduleComponent); + moduleContext = (CompositeContext) rootContext.getContext(moduleComponent.getName()); + //TODO remove the hack below + moduleContext.setAssemblyContext(modelContext); + } finally { + Thread.currentThread().setContextClassLoader(oldCl); + } + } + + private void stopContext(Context ctx) { + if (moduleContext != null) { + moduleContext.publish(new ModuleStop(this)); + } + CompositeContext rootContext = runtime.getRootContext(); + rootContext.removeContext(moduleContext.getName()); + valve.setEnabled(false); + //ctx.getPipeline().removeValve(valve); + //valve = null; + moduleContext.stop(); + moduleContext = null; + // todo unload module component from runtime + } + +} diff --git a/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyHost.java b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyHost.java new file mode 100644 index 0000000000..37984ef40d --- /dev/null +++ b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyHost.java @@ -0,0 +1,185 @@ +/** + * + * Copyright 2005 The Apache Software Foundation + * + * Licensed 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.tuscany.tomcat; + +import javax.servlet.Servlet; + +import org.apache.catalina.Container; +import org.apache.catalina.Context; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.Wrapper; +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.core.StandardHost; +import org.apache.catalina.util.StringManager; +import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.http.mapper.MappingData; + +import org.apache.tuscany.common.monitor.impl.NullMonitorFactory; +import org.apache.tuscany.core.builder.ContextFactoryBuilderRegistry; +import org.apache.tuscany.core.builder.impl.DefaultWireBuilder; +import org.apache.tuscany.core.client.BootstrapHelper; +import org.apache.tuscany.core.config.ConfigurationLoadException; +import org.apache.tuscany.core.config.ModuleComponentConfigurationLoader; +import org.apache.tuscany.core.context.CompositeContext; +import org.apache.tuscany.core.context.SystemCompositeContext; +import org.apache.tuscany.core.context.event.ModuleStart; +import org.apache.tuscany.core.context.event.ModuleStop; +import org.apache.tuscany.core.runtime.RuntimeContext; +import org.apache.tuscany.core.runtime.RuntimeContextImpl; +import org.apache.tuscany.core.webapp.ServletHost; +import org.apache.tuscany.model.assembly.AssemblyContext; +import org.apache.tuscany.model.assembly.AssemblyFactory; +import org.apache.tuscany.model.assembly.ModuleComponent; +import org.apache.tuscany.model.assembly.loader.AssemblyModelLoader; + +/** + * A specialied Tomcat Host that extends the Standardhost implementation and adds SCA capabilities. + * <p/> + * As children are added, they are examined for the presence of SCA configuration + * information and if any is found then the web application is treated as an + * SCA Module defintion which is used to create a ModuleComponent. The name of the + * context is used as the name of the ModuleComponent and its context path is used + * as the URI. + * + * @version $Rev$ $Date$ + */ +@SuppressWarnings({"serial"}) +public class TuscanyHost extends StandardHost implements ServletHost { + private static final String SYSTEM_MODULE_COMPONENT = "org.apache.tuscany.core.system"; + + private static final StringManager sm = StringManager.getManager("org.apache.tuscany.tomcat"); + + private RuntimeContext runtime; + private AssemblyModelLoader modelLoader; + private AssemblyFactory modelFactory; + + public synchronized void start() throws LifecycleException { + startRuntime(); + super.start(); + } + + public synchronized void stop() throws LifecycleException { + super.stop(); + stopRuntime(); + } + + private void startRuntime() { + // Create an assembly model context + AssemblyContext modelContext = BootstrapHelper.getModelContext(getClass().getClassLoader()); + modelFactory = modelContext.getAssemblyFactory(); + modelLoader = modelContext.getAssemblyLoader(); + + // Create and start the runtime + NullMonitorFactory monitorFactory = new NullMonitorFactory(); + ContextFactoryBuilderRegistry builderRegistry = BootstrapHelper.bootstrapContextFactoryBuilders(monitorFactory); + runtime = new RuntimeContextImpl(monitorFactory, builderRegistry, new DefaultWireBuilder()); + runtime.start(); + + // Load and start the system configuration + try { + SystemCompositeContext systemContext = runtime.getSystemContext(); + BootstrapHelper.bootstrapStaxLoader(systemContext, modelContext); + ModuleComponentConfigurationLoader loader = BootstrapHelper.getConfigurationLoader(systemContext, modelContext); + ModuleComponent systemModuleComponent = loader.loadSystemModuleComponent(SYSTEM_MODULE_COMPONENT, SYSTEM_MODULE_COMPONENT); + CompositeContext context = BootstrapHelper.registerModule(systemContext, systemModuleComponent); + context.publish(new ModuleStart(this)); + + TomcatHost host = systemContext.resolveInstance(TomcatHost.class); + host.setHost(this); + } catch (ConfigurationLoadException e) { + getLogger().warn(sm.getString("runtime.loadSystemFailed", e.getResourceURI()), e); + return; + } catch (Exception e) { + getLogger().warn(sm.getString("runtime.registerSystemFailed"), e); + runtime.stop(); + runtime = null; + return; + } + + getLogger().info(sm.getString("runtime.started")); + } + + private void stopRuntime() { + if (runtime == null) { + return; + } + runtime.getSystemContext().publish(new ModuleStop(this)); + + runtime.stop(); + runtime = null; + getLogger().info(sm.getString("runtime.stopped")); + } + + public synchronized void addChild(Container child) { + if (!(child instanceof StandardContext)) { + throw new IllegalArgumentException(sm.getString("tuscanyHost.notContext")); + } + StandardContext ctx = (StandardContext) child; + ctx.addLifecycleListener(new TuscanyContextListener(runtime, modelFactory, modelLoader)); + super.addChild(child); + } + + public String toString() { + StringBuilder sb = new StringBuilder(132); + if (getParent() != null) { + sb.append(getParent().toString()).append('.'); + } + sb.append("TuscanyHost[").append(getName()).append(']'); + return (sb.toString()); + } + + public void registerMapping(String mapping, Servlet servlet) { + Context ctx = map(mapping); + if (ctx == null) { + throw new UnsupportedOperationException("Cannot find context for mapping " + mapping); + } + String contextPath = ctx.getPath(); + assert mapping.startsWith(contextPath); + mapping = mapping.substring(contextPath.length()); + Wrapper wrapper = new TuscanyWrapper(servlet); + wrapper.setName(mapping.substring(0,mapping.lastIndexOf('/'))); + ctx.addChild(wrapper); + wrapper.addMapping(mapping); + ctx.getMapper().addWrapper(mapping, wrapper, false); + } + + public void unregisterMapping(String mapping) { + } + + public Servlet getMapping(String mapping) { + Context ctx = map(mapping); + if (ctx == null) { + return null; + } + String contextPath = ctx.getPath(); + assert mapping.startsWith(contextPath); + + MappingData mappingData = new MappingData(); + MessageBytes mb = MessageBytes.newInstance(); + mb.setString(mapping); + try { + ctx.getMapper().map(mb, mappingData); + } catch (Exception e) { + return null; + } + if (!(mappingData.wrapper instanceof TuscanyWrapper)) { + return null; + } + TuscanyWrapper wrapper = (TuscanyWrapper) mappingData.wrapper; + return wrapper.getServlet(); + } +} diff --git a/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyValve.java b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyValve.java new file mode 100644 index 0000000000..352a04bde0 --- /dev/null +++ b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyValve.java @@ -0,0 +1,130 @@ +/** + * + * Copyright 2005 The Apache Software Foundation + * + * Licensed 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.tuscany.tomcat; + +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpSession; + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; +import org.osoa.sca.CurrentModuleContext; +import org.osoa.sca.ModuleContext; +import org.osoa.sca.SCA; + +import org.apache.tuscany.core.context.CompositeContext; +import org.apache.tuscany.core.context.event.HttpSessionBound; +import org.apache.tuscany.core.context.event.RequestStart; +import org.apache.tuscany.core.context.event.RequestEnd; +import org.apache.tuscany.core.webapp.LazyHTTPSessionId; + +/** + * Valve that can be added to a pipeline to automatically set the SCA environment as each request is processed. + * + * @version $Rev$ $Date$ + */ +public class TuscanyValve extends ValveBase { + /** + * Name of the note that contains the request id + */ + private static final String REQUEST_ID = "org.apache.tuscany.tomcat.REQUEST_ID"; + + private static final ContextBinder BINDER = new ContextBinder(); + + private CompositeContext moduleComponentContext; + + private boolean enabled = true; + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setContext(CompositeContext moduleComponentContext) { + this.moduleComponentContext = moduleComponentContext; + } + + public TuscanyValve(CompositeContext moduleComponentContext) { + this.moduleComponentContext = moduleComponentContext; + } + + public void invoke(Request request, Response response) throws IOException, ServletException { + if (!enabled){ + return; + } + Object oldRequestId = request.getNote(REQUEST_ID); + ModuleContext oldContext = CurrentModuleContext.getContext(); + // bind the current module context to the thread for use by CurrentModuleContext + BINDER.setContext((ModuleContext) moduleComponentContext); + try { + if (oldRequestId != null) { + // the request has already been started, just invoke the next valve + next.invoke(request, response); + } else { + // tell the runtime a new request is starting + Object requestId = new Object(); + + HttpSession session = request.getSession(false); + if (session != null) { + // A session is already active + moduleComponentContext .publish(new HttpSessionBound(this,session)); + } else { + // Create a lazy wrapper since a session is not yet active + moduleComponentContext.publish(new HttpSessionBound(this, new LazyHTTPSessionId(request))); + } + + try { + moduleComponentContext.publish(new RequestStart(this, requestId)); + } catch (Exception e) { + throw new ServletException(e.getMessage(), e); + } + request.setNote(REQUEST_ID, requestId); + + try { + // invoke the next valve in the pipeline + next.invoke(request, response); + } finally { + // notify the runtime the request is ending + request.removeNote(REQUEST_ID); + try { + moduleComponentContext.publish(new RequestEnd(this, requestId)); + } catch (Exception e) { + // the application already did its work, log and ignore + // todo log this exception + } + } + } + } finally { + // restore the previous module context onto the thread + BINDER.setContext(oldContext); + } + } + + private static class ContextBinder extends SCA { + public void setContext(ModuleContext context) { + setModuleContext(context); + } + + public void start() { + throw new AssertionError(); + } + + public void stop() { + throw new AssertionError(); + } + } +} diff --git a/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyWrapper.java b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyWrapper.java new file mode 100644 index 0000000000..de53ad4d45 --- /dev/null +++ b/sca-java-1.x/tags/java-M1-20060522/java/sca/tomcat/src/main/java/org/apache/tuscany/tomcat/TuscanyWrapper.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2006 The Apache Software Foundation + * + * Licensed 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.tuscany.tomcat; + +import javax.servlet.Servlet; + +import org.apache.catalina.core.StandardWrapper; + +/** + * @version $Rev$ $Date$ + */ +public class TuscanyWrapper extends StandardWrapper { + private static final long serialVersionUID = 1L; + + private final Servlet servlet; + + public TuscanyWrapper(Servlet servlet) { + super(); + this.servlet = servlet; + } + + public synchronized Servlet loadServlet() { + return servlet; + } + + public Servlet getServlet() { + return servlet; + } +} |