public static void main(final String[] args) { try { DeploymentInfo servletBuilder = deployment() .setClassLoader(ServletServer.class.getClassLoader()) .setContextPath(MYAPP) .setDeploymentName("test.war") .addServlets( servlet("MessageServlet", MessageServlet.class) .addInitParam("message", "Hello World") .addMapping("/*"), servlet("MyServlet", MessageServlet.class) .addInitParam("message", "MyServlet") .addMapping("/myservlet")); DeploymentManager manager = defaultContainer().addDeployment(servletBuilder); manager.deploy(); HttpHandler servletHandler = manager.start(); PathHandler path = Handlers.path(Handlers.redirect(MYAPP)).addPrefixPath(MYAPP, servletHandler); Undertow server = Undertow.builder().addListener(8080, "localhost").setHandler(path).build(); server.start(); } catch (ServletException e) { throw new RuntimeException(e); } }
@Override public HttpHandler createHttpHandler(Predicate predicate, final HttpHandler next) { // this is a bit of a hack at the moment. Basically we only want to create a single mod_cluster // instance // not matter how many filter refs use it, also mod_cluster at this point has no way // to specify the next handler. To get around this we invoke the mod_proxy handler // and then if it has not dispatched or handled the request then we know that we can // just pass it on to the next handler final HttpHandler mcmp = managementAccessPredicate != null ? Handlers.predicate(managementAccessPredicate, config.create(modCluster, next), next) : config.create(modCluster, next); final HttpHandler proxyHandler = modCluster.getProxyHandler(); HttpHandler theHandler = new HttpHandler() { @Override public void handleRequest(HttpServerExchange exchange) throws Exception { proxyHandler.handleRequest(exchange); if (!exchange.isDispatched() && !exchange.isComplete()) { exchange.setResponseCode(200); mcmp.handleRequest(exchange); } } }; UndertowLogger.ROOT_LOGGER.debug("HttpHandler for mod_cluster MCMP created."); if (predicate != null) { return new PredicateHandler(predicate, theHandler, next); } else { return theHandler; } }
@BeforeClass public static void setup() throws Exception { final ServletContainer container = ServletContainer.Factory.newInstance(); DeploymentInfo builder = new DeploymentInfo() .setClassLoader(ClientEndpointReconnectTestCase.class.getClassLoader()) .setContextPath("/ws") .setResourceManager(new TestResourceLoader(ClientEndpointReconnectTestCase.class)) .setClassIntrospecter(TestClassIntrospector.INSTANCE) .addServletContextAttribute( WebSocketDeploymentInfo.ATTRIBUTE_NAME, new WebSocketDeploymentInfo() .setBuffers(new ByteBufferSlicePool(100, 1000)) .setWorker(DefaultServer.getWorker()) .addEndpoint(DisconnectServerEndpoint.class) .addEndpoint(AnnotatedClientReconnectEndpoint.class) .addListener( new WebSocketDeploymentInfo.ContainerReadyListener() { @Override public void ready(ServerWebSocketContainer container) { deployment = container; } }) .setReconnectHandler( new WebSocketReconnectHandler() { @Override public long disconnected( CloseReason closeReason, URI connectionUri, Session session, int disconnectCount) { if (disconnectCount < 3) { return 1; } else { return -1; } } @Override public long reconnectFailed( IOException exception, URI connectionUri, Session session, int failedCount) { failed = true; return -1; } })) .setDeploymentName("servletContext.war"); DeploymentManager manager = container.addDeployment(builder); manager.deploy(); DefaultServer.setRootHandler(Handlers.path().addPrefixPath("/ws", manager.start())); }
@BeforeClass public static void setup() { DefaultServer.setRootHandler( new PathHandler() .addPrefixPath( "/target", new HttpHandler() { @Override public void handleRequest(HttpServerExchange exchange) throws Exception { message = exchange.getRequestURI(); } }) .addPrefixPath( "/", predicateContext( predicate( Predicates.regex( "%{REQUEST_URL}", "/(aa.*?)c", RedirectTestCase.class.getClassLoader(), false), Handlers.redirect("/target/matched/${1}"), Handlers.redirect("/target%U"))))); }
@Deprecated public PathHandler mount(ScannerResult scanResult) { PathHandler pathHandler = Handlers.path(); /* try { for (Class<?> handlerClass : scanResult.getHandlers()) { Constructor<?> constructor = handlerClass.getConstructor(); constructor.setAccessible(true); mountMethods(pathHandler, handlerClass); } pathHandler = mountServerEndpoints(pathHandler , scanResult.getServerEndpoints() ); } catch (Exception e) { LOGGER.error(e.getMessage()); }*/ return pathHandler; }
@Override public void run() { Undertow server = Undertow.builder() .addHttpListener(port, host) .setHandler( Handlers.path() // .addPrefixPath("/", new ResourceHandler(new // ClassPathResourceManager(Server.class.getClassLoader(), "templates"))) .addPrefixPath("/", new IndexPageHandler(indexTemplate, this)) .addPrefixPath( "/form", new EagerFormParsingHandler().setNext(new FormHandler(indexTemplate, this))) .addPrefixPath("/api/message", new MessagesRequestHandler(serializer, this)) .addPrefixPath("/api/update", new UpdateHandler(serializer, this))) .build(); server.start(); }
@BeforeClass public static void setup() throws ServletException { final ServletContainer container = ServletContainer.Factory.newInstance(); DeploymentInfo builder = new DeploymentInfo() .setClassLoader(TestMessagesReceivedInOrder.class.getClassLoader()) .setContextPath("/") .setResourceManager(new TestResourceLoader(TestMessagesReceivedInOrder.class)) .setClassIntrospecter(TestClassIntrospector.INSTANCE) .addServletContextAttribute( WebSocketDeploymentInfo.ATTRIBUTE_NAME, new WebSocketDeploymentInfo() .setBuffers(new ByteBufferSlicePool(100, 1000)) .setWorker(DefaultServer.getWorker()) .addEndpoint(EchoSocket.class)) .setDeploymentName("servletContext.war"); DeploymentManager manager = container.addDeployment(builder); manager.deploy(); DefaultServer.setRootHandler(Handlers.path().addPrefixPath("/", manager.start())); }
public void start() { try { // start store. ZWaveProductsStoreModel storeModel = new ZWaveProductsStoreModel(); storeModel.setContentDeliveryDriver( new WebSocketWrapper(new LevelDbContentDeliveryDriver("ZWaveProductsDb"), 23666)); storeModel .connect() .then( new Callback<Throwable>() { @Override public void on(Throwable throwable) { final ZWaveProductsStoreUniverse universe = storeModel.universe(0); ZWaveProductsStoreView baseView = universe.time(0); baseView .select("/") .then( new Callback<KObject[]>() { public void on(KObject[] kObjects) { if (kObjects == null || kObjects.length == 0) { ProductStore store = baseView.createProductStore(); baseView .setRoot(store) .then( new Callback<Throwable>() { public void on(Throwable throwable) { System.err.println("ProductStore Loading"); load(store); storeModel .save() .then( new Callback<Throwable>() { @Override public void on(Throwable throwable) { if (throwable != null) { throwable.printStackTrace(); } } }); } }); } else { System.err.println("ProductStore root found"); } } }); } }); // serves pictures server = Undertow.builder() .addHttpListener(currentPort, currentIp) .setHandler( Handlers.path() .addPrefixPath( "/", Handlers.resource( new ClassPathResourceManager( this.getClass().getClassLoader(), "static")))) .build(); server.start(); } catch (IOException e) { e.printStackTrace(); } }
public class JsonChannelTest { public static final int MOCK_PORT = 16000; public static final String MOCK_SERVER = "localhost"; public static final String ROUTE_BOUNCE = "/bounce"; public static final class BounceAPI extends JsonChannel<ParserTest.Car, ParserTest.Car> { public BounceAPI() { super(ParserTest.Car.class, ParserTest.Car.class); } protected ParserTest.Car handle(final HttpMethod method, final ParserTest.Car input) { return input; } } public static final class BounceDuplicateAPI extends JsonChannel<ParserTest.Car, ParserTest.Car> { public BounceDuplicateAPI() { super(ParserTest.Car.class, ParserTest.Car.class); } protected ParserTest.Car handle(final HttpMethod method, final ParserTest.Car input) { return input; } } public static final String ROUTE_BOUNCE_POST = "/bounce_post"; public static final class BouncePostAPI extends JsonChannel.Post<ParserTest.Car, ParserTest.Car> { public BouncePostAPI() { super(ParserTest.Car.class, ParserTest.Car.class); } protected ParserTest.Car post(final ParserTest.Car input) { return input; } } public static final String ROUTE_BOUNCE_PUT = "/bounce_put"; public static final class BouncePutAPI extends JsonChannel.Put<ParserTest.Car, ParserTest.Car> { public BouncePutAPI() { super(ParserTest.Car.class, ParserTest.Car.class); } protected ParserTest.Car put(final ParserTest.Car input) { return input; } } public static final String ROUTE_BOUNCE_DELETE = "/bounce_delete"; public static final class BounceDeleteAPI extends JsonChannel.Delete<ParserTest.Car, ParserTest.Car> { public BounceDeleteAPI() { super(ParserTest.Car.class, ParserTest.Car.class); } protected ParserTest.Car delete(final ParserTest.Car input) { return input; } } public static final Undertow undertow = Undertow.builder() .addHttpListener(MOCK_PORT, MOCK_SERVER) .setHandler( Handlers.path() .addExactPath(ROUTE_BOUNCE, new BounceAPI()) .addExactPath(ROUTE_BOUNCE, new BounceAPI()) // duplicate - OK! .addExactPath( ROUTE_BOUNCE, new BounceDuplicateAPI()) // duplicate but different handler - will override // previous prefix OK! .addExactPath(ROUTE_BOUNCE_POST, new BouncePostAPI()) .addExactPath(ROUTE_BOUNCE_PUT, new BouncePutAPI()) .addExactPath(ROUTE_BOUNCE_DELETE, new BounceDeleteAPI())) .build(); @Before public final void before() { undertow.start(); } @After public final void stop() { undertow.stop(); } @Test public final void bounce_Get() { given().port(MOCK_PORT).get(ROUTE_BOUNCE).then().body(equalTo("")).statusCode(405); } @Test public final void bounce_Post() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .post(ROUTE_BOUNCE) .then() .body(equalTo(json(ParserTest.MOCK_CAR).toString())) .statusCode(200); } @Test public final void bounce_Put() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .put(ROUTE_BOUNCE) .then() .body(equalTo(json(ParserTest.MOCK_CAR).toString())) .statusCode(200); } @Test public final void bounce_Delete() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .delete(ROUTE_BOUNCE) .then() .body(equalTo(json(ParserTest.MOCK_CAR).toString())) .statusCode(200); } @Test public final void bouncePost_Get() { given().port(MOCK_PORT).get(ROUTE_BOUNCE_POST).then().body(equalTo("")).statusCode(405); } @Test public final void bouncePost_Post() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .post(ROUTE_BOUNCE_POST) .then() .body(equalTo(json(ParserTest.MOCK_CAR).toString())) .statusCode(200); } @Test public final void bouncePost_Put() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .put(ROUTE_BOUNCE_POST) .then() .body(equalTo("")) .statusCode(405); } @Test public final void bouncePost_Delete() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .delete(ROUTE_BOUNCE_POST) .then() .body(equalTo("")) .statusCode(405); } @Test public final void bouncePut_Get() { given().port(MOCK_PORT).get(ROUTE_BOUNCE_PUT).then().body(equalTo("")).statusCode(405); } @Test public final void bouncePut_Post() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .post(ROUTE_BOUNCE_PUT) .then() .body(equalTo("")) .statusCode(405); } @Test public final void bouncePut_Put() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .put(ROUTE_BOUNCE_PUT) .then() .body(equalTo(json(ParserTest.MOCK_CAR).toString())) .statusCode(200); } @Test public final void bouncePut_Delete() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .delete(ROUTE_BOUNCE_PUT) .then() .body(equalTo("")) .statusCode(405); } @Test public final void bounceDelete_Get() { given().port(MOCK_PORT).get(ROUTE_BOUNCE_DELETE).then().body(equalTo("")).statusCode(405); } @Test public final void bounceDelete_Post() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .post(ROUTE_BOUNCE_DELETE) .then() .body(equalTo("")) .statusCode(405); } @Test public final void bounceDelete_Put() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .put(ROUTE_BOUNCE_DELETE) .then() .body(equalTo("")) .statusCode(405); } @Test public final void bounceDelete_Delete() { given() .port(MOCK_PORT) .body(json(ParserTest.MOCK_CAR).toString()) .delete(ROUTE_BOUNCE_DELETE) .then() .body(equalTo(json(ParserTest.MOCK_CAR).toString())) .statusCode(200); } }
public CanonicalPathHandler setNext(final HttpHandler next) { Handlers.handlerNotNull(next); this.next = next; return this; }
private HttpHandler setupSecurityHandlers(HttpHandler initialHandler) { final DeploymentInfo deploymentInfo = super.getDeployment().getDeploymentInfo(); final LoginConfig loginConfig = deploymentInfo.getLoginConfig(); final Map<String, AuthenticationMechanismFactory> factoryMap = new HashMap<>(deploymentInfo.getAuthenticationMechanisms()); if (!factoryMap.containsKey(BASIC_AUTH)) { factoryMap.put(BASIC_AUTH, BasicAuthenticationMechanism.FACTORY); } if (!factoryMap.containsKey(FORM_AUTH)) { factoryMap.put(FORM_AUTH, ServletFormAuthenticationMechanism.FACTORY); } if (!factoryMap.containsKey(DIGEST_AUTH)) { factoryMap.put(DIGEST_AUTH, DigestAuthenticationMechanism.FACTORY); } if (!factoryMap.containsKey(CLIENT_CERT_AUTH)) { factoryMap.put(CLIENT_CERT_AUTH, ClientCertAuthenticationMechanism.FACTORY); } if (!factoryMap.containsKey(ExternalAuthenticationMechanism.NAME)) { factoryMap.put(ExternalAuthenticationMechanism.NAME, ExternalAuthenticationMechanism.FACTORY); } HttpHandler current = initialHandler; current = new SSLInformationAssociationHandler(current); final SecurityPathMatches securityPathMatches = buildSecurityConstraints(); current = new ServletAuthenticationCallHandler(current); if (deploymentInfo.isDisableCachingForSecuredPages()) { current = Handlers.predicate(Predicates.authRequired(), Handlers.disableCache(current), current); } if (!securityPathMatches.isEmpty()) { current = new ServletAuthenticationConstraintHandler(current); } current = new ServletConfidentialityConstraintHandler( deploymentInfo.getConfidentialPortManager(), current); if (!securityPathMatches.isEmpty()) { current = new ServletSecurityConstraintHandler(securityPathMatches, current); } List<AuthenticationMechanism> authenticationMechanisms = new LinkedList<>(); authenticationMechanisms.add( new CachedAuthenticatedSessionMechanism()); // TODO: does this really need to be hard coded? String mechName = null; if (loginConfig != null || deploymentInfo.getJaspiAuthenticationMechanism() != null) { // we don't allow multipart requests, and always use the default encoding FormParserFactory parser = FormParserFactory.builder(false) .addParser( new FormEncodedDataDefinition() .setDefaultEncoding(deploymentInfo.getDefaultEncoding())) .build(); List<AuthMethodConfig> authMethods = Collections.<AuthMethodConfig>emptyList(); if (loginConfig != null) { authMethods = loginConfig.getAuthMethods(); } for (AuthMethodConfig method : authMethods) { AuthenticationMechanismFactory factory = factoryMap.get(method.getName()); if (factory == null) { throw UndertowServletMessages.MESSAGES.unknownAuthenticationMechanism(method.getName()); } if (mechName == null) { mechName = method.getName(); } final Map<String, String> properties = new HashMap<>(); properties.put( AuthenticationMechanismFactory.CONTEXT_PATH, deploymentInfo.getContextPath()); properties.put(AuthenticationMechanismFactory.REALM, loginConfig.getRealmName()); properties.put(AuthenticationMechanismFactory.ERROR_PAGE, loginConfig.getErrorPage()); properties.put(AuthenticationMechanismFactory.LOGIN_PAGE, loginConfig.getLoginPage()); properties.putAll(method.getProperties()); String name = method.getName().toUpperCase(Locale.US); // The mechanism name is passed in from the HttpServletRequest interface as the name // reported needs to be // comparable using '==' name = name.equals(FORM_AUTH) ? FORM_AUTH : name; name = name.equals(BASIC_AUTH) ? BASIC_AUTH : name; name = name.equals(DIGEST_AUTH) ? DIGEST_AUTH : name; name = name.equals(CLIENT_CERT_AUTH) ? CLIENT_CERT_AUTH : name; authenticationMechanisms.add(factory.create(name, parser, properties)); } } ((DeploymentImpl) super.getDeployment()).setAuthenticationMechanisms(authenticationMechanisms); // if the JASPI auth mechanism is set then it takes over if (deploymentInfo.getJaspiAuthenticationMechanism() == null) { current = new AuthenticationMechanismsHandler(current, authenticationMechanisms); } else { current = new AuthenticationMechanismsHandler( current, Collections.<AuthenticationMechanism>singletonList( deploymentInfo.getJaspiAuthenticationMechanism())); } current = new CachedAuthenticatedSessionHandler(current, super.getDeployment().getServletContext()); List<NotificationReceiver> notificationReceivers = deploymentInfo.getNotificationReceivers(); if (!notificationReceivers.isEmpty()) { current = new NotificationReceiverHandler(current, notificationReceivers); } // TODO - A switch to constraint driven could be configurable, however before we can support // that with servlets we would // need additional tracking within sessions if a servlet has specifically requested that // authentication occurs. SecurityContextFactory contextFactory = deploymentInfo.getSecurityContextFactory(); if (contextFactory == null) { contextFactory = SecurityContextFactoryImpl.INSTANCE; } current = new SecurityInitialHandler( AuthenticationMode.PRO_ACTIVE, deploymentInfo.getIdentityManager(), mechName, contextFactory, current); return current; }
@Override public void deploy() { DeploymentInfo deploymentInfo = originalDeployment.clone(); if (deploymentInfo.getServletStackTraces() == ServletStackTraces.ALL) { UndertowServletLogger.REQUEST_LOGGER.servletStackTracesAll( deploymentInfo.getDeploymentName()); } deploymentInfo.validate(); final ConvergedDeploymentImpl deployment = new ConvergedDeploymentImpl(this, deploymentInfo, servletContainer); // set deployment to parent using reflection try { Field deploymentField = DeploymentManagerImpl.class.getDeclaredField("deployment"); deploymentField.setAccessible(true); deploymentField.set(this, deployment); deploymentField.setAccessible(false); } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException(e); } final ServletContextImpl servletContexImpl = new ServletContextImpl(servletContainer, deployment); final ServletContext servletContext = new ConvergedServletContextImpl(servletContexImpl); // deployment.setServletContext(((ConvergedServletContextImpl)servletContext).getDelegatedContext()); this.invokeDeploymentMethod( deployment, "setServletContext", new Class[] {ServletContextImpl.class}, new Object[] {((ConvergedServletContextImpl) servletContext).getDelegatedContext()}); deployment.setConvergedServletContext((ConvergedServletContextImpl) servletContext); handleExtensions(deploymentInfo, servletContext); deployment.setDefaultCharset(Charset.forName(deploymentInfo.getDefaultEncoding())); handleDeploymentSessionConfig( deploymentInfo, ((ConvergedServletContextImpl) servletContext).getDelegatedContext()); // deployment.setSessionManager(deploymentInfo.getSessionManagerFactory().createSessionManager(deployment)); this.invokeDeploymentMethod( deployment, "setSessionManager", new Class[] {SessionManager.class}, new Object[] {deploymentInfo.getSessionManagerFactory().createSessionManager(deployment)}); deployment .getSessionManager() .setDefaultSessionTimeout(deploymentInfo.getDefaultSessionTimeout()); for (SessionListener listener : deploymentInfo.getSessionListeners()) { deployment.getSessionManager().registerSessionListener(listener); } final List<ThreadSetupAction> setup = new ArrayList<>(); setup.add(ServletRequestContextThreadSetupAction.INSTANCE); setup.add(new ContextClassLoaderSetupAction(deploymentInfo.getClassLoader())); setup.addAll(deploymentInfo.getThreadSetupActions()); final CompositeThreadSetupAction threadSetupAction = new CompositeThreadSetupAction(setup); deployment.setThreadSetupAction(threadSetupAction); ThreadSetupAction.Handle handle = threadSetupAction.setup(null); try { final ApplicationListeners listeners = createListeners(); listeners.start(); // deployment.setApplicationListeners(listeners); this.invokeDeploymentMethod( deployment, "setApplicationListeners", new Class[] {ApplicationListeners.class}, new Object[] {listeners}); // now create the servlets and filters that we know about. We can still get more later createServletsAndFilters(deployment, deploymentInfo); // first run the SCI's for (final ServletContainerInitializerInfo sci : deploymentInfo.getServletContainerInitializers()) { final InstanceHandle<? extends ServletContainerInitializer> instance = sci.getInstanceFactory().createInstance(); try { instance.getInstance().onStartup(sci.getHandlesTypes(), servletContext); } finally { instance.release(); } } deployment .getSessionManager() .registerSessionListener( new ConvergedSessionListenerBridge( threadSetupAction, listeners, servletContext, deployment.getSessionManager())); initializeErrorPages(deployment, deploymentInfo); initializeMimeMappings(deployment, deploymentInfo); initializeTempDir(servletContext, deploymentInfo); listeners.contextInitialized(); // run HttpHandler wrappedHandlers = ServletDispatchingHandler.INSTANCE; wrappedHandlers = wrapHandlers(wrappedHandlers, deploymentInfo.getInnerHandlerChainWrappers()); HttpHandler securityHandler = setupSecurityHandlers(wrappedHandlers); wrappedHandlers = new PredicateHandler(DispatcherTypePredicate.REQUEST, securityHandler, wrappedHandlers); HttpHandler outerHandlers = wrapHandlers(wrappedHandlers, deploymentInfo.getOuterHandlerChainWrappers()); wrappedHandlers = new PredicateHandler(DispatcherTypePredicate.REQUEST, outerHandlers, wrappedHandlers); wrappedHandlers = handleDevelopmentModePersistentSessions( wrappedHandlers, deploymentInfo, deployment.getSessionManager(), servletContext); MetricsCollector metrics = deploymentInfo.getMetricsCollector(); if (metrics != null) { wrappedHandlers = new MetricsChainHandler(wrappedHandlers, metrics, deployment); } final ServletInitialHandler servletInitialHandler = SecurityActions.createServletInitialHandler( deployment.getServletPaths(), wrappedHandlers, deployment.getThreadSetupAction(), servletContext); HttpHandler initialHandler = wrapHandlers( servletInitialHandler, deployment.getDeploymentInfo().getInitialHandlerChainWrappers()); initialHandler = new HttpContinueReadHandler(initialHandler); if (deploymentInfo.getUrlEncoding() != null) { initialHandler = Handlers.urlDecodingHandler(deploymentInfo.getUrlEncoding(), initialHandler); } deployment.setInitialHandler(initialHandler); // deployment.setServletHandler(servletInitialHandler); this.invokeDeploymentMethod( deployment, "setServletHandler", new Class[] {ServletInitialHandler.class}, new Object[] {servletInitialHandler}); deployment.getServletPaths().invalidate(); // make sure we have a fresh set of servlet paths ((ConvergedServletContextImpl) servletContext).initDone(); } catch (Exception e) { throw new RuntimeException(e); } finally { handle.tearDown(); } // set state using reflection: try { Field stateField = DeploymentManagerImpl.class.getDeclaredField("state"); stateField.setAccessible(true); stateField.set(this, State.DEPLOYED); stateField.setAccessible(false); } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException(e); } }