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