001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.osgi.application; 023 024import java.io.File; 025import java.io.IOException; 026import java.lang.reflect.Method; 027import java.net.URL; 028import java.net.URLClassLoader; 029import java.util.ArrayList; 030import java.util.List; 031 032/** 033 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 034 */ 035public class Main { 036 037 public static void main(String[] args) throws Exception { 038 if (args.length == 0) { 039 System.err.println("No classpath specified"); 040 System.exit(10); 041 } 042 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 043 if (!(cl instanceof URLClassLoader)) { 044 System.err.println("Not a valid class loader: " + cl); 045 System.exit(10); 046 } 047 ClassLoader parent = cl.getParent(); 048 if (parent == null) { 049 parent = ClassLoader.getSystemClassLoader(); 050 } 051 RootClassLoader rootLoader = new RootClassLoader(parent, SharedClassLoader.class); 052 SharedClassLoaderImpl classLoader = new SharedClassLoaderImpl(((URLClassLoader) cl).getURLs(), rootLoader); 053 Thread.currentThread().setContextClassLoader(classLoader.getLoader()); 054 URL systemBundle = classLoader.getURLs()[0]; 055 // build the class path now 056 List<File> cp = buildClassPath(classLoader, args[0]); 057 // make new arguments by removing the first one to pass further 058 String[] tmp = new String[args.length - 1]; 059 System.arraycopy(args, 1, tmp, 0, tmp.length); 060 args = tmp; 061 // reload classes from this JAR using a SharedClassLoader 062 Class<?> me = classLoader.loadClass(StandaloneApplication.class.getName()); 063 Method main = me.getMethod("main", URL.class, List.class, String[].class); 064 main.invoke(null, systemBundle, cp, args); 065 } 066 067 public static List<File> buildClassPath(SharedClassLoader classLoader, String rawcp) throws IOException { 068 List<File> result = new ArrayList<>(); 069 String[] cp = rawcp.split(":"); 070 for (String entry : cp) { 071 File entryFile; 072 if (entry.endsWith("/.")) { 073 entryFile = new File(entry.substring(0, entry.length() - 2)); 074 File[] files = entryFile.listFiles(); 075 if (files != null) { 076 for (File file : files) { 077 result.add(file); 078 classLoader.addURL(file.toURI().toURL()); 079 } 080 } 081 } else { 082 entryFile = new File(entry); 083 result.add(entryFile); 084 classLoader.addURL(entryFile.toURI().toURL()); 085 } 086 } 087 return result; 088 } 089 090 private static class RootClassLoader extends ClassLoader { 091 092 private final Class<?> loaderClass; 093 094 private final String loaderName; 095 096 RootClassLoader(ClassLoader parent, Class<?> loaderClass) { 097 super(parent); 098 this.loaderClass = loaderClass; 099 loaderName = loaderClass.getName(); 100 } 101 102 @Override 103 protected Class<?> findClass(String name) throws ClassNotFoundException { 104 if (loaderName.equals(name)) { 105 return loaderClass; 106 } 107 throw new ClassNotFoundException(name); 108 } 109 110 } 111 112}