/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.foo.paint;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.swing.*;
import org.foo.shape.SimpleShape;
import org.foo.shape.trapezoid.Trapezoid;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.launch.FrameworkFactory;
/**
* This class is the launcher for the paint program. It creates an embedded
* framework instance and deploys shape bundles into it, then creates a
* paint frame and connects it to the framework instance using a ShapeTracker
* and the BundleContext of the system bundle.
*/
public class Main {
private static Framework fwk;
private static PaintFrame frame = null;
private static ShapeTracker shapeTracker = null;
/**
* The static main method launches the paint program.
* @param args All command line arguments are ignored.
* @throws Exception if any errors occur.
*/
public static void main(String[] args) throws Exception {
addShutdownHook();
fwk = createFramework();
publishTrapezoidService();
createPaintFrame();
}
/**
* Adds a shutdown hook to the JVM process to cleanly shutdown
* the embedded framework instance.
*/
private static void addShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
if (fwk != null) {
fwk.stop();
fwk.waitForStop(0);
}
} catch (Exception ex) {
System.err.println("Error stopping framework: " + ex);
}
}
});
}
/**
* Creates a framework instance using the standard META-INF/services approach.
* The created instance is configured to start with a clean cache and for the
* system bundle to export the shape API. All bundles located in the "bundles"
* directory are installed and started.
* @return the created framework instance.
* @throws Exception if any error occurs.
*/
private static Framework createFramework() throws Exception {
// Look in the "bundles" directory to create a list
// of all JAR files to install.
File[] files = new File("bundles").listFiles();
Arrays.sort(files);
List jars = new ArrayList();
for (int i = 0; i < files.length; i++)
if (files[i].getName().toLowerCase().endsWith(".jar"))
jars.add(files[i]);
try {
// Create, configure, and start an OSGi framework instance
// using the ServiceLoader to get a factory.
List bundleList = new ArrayList();
Map m = new HashMap();
m.putAll(System.getProperties());
m.put(Constants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
m.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "org.foo.shape; version=\"4.0.0\"");
fwk = getFrameworkFactory().newFramework(m);
fwk.start();
// Install bundle JAR files and remember the bundle objects.
BundleContext ctxt = fwk.getBundleContext();
for (int i = 0; i < jars.size(); i++) {
Bundle b = ctxt.installBundle(((File) jars.get(i)).toURI().toString());
bundleList.add(b);
}
// Start all installed bundles.
for (int i = 0; i < bundleList.size(); i++) {
((Bundle) bundleList.get(i)).start();
}
} catch (Exception ex) {
System.err.println("Error starting framework: " + ex);
ex.printStackTrace();
System.exit(0);
}
return fwk;
}
/**
* Publishes a trapezoid shape service implementation from the host
* application into the embedded framework instance using the system
* bundle context.
*/
private static void publishTrapezoidService() {
Hashtable dict = new Hashtable();
dict.put(SimpleShape.NAME_PROPERTY, "Trapezoid");
dict.put(SimpleShape.ICON_PROPERTY, new ImageIcon(Trapezoid.class.getResource("trapezoid.png")));
fwk.getBundleContext().registerService(SimpleShape.class.getName(), new Trapezoid(), dict);
}
/**
* Creates and displays the paint program's paint frame. The embedded
* framework instance and the paint frame are wired together using a
* ShapeTracker instance and the system bundle's BundleContext.
* @throws Exception if any errors occur.
*/
private static void createPaintFrame() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame = new PaintFrame();
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
try {
fwk.stop();
fwk.waitForStop(0);
} catch (Exception ex) {
System.err.println("Issue stopping framework: " + ex);
}
System.exit(0);
}
});
frame.setVisible(true);
shapeTracker = new ShapeTracker(fwk.getBundleContext(), frame);
shapeTracker.open();
}
});
}
/**
* Simple method to parse META-INF/services file for framework factory.
* Currently, it assumes the first non-commented line is the class name
* of the framework factory implementation.
* @return The created <tt>FrameworkFactory</tt> instance.
* @throws Exception if any errors occur.
**/
private static FrameworkFactory getFrameworkFactory() throws Exception {
URL url = Main.class.getClassLoader().getResource(
"META-INF/services/org.osgi.framework.launch.FrameworkFactory");
if (url != null) {
BufferedReader br =
new BufferedReader(new InputStreamReader(url.openStream()));
try {
for (String s = br.readLine(); s != null; s = br.readLine()) {
s = s.trim();
// Try to load first non-empty, non-commented line.
if ((s.length() > 0) && (s.charAt(0) != '#')) {
return (FrameworkFactory) Class.forName(s).newInstance();
}
}
} finally {
if (br != null) br.close();
}
}
throw new Exception("Could not find framework factory.");
}
}