View Javadoc

1   // ========================================================================
2   // Copyright (c) 2010 Intalio, Inc.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // Contributors:
13  //    Hugues Malphettes - initial API and implementation
14  // ========================================================================
15  package org.eclipse.jetty.osgi.boot.internal.serverfactory;
16  
17  import java.io.File;
18  import java.net.MalformedURLException;
19  import java.net.URL;
20  import java.util.Dictionary;
21  import java.util.Hashtable;
22  import java.util.Enumeration;
23  import java.util.Properties;
24  import java.util.StringTokenizer;
25  
26  import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
27  import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
28  import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
29  import org.eclipse.jetty.server.Server;
30  import org.eclipse.jetty.util.log.Log;
31  import org.osgi.framework.Bundle;
32  import org.osgi.framework.BundleContext;
33  
34  /**
35   * Called by the {@link JettyBootstrapActivator} during the starting of the bundle.
36   * If the system property 'jetty.home' is defined and points to a folder,
37   * then setup the corresponding jetty server and starts it.
38   */
39  public class DefaultJettyAtJettyHomeHelper {
40  	
41      /**
42       * contains a comma separated list of pathes to the etc/jetty-*.xml files
43       * used to configure jetty. By default the value is 'etc/jetty.xml' when the
44       * path is relative the file is resolved relatively to jettyhome.
45       */
46      public static final String SYS_PROP_JETTY_ETC_FILES = OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS;
47  
48      /**
49       * Usual system property used as the hostname for a typical jetty configuration.
50       */
51      public static final String SYS_PROP_JETTY_HOME = "jetty.home";
52      /**
53       * System property to point to a bundle that embeds a jetty configuration
54       * and that jetty configuration should be the default jetty server.
55       * First we look for jetty.home. If we don't find it then we look for this property.
56       */
57      public static final String SYS_PROP_JETTY_HOME_BUNDLE = "jetty.home.bundle";
58      /**
59       * Usual system property used as the hostname for a typical jetty configuration.
60       */
61      public static final String SYS_PROP_JETTY_HOST = "jetty.host";
62      /**
63       * Usual system property used as the port for http for a typical jetty configuration.
64       */
65      public static final String SYS_PROP_JETTY_PORT = "jetty.port";
66      /**
67       * Usual system property used as the port for https for a typical jetty configuration.
68       */
69      public static final String SYS_PROP_JETTY_PORT_SSL = "jetty.port.ssl";
70  	
71      /**
72       * Called by the JettyBootStrapActivator.
73       * If the system property jetty.home is defined and points to a folder,
74       * deploys the corresponding jetty server.
75       * <p>
76       * If the system property jetty.home.bundle is defined and points to a bundle.
77       * Look for the configuration of jetty inside that bundle and deploys the corresponding bundle.
78       * </p>
79       * <p>
80       * In both cases reads the system property 'jetty.etc.config.urls' to locate the configuration
81       * files for the deployed jetty. It is a comma spearate list of URLs or relative paths inside the bundle or folder
82       * to the config files. If underfined it defaults to 'etc/jetty.xml'.
83       * </p>
84       * <p>
85       * In both cases the system properties jetty.host, jetty.port and jetty.port.ssl are passed to the configuration files
86       * that might use them as part of their properties.
87       * </p>
88       */
89      public static void startJettyAtJettyHome(BundleContext bundleContext)
90      {
91      	String jettyHomeSysProp = System.getProperty(SYS_PROP_JETTY_HOME);
92      	String jettyHomeBundleSysProp = System.getProperty(SYS_PROP_JETTY_HOME_BUNDLE);
93      	File jettyHome = null;
94      	Bundle jettyHomeBundle = null;
95      	if (jettyHomeSysProp != null)
96      	{
97      		//bug 329621
98      		if (jettyHomeSysProp.startsWith("\"") && jettyHomeSysProp.endsWith("\"")) {
99      			jettyHomeSysProp = jettyHomeSysProp.substring(1, jettyHomeSysProp.length() - 1);
100     		}
101     		if (jettyHomeBundleSysProp != null)
102     		{
103     			Log.warn("Both the jetty.home property and the jetty.home.bundle property are defined."
104     					+ " jetty.home.bundle is not taken into account.");
105     		}
106     		jettyHome = new File(jettyHomeSysProp);
107     		if (!jettyHome.exists() || !jettyHome.isDirectory())
108     		{
109     			Log.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
110     			return;
111     		}
112     	}
113     	else if (jettyHomeBundleSysProp != null)
114     	{
115     		for (Bundle b : bundleContext.getBundles())
116     		{
117     			if (b.getSymbolicName().equals(jettyHomeBundleSysProp))
118     			{
119     				jettyHomeBundle = b;
120     				break;
121     			}
122     		}
123     		if (jettyHomeBundle == null)
124     		{
125     			Log.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
126     			return;
127     		}
128     		
129     	}
130     	if (jettyHome == null && jettyHomeBundle == null)
131     	{
132     		Log.warn("No default jetty started.");
133     		return;
134     	}
135 		try
136 		{
137 			Server server = new Server();
138 			Dictionary properties = new Hashtable();
139 			properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME);
140 			
141 			String configURLs = jettyHome != null ? getJettyConfigurationURLs(jettyHome) : getJettyConfigurationURLs(jettyHomeBundle);
142 			properties.put(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS, configURLs);
143 
144 			Log.info("Configuring the default jetty server with " + configURLs);
145 			
146 			//these properties usually are the ones passed to this type of configuration.
147 			setProperty(properties,SYS_PROP_JETTY_HOME,System.getProperty(SYS_PROP_JETTY_HOME));
148 			setProperty(properties,SYS_PROP_JETTY_HOST,System.getProperty(SYS_PROP_JETTY_HOST));
149 			setProperty(properties,SYS_PROP_JETTY_PORT,System.getProperty(SYS_PROP_JETTY_PORT));
150 			setProperty(properties,SYS_PROP_JETTY_PORT_SSL,System.getProperty(SYS_PROP_JETTY_PORT_SSL));
151 
152    			bundleContext.registerService(Server.class.getName(), server, properties);
153 		}
154 		catch (Throwable t)
155 		{
156 			t.printStackTrace();
157 		}
158     }
159     
160     /**
161      * Minimum setup for the location of the configuration files given a jettyhome folder.
162      * Reads the system property jetty.etc.config.urls and look for the corresponding jetty
163      * configuration files that will be used to setup the jetty server.
164      * @param jettyhome
165      * @return
166      */
167     private static String getJettyConfigurationURLs(File jettyhome)
168     {
169     	String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
170         StringTokenizer tokenizer = new StringTokenizer(jettyetc,";,", false);
171         StringBuilder res = new StringBuilder();
172         while (tokenizer.hasMoreTokens())
173         {
174         	String next = tokenizer.nextToken().trim();
175         	if (!next.startsWith("/") && next.indexOf(':') == -1)
176         	{
177         		try {
178         			next = new File(jettyhome, next).toURI().toURL().toString();
179 				} catch (MalformedURLException e) {
180 					e.printStackTrace();
181 					continue;
182 				}
183         	}
184         	appendToCommaSeparatedList(res, next);
185         }
186         return res.toString();
187     }
188 
189     /**
190      * Minimum setup for the location of the configuration files given a configuration
191      * embedded inside a bundle.
192      * Reads the system property jetty.etc.config.urls and look for the corresponding jetty
193      * configuration files that will be used to setup the jetty server.
194      * @param jettyhome
195      * @return
196      */
197     private static String getJettyConfigurationURLs(Bundle configurationBundle)
198     {
199     	String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
200     	System.err.println("jettyetc=" + jettyetc);
201         StringTokenizer tokenizer = new StringTokenizer(jettyetc,";,", false);
202         StringBuilder res = new StringBuilder();
203         
204         while (tokenizer.hasMoreTokens())
205         {
206             String etcFile = tokenizer.nextToken().trim();
207             if (etcFile.startsWith("/") || etcFile.indexOf(":") != -1)
208             {
209             	appendToCommaSeparatedList(res, etcFile);
210             }
211             else
212             {
213             	Enumeration<URL> enUrls = BundleFileLocatorHelper.DEFAULT
214             				.findEntries(configurationBundle, etcFile);
215         		
216         		//default for org.eclipse.osgi.boot where we look inside jettyhome for the default embedded configuration.
217         		//default inside jettyhome. this way fragments to the bundle can define their own configuration.
218             	if ((enUrls == null || !enUrls.hasMoreElements()) && etcFile.endsWith("etc/jetty.xml"))
219             	{
220             		enUrls = BundleFileLocatorHelper.DEFAULT
221             				.findEntries(configurationBundle, "/jettyhome/etc/jetty-osgi-default.xml");
222             		System.err.println("Configuring jetty with the default embedded configuration:" +
223             				"bundle: " + configurationBundle.getSymbolicName() + 
224             				" config: /jettyhome/etc/jetty-osgi-default.xml");
225             	}
226             	if (enUrls == null || !enUrls.hasMoreElements())
227             	{
228             		System.err.println("Unable to locate a jetty configuration file for " + etcFile);
229             	}
230         		if (enUrls != null)
231         		{
232         			while (enUrls.hasMoreElements())
233         			{
234         				appendToCommaSeparatedList(res, enUrls.nextElement().toString());
235         			}
236         		}
237             }
238         }
239         return res.toString();
240     }
241 	
242 	private static void appendToCommaSeparatedList(StringBuilder buffer, String value)
243 	{
244 		if (buffer.length() != 0)
245 		{
246 			buffer.append(",");
247 		}
248 		buffer.append(value);
249 	}
250 	
251 	private static void setProperty(Dictionary properties, String key, String value)
252 	{
253 		if (value != null)
254 		{
255 			properties.put(key, value);
256 		}
257 	}
258 	
259 }