Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: a8e3c51aeadfd70232e677378e84ad1ac88701c0 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                                                                
                                                       







                                                                                 
                                     

                           
                                 
                    







                                 











                                                                                                                                              

        

                                                                                                                       
        





                                  













                                                                                                                                                                                
                                    
                                                
                                  

                                                                                 



                                                    



                                                                   
                                              

                                      
         
        



                                                   
                                  
                                  


          
                                                                                  


                                                                       
                                                                       

                                    


                                                                      
                 
                                         
                                    
 





                                                                
                                                                    

         
                                                                                                 





























                                                                                                 
           
                                                                  
           

                                           


                                                                                                                        








                                                                                               



                                            

         













                                                                                                                
                 
                                            

         
          
                                                                                  






                                                                                                       
                                                      


                               
                                               






                                                                                      

                                                            
                                                                                                    


                                                                                                                                                               
                         
                                              


                 
                                                           

                                                                                       
 

                            
                                                                    
                                                                                                         
                                                       
                                            
 






                                                                                         
                         




                                                        
                 
                            

         
                                                                                                   
                                            





                                                                                                                               
                 
 





                                                                                                                                           


                                 
                                                                                          
         
 
/*******************************************************************************
 * Copyright (c) 2005, 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.launcher;

import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

/**
 * The launcher ot start eclipse using webstart.
 * To use this launcher, the client must accept to give all security permissions. 
 */
//The bundles are discovered by finding all the jars on the classpath. Then they are added with their full path to the osgi.bundles list.
public class WebStartMain extends Main {
	private static final String PROP_WEBSTART_AUTOMATIC_INSTALLATION = "eclipse.webstart.automaticInstallation"; //$NON-NLS-1$
	private static final String DEFAULT_OSGI_BUNDLES = "org.eclipse.equinox.common@2:start, org.eclipse.core.runtime@start"; //$NON-NLS-1$
	private static final String PROP_OSGI_BUNDLES = "osgi.bundles"; //$NON-NLS-1$
	

	private Map allBundles = null; 	// Map of all the bundles found on the classpath. Id -> ArrayList of BundleInfo
	private List bundleList = null; //The list of bundles found on the osgi.bundle list 
	
	private class BundleInfo {
		String bsn;
		String version;
		String startData;
		String location;
	}
	
	public static void main(String[] args) {
		System.setSecurityManager(null); //TODO Hack so that when the classloader loading the fwk is created we don't have funny permissions. This should be revisited. 
		int result = new WebStartMain().run(args);
		System.exit(result);
	}

	private void setDefaultBundles() {
		if (System.getProperty(PROP_OSGI_BUNDLES) != null)
			return;
		System.getProperties().put(PROP_OSGI_BUNDLES, DEFAULT_OSGI_BUNDLES);
	}

	protected void basicRun(String[] args) throws Exception {
		setDefaultBundles();
		initializeBundleListStructure();
		discoverBundles();
		//Set the fwk location since the regular lookup would not find it
		String fwkURL = searchFor(framework, null);
		if (fwkURL == null) {
			//MESSAGE CAN"T FIND THE FWK
		}
		allBundles.remove(framework);
		System.getProperties().put(PROP_FRAMEWORK, fwkURL);
		super.basicRun(args);
	}

	protected void beforeFwkInvocation() {
		buildOSGiBundleList();
		cleanup();
	}
	
	/*
	 * Null out all the fields containing data 
	 */
	private void cleanup() {
		allBundles = null;
		bundleList = null;
	}

	/*
	 * Find the target bundle among all the bundles that are on the classpath.
	 * The start parameter is not used in this context
	 */
	protected String searchFor(final String target, String start) {
		ArrayList matches = (ArrayList) allBundles.get(target);
		if (matches == null)
			return null;
		int numberOfMatches = matches.size();
		if (numberOfMatches == 1) {
			return ((BundleInfo) matches.get(0)).location;
		}
		if (numberOfMatches == 0)
			return null;

		String[] versions = new String[numberOfMatches];
		int highest = 0;
		for (int i = 0; i < versions.length; i++) {
			versions[i] = (String) matches.get(i);
			highest = findMax(versions);
		}
		return ((BundleInfo) matches.get(highest)).location;
	}

	private BundleInfo findBundle(final String target, String version, boolean removeMatch) {
		ArrayList matches = (ArrayList) allBundles.get(target);
		int numberOfMatches = matches.size();
		if (numberOfMatches == 1) {
			//TODO Need to check the version
			return (BundleInfo) matches.remove(0);
		}
		if (numberOfMatches == 0)
			return null;

		if (version != null) {
			for (Iterator iterator = matches.iterator(); iterator.hasNext();) {
				BundleInfo bi = (BundleInfo) iterator.next();
				if (bi.version.equals(version)) {
					iterator.remove();
					return bi;
				}
			}
			//TODO Need to log the fact that we could not find the version mentionned
			return null;
		} else {
			String[] versions = new String[numberOfMatches];
			int highest = 0;
			for (int i = 0; i < versions.length; i++) {
				versions[i] = (String) matches.get(i);
				highest = findMax(versions);
			}
			return (BundleInfo) matches.remove(highest);
		}
	}
	
