View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.index.updater.fixtures;
20  
21  import javax.servlet.http.HttpServlet;
22  import javax.servlet.http.HttpServletRequest;
23  import javax.servlet.http.HttpServletResponse;
24  
25  import java.io.File;
26  import java.io.FileInputStream;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.io.OutputStream;
30  import java.net.URISyntaxException;
31  import java.net.URL;
32  
33  import org.eclipse.jetty.security.ConstraintMapping;
34  import org.eclipse.jetty.security.ConstraintSecurityHandler;
35  import org.eclipse.jetty.security.HashLoginService;
36  import org.eclipse.jetty.security.UserStore;
37  import org.eclipse.jetty.security.authentication.BasicAuthenticator;
38  import org.eclipse.jetty.server.Connector;
39  import org.eclipse.jetty.server.Handler;
40  import org.eclipse.jetty.server.Server;
41  import org.eclipse.jetty.server.ServerConnector;
42  import org.eclipse.jetty.server.handler.DefaultHandler;
43  import org.eclipse.jetty.server.handler.HandlerCollection;
44  import org.eclipse.jetty.server.session.SessionHandler;
45  import org.eclipse.jetty.util.security.Constraint;
46  import org.eclipse.jetty.util.security.Password;
47  import org.eclipse.jetty.webapp.WebAppContext;
48  
49  public class ServerTestFixture {
50  
51      private static final String SERVER_ROOT_RESOURCE_PATH = "index-updater/server-root";
52  
53      private static final String SIXTY_TWO_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
54  
55      public static final String LONG_PASSWORD = SIXTY_TWO_CHARS + SIXTY_TWO_CHARS;
56  
57      private final Server server;
58  
59      public ServerTestFixture(final int port) throws Exception {
60          server = new Server();
61  
62          ServerConnector connector = new ServerConnector(server);
63          connector.setPort(port);
64  
65          server.setConnectors(new Connector[] {connector});
66  
67          Constraint constraint = new Constraint();
68          constraint.setName(Constraint.__BASIC_AUTH);
69  
70          constraint.setRoles(new String[] {"allowed"});
71          constraint.setAuthenticate(true);
72  
73          ConstraintMapping cm = new ConstraintMapping();
74          cm.setConstraint(constraint);
75          cm.setPathSpec("/protected/*");
76  
77          UserStore userStore = new UserStore();
78          userStore.addUser("user", new Password("password"), new String[] {"allowed"});
79          userStore.addUser("longuser", new Password(LONG_PASSWORD), new String[] {"allowed"});
80          HashLoginService hls = new HashLoginService("POC Server");
81          hls.setUserStore(userStore);
82  
83          ConstraintSecurityHandler sh = new ConstraintSecurityHandler();
84          sh.setAuthenticator(new BasicAuthenticator());
85          sh.setLoginService(hls);
86          sh.setConstraintMappings(new ConstraintMapping[] {cm});
87  
88          WebAppContext ctx = new WebAppContext();
89          ctx.setContextPath("/");
90  
91          File base = getBase();
92          ctx.setWar(base.getAbsolutePath());
93          ctx.setSecurityHandler(sh);
94  
95          ctx.getServletHandler().addServletWithMapping(TimingServlet.class, "/slow/*");
96          ctx.getServletHandler().addServletWithMapping(InfiniteRedirectionServlet.class, "/redirect-trap/*");
97  
98          SessionHandler sessionHandler = ctx.getSessionHandler();
99          sessionHandler.setUsingCookies(true);
100 
101         HandlerCollection handlers = new HandlerCollection();
102         handlers.setHandlers(new Handler[] {ctx, new DefaultHandler()});
103 
104         server.setHandler(handlers);
105         server.start();
106     }
107 
108     private static File getBase() throws URISyntaxException {
109         URL resource = Thread.currentThread().getContextClassLoader().getResource(SERVER_ROOT_RESOURCE_PATH);
110         if (resource == null) {
111             throw new IllegalStateException("Cannot find classpath resource: " + SERVER_ROOT_RESOURCE_PATH);
112         }
113 
114         return new File(resource.toURI().normalize());
115     }
116 
117     public void stop() throws Exception {
118         server.stop();
119         server.join();
120     }
121 
122     public static final class TimingServlet extends HttpServlet {
123         private static final long serialVersionUID = 1L;
124 
125         @Override
126         protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
127             String basePath = req.getServletPath();
128             String subPath = req.getRequestURI().substring(basePath.length());
129 
130             File base;
131             try {
132                 base = getBase();
133             } catch (URISyntaxException e) {
134                 resp.sendError(
135                         HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
136                         "Cannot find server document root in classpath: " + SERVER_ROOT_RESOURCE_PATH);
137                 return;
138             }
139 
140             File f = new File(base, "slow" + subPath);
141             try (InputStream in = new FileInputStream(f)) {
142                 OutputStream out = resp.getOutputStream();
143 
144                 int read;
145                 byte[] buf = new byte[64];
146                 while ((read = in.read(buf)) > -1) {
147                     System.out.println("Sending " + read + " bytes (after pausing 1 seconds)...");
148                     try {
149                         Thread.sleep(1000);
150                     } catch (InterruptedException e) {
151                         throw new RuntimeException(e);
152                     }
153 
154                     out.write(buf, 0, read);
155                 }
156 
157                 out.flush();
158             }
159         }
160     }
161 
162     public static final class InfiniteRedirectionServlet extends HttpServlet {
163         private static final long serialVersionUID = 1L;
164 
165         static int redirCount = 0;
166 
167         @Override
168         protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
169             String path = req.getServletPath();
170             String subPath = req.getRequestURI().substring(path.length());
171 
172             path += subPath + "-" + (++redirCount);
173             resp.sendRedirect(path);
174         }
175     }
176 }