001/* 002 * Copyright 2012-2016 the original author or authors. 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 017package org.springframework.boot.cli.archive; 018 019import java.net.URL; 020import java.net.URLClassLoader; 021import java.util.Enumeration; 022import java.util.jar.Attributes; 023import java.util.jar.Manifest; 024 025import org.springframework.boot.cli.app.SpringApplicationLauncher; 026 027/** 028 * A launcher for a CLI application that has been compiled and packaged as a jar file. 029 * 030 * @author Andy Wilkinson 031 * @author Phillip Webb 032 */ 033public final class PackagedSpringApplicationLauncher { 034 035 /** 036 * The entry containing the source class. 037 */ 038 public static final String SOURCE_ENTRY = "Spring-Application-Source-Classes"; 039 040 /** 041 * The entry containing the start class. 042 */ 043 public static final String START_CLASS_ENTRY = "Start-Class"; 044 045 private PackagedSpringApplicationLauncher() { 046 } 047 048 private void run(String[] args) throws Exception { 049 URLClassLoader classLoader = (URLClassLoader) Thread.currentThread() 050 .getContextClassLoader(); 051 new SpringApplicationLauncher(classLoader).launch(getSources(classLoader), args); 052 } 053 054 private Object[] getSources(URLClassLoader classLoader) throws Exception { 055 Enumeration<URL> urls = classLoader.getResources("META-INF/MANIFEST.MF"); 056 while (urls.hasMoreElements()) { 057 URL url = urls.nextElement(); 058 Manifest manifest = new Manifest(url.openStream()); 059 if (isCliPackaged(manifest)) { 060 String sources = manifest.getMainAttributes().getValue(SOURCE_ENTRY); 061 return loadClasses(classLoader, sources.split(",")); 062 } 063 } 064 throw new IllegalStateException( 065 "Cannot locate " + SOURCE_ENTRY + " in MANIFEST.MF"); 066 } 067 068 private boolean isCliPackaged(Manifest manifest) { 069 Attributes attributes = manifest.getMainAttributes(); 070 String startClass = attributes.getValue(START_CLASS_ENTRY); 071 return getClass().getName().equals(startClass); 072 } 073 074 private Class<?>[] loadClasses(ClassLoader classLoader, String[] names) 075 throws ClassNotFoundException { 076 Class<?>[] classes = new Class<?>[names.length]; 077 for (int i = 0; i < names.length; i++) { 078 classes[i] = classLoader.loadClass(names[i]); 079 } 080 return classes; 081 } 082 083 public static void main(String[] args) throws Exception { 084 new PackagedSpringApplicationLauncher().run(args); 085 } 086 087}