View Javadoc
1   package org.argeo.osgi.boot;
2   
3   import java.io.InputStream;
4   import java.io.OutputStream;
5   import java.nio.file.Files;
6   import java.nio.file.Path;
7   import java.nio.file.Paths;
8   import java.util.Date;
9   import java.util.HashMap;
10  import java.util.Map;
11  import java.util.Properties;
12  import java.util.ServiceLoader;
13  
14  import org.osgi.framework.BundleContext;
15  import org.osgi.framework.ServiceReference;
16  import org.osgi.framework.launch.Framework;
17  import org.osgi.framework.launch.FrameworkFactory;
18  
19  /** Launch an OSGi framework and deploy a CMS Node into it. */
20  public class NodeRunner {
21  	private Long timeout = 30 * 1000l;
22  	private final Path baseDir;
23  	private final Path confDir;
24  	private final Path dataDir;
25  
26  	private String baseUrl = "http://forge.argeo.org/data/java/argeo-2.1/";
27  	private String distributionUrl = null;
28  
29  	private Framework framework = null;
30  
31  	public NodeRunner(String distributionUrl, Path baseDir) {
32  		this.distributionUrl = distributionUrl;
33  		Path mavenBase = Paths.get(System.getProperty("user.home") + "/.m2/repository");
34  		Path osgiBase = Paths.get("/user/share/osgi");
35  		if (Files.exists(mavenBase)) {
36  			Path mavenPath = mavenBase.resolve(distributionUrl);
37  			if (Files.exists(mavenPath))
38  				baseUrl = mavenBase.toUri().toString();
39  		} else if (Files.exists(osgiBase)) {
40  			Path osgiPath = osgiBase.resolve(distributionUrl);
41  			if (Files.exists(osgiPath))
42  				baseUrl = osgiBase.toUri().toString();
43  		}
44  
45  		this.baseDir = baseDir;
46  		this.confDir = this.baseDir.resolve("state");
47  		this.dataDir = this.baseDir.resolve("data");
48  
49  	}
50  
51  	public void start() {
52  		long begin = System.currentTimeMillis();
53  		// log4j
54  		Path log4jFile = confDir.resolve("log4j.properties");
55  		if (!Files.exists(log4jFile))
56  			copyResource("/org/argeo/osgi/boot/log4j.properties", log4jFile);
57  		System.setProperty("log4j.configuration", "file://" + log4jFile.toAbsolutePath());
58  
59  		// Start Equinox
60  		try {
61  			ServiceLoader<FrameworkFactory> ff = ServiceLoader.load(FrameworkFactory.class);
62  			FrameworkFactory frameworkFactory = ff.iterator().next();
63  			Map<String, String> configuration = new HashMap<String, String>();
64  			configuration.put("osgi.configuration.area", confDir.toAbsolutePath().toString());
65  			configuration.put("osgi.instance.area", dataDir.toAbsolutePath().toString());
66  			defaultConfiguration(configuration);
67  
68  			framework = frameworkFactory.newFramework(configuration);
69  			framework.start();
70  			info("## Date : " + new Date());
71  			info("## Data : " + dataDir.toAbsolutePath());
72  		} catch (Exception e) {
73  			throw new IllegalStateException("Cannot start OSGi framework", e);
74  		}
75  		BundleContext bundleContext = framework.getBundleContext();
76  		try {
77  
78  			// Spring configs currently require System properties
79  			// System.getProperties().putAll(configuration);
80  
81  			// expected by JAAS as System.property FIXME
82  			System.setProperty("osgi.instance.area", bundleContext.getProperty("osgi.instance.area"));
83  
84  			// OSGi bootstrap
85  			OsgiBoot osgiBoot = new OsgiBoot(bundleContext);
86  
87  			osgiBoot.installUrls(osgiBoot.getDistributionUrls(distributionUrl, baseUrl));
88  
89  			// Start runtime
90  			Properties startProperties = new Properties();
91  			// TODO make it possible to override it
92  			startProperties.put("argeo.osgi.start.2.node",
93  					"org.eclipse.equinox.http.servlet,org.eclipse.equinox.http.jetty,"
94  							+ "org.eclipse.equinox.metatype,org.eclipse.equinox.cm,org.eclipse.rap.rwt.osgi");
95  			startProperties.put("argeo.osgi.start.3.node", "org.argeo.cms");
96  			startProperties.put("argeo.osgi.start.4.node",
97  					"org.eclipse.gemini.blueprint.extender,org.eclipse.equinox.http.registry");
98  			osgiBoot.startBundles(startProperties);
99  
100 			// Find node repository
101 			ServiceReference<?> sr = null;
102 			while (sr == null) {
103 				sr = bundleContext.getServiceReference("javax.jcr.Repository");
104 				if (System.currentTimeMillis() - begin > timeout)
105 					throw new RuntimeException("Could find node after " + timeout + "ms");
106 				Thread.sleep(100);
107 			}
108 			Object nodeDeployment = bundleContext.getService(sr);
109 			info("Node Deployment " + nodeDeployment);
110 
111 			// Initialization completed
112 			long duration = System.currentTimeMillis() - begin;
113 			info("## CMS Launcher initialized in " + (duration / 1000) + "s " + (duration % 1000) + "ms");
114 		} catch (Exception e) {
115 			shutdown();
116 			throw new RuntimeException("Cannot start CMS", e);
117 		} finally {
118 
119 		}
120 	}
121 
122 	private void defaultConfiguration(Map<String, String> configuration) {
123 		// all permissions to OSGi security manager
124 		Path policyFile = confDir.resolve("node.policy");
125 		if (!Files.exists(policyFile))
126 			copyResource("/org/argeo/osgi/boot/node.policy", policyFile);
127 		configuration.put("java.security.policy", "file://" + policyFile.toAbsolutePath());
128 
129 		configuration.put("org.eclipse.rap.workbenchAutostart", "false");
130 		configuration.put("org.eclipse.equinox.http.jetty.autostart", "false");
131 		configuration.put("org.osgi.framework.bootdelegation",
132 				"com.sun.jndi.ldap,com.sun.jndi.ldap.sasl,com.sun.security.jgss,com.sun.jndi.dns,"
133 						+ "com.sun.nio.file,com.sun.nio.sctp");
134 
135 		// Do clean
136 		// configuration.put("osgi.clean", "true");
137 		// if (args.length == 0) {
138 		// configuration.put("osgi.console", "");
139 		// }
140 	}
141 
142 	public void shutdown() {
143 		try {
144 			framework.stop();
145 			framework.waitForStop(15 * 1000);
146 		} catch (Exception silent) {
147 		}
148 	}
149 
150 	public Path getConfDir() {
151 		return confDir;
152 	}
153 
154 	public Path getDataDir() {
155 		return dataDir;
156 	}
157 
158 	public Framework getFramework() {
159 		return framework;
160 	}
161 
162 	public static void main(String[] args) {
163 		try {
164 			String distributionUrl;
165 			Path executionDir;
166 			if (args.length == 2) {
167 				distributionUrl = args[0];
168 				executionDir = Paths.get(args[1]);
169 			} else if (args.length == 1) {
170 				executionDir = Paths.get(System.getProperty("user.dir"));
171 				distributionUrl = args[0];
172 			} else if (args.length == 0) {
173 				executionDir = Paths.get(System.getProperty("user.dir"));
174 				distributionUrl = "org/argeo/commons/org.argeo.dep.cms.sdk/2.1.70/org.argeo.dep.cms.sdk-2.1.70.jar";
175 			}else{
176 				printUsage();
177 				System.exit(1);
178 				return;
179 			}
180 
181 			NodeRunner nodeRunner = new NodeRunner(distributionUrl, executionDir);
182 			nodeRunner.start();
183 //			if (args.length != 0)
184 //				System.exit(0);
185 		} catch (Exception e) {
186 			e.printStackTrace();
187 			System.exit(1);
188 		}
189 	}
190 
191 	protected static void info(Object msg) {
192 		System.out.println(msg);
193 	}
194 
195 	protected static void err(Object msg) {
196 		System.err.println(msg);
197 	}
198 
199 	protected static void debug(Object msg) {
200 		System.out.println(msg);
201 	}
202 
203 	protected static void copyResource(String resource, Path targetFile) {
204 		InputStream input = null;
205 		OutputStream output = null;
206 		try {
207 			input = NodeRunner.class.getResourceAsStream(resource);
208 			Files.createDirectories(targetFile.getParent());
209 			output = Files.newOutputStream(targetFile);
210 			byte[] buf = new byte[8192];
211 			while (true) {
212 				int length = input.read(buf);
213 				if (length < 0)
214 					break;
215 				output.write(buf, 0, length);
216 			}
217 		} catch (Exception e) {
218 			throw new RuntimeException("Cannot write " + resource + " file to " + targetFile, e);
219 		} finally {
220 			try {
221 				input.close();
222 			} catch (Exception ignore) {
223 			}
224 			try {
225 				output.close();
226 			} catch (Exception ignore) {
227 			}
228 		}
229 
230 	}
231 
232 	static void printUsage(){
233 		err("Usage: <distribution url> <base dir>");
234 	}
235 }