View Javadoc

1   package org.eclipse.jetty.rewrite.handler;
2   
3   import java.io.IOException;
4   import java.util.Collections;
5   import java.util.List;
6   import java.util.concurrent.CopyOnWriteArrayList;
7   import java.util.regex.Matcher;
8   import java.util.regex.Pattern;
9   
10  import javax.servlet.ServletException;
11  import javax.servlet.http.HttpServletRequest;
12  import javax.servlet.http.HttpServletResponse;
13  
14  import org.eclipse.jetty.server.Request;
15  import org.eclipse.jetty.server.handler.ContextHandler;
16  import org.eclipse.jetty.server.handler.ContextHandler.Context;
17  import org.eclipse.jetty.server.handler.ScopedHandler;
18  import org.eclipse.jetty.util.component.AggregateLifeCycle;
19  import org.eclipse.jetty.util.log.Log;
20  import org.eclipse.jetty.util.log.Logger;
21  
22  
23  /* ------------------------------------------------------------ */
24  /** A handle that uses regular expressions to select the target.
25   * <p>
26   * This handler applies a list of regex to target name mappings to the URIs of requests. 
27   * If the regex matches the URI, then the mapped target name is used in the nested
28   * call to {@link #doScope(String, Request, HttpServletRequest, HttpServletResponse)}.
29   * <p>
30   * This handler should be installed as the first handler in a Context.   It can be configured
31   * either with direct calls to {@link #addPatternTarget(String, String)} or by setting
32   * the context init parameters "org.eclipse.jetty.rewrite.handler.REGEX_MAPPINGS" to a comma
33   * separated list of strings in the format regex==target.
34   */
35  public class RegexTargetHandler extends ScopedHandler
36  {
37      private final static Logger LOG = Log.getLogger(RegexTargetHandler.class);
38      public final static String REGEX_MAPPINGS="org.eclipse.jetty.rewrite.handler.REGEX_MAPPINGS";
39      static class RegexMapping
40      {
41          RegexMapping(String regex,String target)
42          {
43              _pattern=Pattern.compile(regex);
44              _target=target;
45          }
46          final Pattern _pattern;
47          final String _target;
48          
49          public String toString()
50          {
51              return _pattern+"=="+_target;
52          }
53      }
54      
55      final private List<RegexTargetHandler.RegexMapping> _patterns = new CopyOnWriteArrayList<RegexTargetHandler.RegexMapping>();
56      
57      /* ------------------------------------------------------------ */
58      /** Add a pattern to target mapping.
59       * @param pattern The regular expression pattern to match.  
60       * @param target The target (normally servlet name) to handle the request
61       */
62      public void addPatternTarget(String pattern,String target)
63      {
64          _patterns.add(new RegexMapping(pattern,target));
65      }
66  
67      /* ------------------------------------------------------------ */
68      @Override
69      protected void doStart() throws Exception
70      {
71          super.doStart();
72          
73          Context context = ContextHandler.getCurrentContext();
74          if (context!=null)
75          {
76              String config=context.getInitParameter(REGEX_MAPPINGS);
77              LOG.debug("{}={}",REGEX_MAPPINGS,config);
78              String[] mappings=config.split("\\s*,\\s*");
79              for (String mapping : mappings)
80              {
81                  mapping=mapping.trim();
82                  String[] parts=mapping.split("\\s*==\\s*");
83                  if (parts.length==2)
84                  {
85                      String pattern=parts[0];
86                      String target=parts[1];
87                      addPatternTarget(pattern,target);
88                  }
89                  else
90                      LOG.warn("Bad regex mapping: "+mapping);
91              }
92          }
93      }
94  
95      /* ------------------------------------------------------------ */
96      @Override
97      public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
98      {
99          for (RegexTargetHandler.RegexMapping rm : _patterns)
100         {
101             Matcher m=rm._pattern.matcher(target);
102             if (m.matches())
103             {
104                 String new_target = rm._target;
105                 final String sp;
106                 final String pi;
107                 
108                 if (m.groupCount()==1&&target.endsWith(m.group(1)))
109                 {
110                     pi=m.group(1);
111                     sp=target.substring(0,target.length()-pi.length());
112                 }
113                 else
114                 {
115                     sp=target;
116                     pi=null;
117                 }
118                 baseRequest.setServletPath(sp);
119                 baseRequest.setPathInfo(pi);
120                 baseRequest.setAttribute("org.eclipse.jetty.servlet.REGEX_PATH",target);
121                 super.nextScope(new_target,baseRequest,request,response);
122                 return;
123             }
124         }
125         super.nextScope(target,baseRequest,request,response);
126     }
127 
128     /* ------------------------------------------------------------ */
129     @Override
130     public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
131     {
132         String path=(String)baseRequest.getAttribute("org.eclipse.jetty.servlet.REGEX_PATH");
133         if (path==null)
134             path=target;
135         else
136             baseRequest.setAttribute("org.eclipse.jetty.servlet.REGEX_PATH",null);
137         
138         super.nextHandle(path,baseRequest,request,response);
139     }
140 
141     /* ------------------------------------------------------------ */
142     public void dump(Appendable out, String indent) throws IOException
143     {
144         AggregateLifeCycle.dumpObject(out,this);
145         AggregateLifeCycle.dump(out,indent,_patterns,Collections.singletonList(getHandler()));
146     }
147     
148     
149 }