	/* 
	 * Get all the bundles available on the webstart classpath
	 */
	private void discoverBundles() {
		allBundles = new HashMap();
		try {
			Enumeration resources = WebStartMain.class.getClassLoader().getResources(JarFile.MANIFEST_NAME);
			while (resources.hasMoreElements()) {
				BundleInfo found = getBundleInfo((URL)resources.nextElement());
				if (found == null)
					continue;
				ArrayList matching = (ArrayList) allBundles.get(found.bsn);
				if(matching == null) {
					matching = new ArrayList(1);
					allBundles.put(found.bsn, matching);
				}
				matching.add(found);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private String extractInnerURL(URL url) {
		try {
			URLConnection connection = null;
			try {
				connection = url.openConnection();
				if (connection instanceof JarURLConnection) {
					return "file:" + ((JarURLConnection) connection).getJarFile().getName();
				}
			} finally {
				if (connection != null)
					connection.getInputStream().close();
			}
		} catch (IOException e) {
			//Ignore and return the external form
		}
		return url.toExternalForm();
	}

	/*
	 * Construct bundle info objects from items found on the osgi.bundles list
	 */
	private void initializeBundleListStructure() {
		final char STARTLEVEL_SEPARATOR = '@';

		//In webstart the bundles list can only contain bundle names with or without a version.
		String prop = System.getProperty(PROP_OSGI_BUNDLES);
		if (prop == null || prop.trim().equals("")) { //$NON-NLS-1$
			bundleList = new ArrayList(0);
			return;
		}

		bundleList = new ArrayList(10);
		StringTokenizer tokens = new StringTokenizer(prop, ","); //$NON-NLS-1$
		while (tokens.hasMoreTokens()) {
			String token = tokens.nextToken().trim();
			String bundleId = token;
			if (token.equals("")) //$NON-NLS-1$
				continue;
			int startLevelSeparator;
			BundleInfo toAdd = new BundleInfo();
			toAdd.bsn = bundleId;
			if ((startLevelSeparator = token.lastIndexOf(STARTLEVEL_SEPARATOR)) != -1) {
				toAdd.bsn = token.substring(0, startLevelSeparator);
				toAdd.startData = token.substring(startLevelSeparator);
				//Note that here we don't try to parse the start attribute since this info is then used to recompose the value for osgi.bundles
			}
			bundleList.add(toAdd);
		}
	}

	private BundleInfo getBundleInfo(URL manifestURL) {
		final String BUNDLE_SYMBOLICNAME = "Bundle-SymbolicName"; //$NON-NLS-1$
		final String BUNDLE_VERSION = "Bundle-Version"; //$NON-NLS-1$

		Manifest mf;
		try {
			mf = new Manifest(manifestURL.openStream());
			String symbolicNameString = mf.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
			if (symbolicNameString == null)
				return null;

			BundleInfo result = new BundleInfo();
			result.version = mf.getMainAttributes().getValue(BUNDLE_VERSION);
			result.location = extractInnerURL(manifestURL); 
			int pos = symbolicNameString.lastIndexOf(';');
			if (pos != -1) { 
				result.bsn = symbolicNameString.substring(0, pos);
				return result;
			}
			result.bsn = symbolicNameString;
			return result;
		} catch (IOException e) {
			if (debug)
				e.printStackTrace();
		}
		return null;
	}
	
	//Build the osgi bundle list. The allbundles data structure is changed during the process. 
	private void buildOSGiBundleList() {
		StringBuffer finalBundleList = new StringBuffer(allBundles.size() * 30);
		//First go through all the bundles of the bundle
		for (Iterator iterator = bundleList.iterator(); iterator.hasNext();) {
			BundleInfo searched = (BundleInfo) iterator.next();
			BundleInfo found = findBundle(searched.bsn, searched.version, true);
			finalBundleList.append(REFERENCE_SCHEME).append(found.location).append(searched.startData).append(',');
		}

		if (!Boolean.FALSE.toString().equalsIgnoreCase(System.getProperties().getProperty(PROP_WEBSTART_AUTOMATIC_INSTALLATION))) {
			for (Iterator iterator = allBundles.values().iterator(); iterator.hasNext();) {
				ArrayList toAdd = (ArrayList) iterator.next();
				for (Iterator iterator2 = toAdd.iterator(); iterator2.hasNext();) {
					BundleInfo bi = (BundleInfo) iterator2.next();
					finalBundleList.append(REFERENCE_SCHEME).append(bi.location).append(',');
				}
			}
		}
		System.getProperties().put(PROP_OSGI_BUNDLES, finalBundleList.toString());
	}
}

Back to the top