View Javadoc
1   package org.apache.maven.plugins.javadoc;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.net.InetAddress;
24  import java.net.UnknownHostException;
25  import java.util.Map;
26  
27  import javax.servlet.ServletException;
28  import javax.servlet.ServletRequest;
29  import javax.servlet.ServletResponse;
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  
33  import org.mortbay.jetty.Connector;
34  import org.mortbay.jetty.Server;
35  import org.mortbay.jetty.bio.SocketConnector;
36  import org.mortbay.jetty.security.B64Code;
37  import org.mortbay.jetty.servlet.Context;
38  import org.mortbay.jetty.servlet.ServletHolder;
39  import org.mortbay.proxy.AsyncProxyServlet;
40  
41  /**
42   * A Proxy server.
43   *
44   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
45   * @since 2.6
46   */
47  class ProxyServer
48  {
49      private Server proxyServer;
50  
51      /**
52       * @param proxyServlet the wanted auth proxy servlet
53       */
54      public ProxyServer( AuthAsyncProxyServlet proxyServlet )
55      {
56          this( null, 0, proxyServlet );
57      }
58  
59      /**
60       * @param hostName the server name
61       * @param port the server port
62       * @param proxyServlet the wanted auth proxy servlet
63       */
64      public ProxyServer( String hostName, int port, AuthAsyncProxyServlet proxyServlet )
65      {
66          proxyServer = new Server();
67  
68          proxyServer.addConnector( getDefaultConnector( hostName, port ) );
69  
70          Context context = new Context( proxyServer, "/", 0 );
71  
72          context.addServlet( new ServletHolder( proxyServlet ), "/" );
73      }
74  
75      /**
76       * @return the host name
77       */
78      public String getHostName()
79      {
80          Connector connector = proxyServer.getConnectors()[0];
81          return connector.getHost();
82      }
83  
84      /**
85       * @return the host port
86       */
87      public int getPort()
88      {
89          Connector connector = proxyServer.getConnectors()[0];
90          return ( connector.getLocalPort() <= 0 ? connector.getPort() : connector.getLocalPort() );
91      }
92  
93      /**
94       * @throws Exception if any
95       */
96      public void start()
97          throws Exception
98      {
99          if ( proxyServer != null )
100         {
101             proxyServer.start();
102         }
103     }
104 
105     /**
106      * @throws Exception if any
107      */
108     public void stop()
109         throws Exception
110     {
111         if ( proxyServer != null )
112         {
113             proxyServer.stop();
114         }
115         proxyServer = null;
116     }
117 
118     private Connector getDefaultConnector( String hostName, int port )
119     {
120         Connector connector = new SocketConnector();
121         if ( hostName != null )
122         {
123             connector.setHost( hostName );
124         }
125         else
126         {
127             try
128             {
129                 connector.setHost( InetAddress.getLocalHost().getCanonicalHostName() );
130             }
131             catch ( UnknownHostException e )
132             {
133                 // nop
134             }
135         }
136         if ( port > 0 )
137         {
138             connector.setPort( port );
139         }
140 
141         return connector;
142     }
143 
144     /**
145      * A proxy servlet with authentication support.
146      */
147     static class AuthAsyncProxyServlet
148         extends AsyncProxyServlet
149     {
150         private Map<String, String> authentications;
151 
152         private long sleepTime = 0;
153 
154         /**
155          * Constructor for non authentication servlet.
156          */
157         public AuthAsyncProxyServlet()
158         {
159             super();
160         }
161 
162         /**
163          * Constructor for authentication servlet.
164          *
165          * @param authentications a map of user/password
166          */
167         public AuthAsyncProxyServlet( Map<String, String> authentications )
168         {
169             this();
170 
171             this.authentications = authentications;
172         }
173 
174         /**
175          * Constructor for authentication servlet.
176          *
177          * @param authentications a map of user/password
178          * @param sleepTime a positive time to sleep the service thread (for timeout)
179          */
180         public AuthAsyncProxyServlet( Map<String, String> authentications, long sleepTime )
181         {
182             this();
183 
184             this.authentications = authentications;
185             this.sleepTime = sleepTime;
186         }
187 
188         /** {@inheritDoc} */
189         @Override
190         public void service( ServletRequest req, ServletResponse res )
191             throws ServletException, IOException
192         {
193             final HttpServletRequest request = (HttpServletRequest) req;
194             final HttpServletResponse response = (HttpServletResponse) res;
195 
196             if ( this.authentications != null && !this.authentications.isEmpty() )
197             {
198                 String proxyAuthorization = request.getHeader( "Proxy-Authorization" );
199                 if ( proxyAuthorization != null && proxyAuthorization.startsWith( "Basic " ) )
200                 {
201                     String proxyAuth = proxyAuthorization.substring( 6 );
202                     String authorization = B64Code.decode( proxyAuth );
203                     String[] authTokens = authorization.split( ":" );
204                     String user = authTokens[0];
205                     String password = authTokens[1];
206 
207                     if ( this.authentications.get( user ) == null )
208                     {
209                         throw new IllegalArgumentException( user + " not found in the map!" );
210                     }
211 
212                     if ( sleepTime > 0 )
213                     {
214                         try
215                         {
216                             Thread.sleep( sleepTime );
217                         }
218                         catch ( InterruptedException e )
219                         {
220                             // nop
221                         }
222                     }
223                     String authPass = this.authentications.get(user);
224                     if ( password.equals( authPass ) )
225                     {
226                         // could throw exceptions...
227                         super.service( req, res );
228                         return;
229                     }
230                 }
231 
232                 // Proxy-Authenticate Basic realm="CCProxy Authorization"
233                 response.addHeader( "Proxy-Authenticate", "Basic realm=\"Jetty Proxy Authorization\"" );
234                 response.setStatus( HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED );
235                 return;
236             }
237 
238             super.service( req, res );
239         }
240     }
241 }