View Javadoc
1   package org.apache.commons.jcs.auxiliary.remote.server;
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.io.OutputStream;
24  import java.net.UnknownHostException;
25  import java.util.Properties;
26  
27  import javax.servlet.ServletConfig;
28  import javax.servlet.ServletException;
29  import javax.servlet.http.HttpServlet;
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  
33  import org.apache.commons.jcs.access.exception.CacheException;
34  import org.apache.commons.jcs.auxiliary.remote.RemoteUtils;
35  import org.apache.commons.jcs.engine.control.CompositeCacheManager;
36  import org.apache.commons.jcs.utils.net.HostNameUtil;
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  
40  /**
41   * This servlet can be used to startup the JCS remote cache. It is easy to
42   * deploy the remote server in a tomcat base. This give you an easy way to
43   * monitor its activity.
44   * <p>
45   * <code>
46   *  servlet&gt;
47          &lt;servlet-name&gt;JCSRemoteCacheStartupServlet&lt;/servlet-name&gt;
48          &lt;servlet-class&gt;
49               org.apache.commons.jcs.auxiliary.remote.server.RemoteCacheStartupServlet
50          &lt;/servlet-class&gt;
51          &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
52      &lt;/servlet&gt;
53  
54  
55      &lt;servlet-mapping&gt;
56          &lt;servlet-name&gt;JCSRemoteCacheStartupServlet&lt;/servlet-name&gt;
57          &lt;url-pattern&gt;/jcs&lt;/url-pattern&gt;
58      &lt;/servlet-mapping&gt;
59   * </code>
60   *
61   * @author Aaron Smuts
62   */
63  public class RemoteCacheStartupServlet
64          extends HttpServlet
65  {
66      /** Don't change */
67      private static final long serialVersionUID = 1L;
68  
69      /** The logger */
70      private static final Log log = LogFactory.getLog(RemoteCacheStartupServlet.class);
71  
72      /** The default port to start the registry on. */
73      private static final int DEFAULT_REGISTRY_PORT = 1101;
74  
75      /** properties file name */
76      private static final String DEFAULT_PROPS_FILE_NAME = "/cache.ccf";
77  
78      /** properties file name, must set prior to calling get instance */
79      private String propsFileName = DEFAULT_PROPS_FILE_NAME;
80  
81      /** Configuration properties */
82      private int registryPort = DEFAULT_REGISTRY_PORT;
83  
84      /** Configuration properties */
85      private String registryHost = null;
86  
87      /**
88       * Starts the registry and then tries to bind to it.
89       * <p>
90       * Gets the port from a props file. Uses the local host name for the
91       * registry host. Tries to start the registry, ignoring failure. Starts the
92       * server.
93       * <p>
94       *
95       * @throws ServletException
96       */
97      @Override
98      public void init()
99              throws ServletException
100     {
101         super.init();
102 
103         loadInitParams();
104         Properties props = loadPropertiesFromFile();
105 
106         if (registryHost == null)
107         {
108             // we will always use the local machine for the registry
109             try
110             {
111                 registryHost = HostNameUtil.getLocalHostAddress();
112             }
113             catch (UnknownHostException e)
114             {
115                 log.error("Could not get local address to use for the registry!", e);
116             }
117         }
118 
119         if (log.isDebugEnabled())
120         {
121             log.debug("registryHost = [" + registryHost + "]");
122         }
123 
124         if ("localhost".equals(registryHost) || "127.0.0.1".equals(registryHost))
125         {
126             log.warn("The local address [" + registryHost
127                     + "] is INVALID.  Other machines must be able to use the address to reach this server.");
128         }
129 
130         try
131         {
132             if (props == null)
133             {
134                 throw new ServletException("Could not load configuration from " + propsFileName);
135             }
136 
137             RemoteCacheServerFactory.startup(registryHost, registryPort, props);
138             if (log.isInfoEnabled())
139             {
140                 log.info("Remote JCS Server started with properties from " + propsFileName);
141             }
142         }
143         catch (IOException e)
144         {
145             throw new ServletException("Problem starting remote cache server.", e);
146         }
147     }
148 
149     /**
150      * It just dumps the stats.
151      * <p>
152      *
153      * @param request
154      * @param response
155      * @throws ServletException
156      * @throws IOException
157      */
158     @Override
159     protected void service(HttpServletRequest request, HttpServletResponse response)
160             throws ServletException, IOException
161     {
162         String stats = "";
163 
164         try
165         {
166             stats = CompositeCacheManager.getInstance().getStats();
167         }
168         catch (CacheException e)
169         {
170             throw new ServletException(e);
171         }
172 
173         if (log.isInfoEnabled())
174         {
175             log.info(stats);
176         }
177 
178         try
179         {
180             String characterEncoding = response.getCharacterEncoding();
181             if (characterEncoding == null)
182             {
183                 characterEncoding = "UTF-8";
184                 response.setCharacterEncoding(characterEncoding);
185             }
186             OutputStream os = response.getOutputStream();
187             os.write(stats.getBytes(characterEncoding));
188             os.close();
189         }
190         catch (IOException e)
191         {
192             log.error("Problem writing response.", e);
193         }
194     }
195 
196     /**
197      * shuts the cache down.
198      */
199     @Override
200     public void destroy()
201     {
202         super.destroy();
203 
204         log.info("Shutting down remote cache ");
205 
206         try
207         {
208             RemoteCacheServerFactory.shutdownImpl(registryHost, registryPort);
209         }
210         catch (IOException e)
211         {
212             log.error("Problem shutting down.", e);
213         }
214 
215         try
216         {
217             CompositeCacheManager.getInstance().shutDown();
218         }
219         catch (CacheException e)
220         {
221             log.error("Could not retrieve cache manager instance", e);
222         }
223     }
224 
225     /**
226      * Load configuration values from config file if possible
227      */
228     private Properties loadPropertiesFromFile()
229     {
230         Properties props = null;
231 
232         try
233         {
234             props = RemoteUtils.loadProps(propsFileName);
235             if (props != null)
236             {
237                 registryHost = props.getProperty("registry.host", registryHost);
238                 String portS = props.getProperty("registry.port", String.valueOf(registryPort));
239                 setRegistryPort(portS);
240             }
241         }
242         catch (IOException e)
243         {
244             log.error("Problem loading props.", e);
245         }
246 
247         return props;
248     }
249 
250     /**
251      * Load configuration values from init params if possible
252      */
253     private void loadInitParams()
254     {
255         ServletConfig config = getServletConfig();
256         String _propsFileName = config.getInitParameter("propsFileName");
257         if (null != _propsFileName)
258         {
259             this.propsFileName = _propsFileName;
260         }
261         String _registryHost = config.getInitParameter("registryHost");
262         if (null != _registryHost)
263         {
264             this.registryHost = _registryHost;
265         }
266         String regPortString = config.getInitParameter("registryPort");
267         if (null != regPortString)
268         {
269             setRegistryPort(regPortString);
270         }
271     }
272 
273     /**
274      * Set registry port from string If the string cannot be parsed, the default
275      * value is used
276      *
277      * @param portS
278      */
279     private void setRegistryPort(String portS)
280     {
281         try
282         {
283             this.registryPort = Integer.parseInt(portS);
284         }
285         catch (NumberFormatException e)
286         {
287             log.error("Problem converting port to an int.", e);
288             this.registryPort = DEFAULT_REGISTRY_PORT;
289         }
290     }
291 }