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 * bstefanescu 018 */ 019package org.nuxeo.osgi.application.client; 020 021import java.io.File; 022import java.io.IOException; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.Collection; 026import java.util.Collections; 027import java.util.LinkedHashSet; 028import java.util.List; 029import java.util.StringTokenizer; 030 031import org.nuxeo.common.Environment; 032import org.nuxeo.osgi.BundleFile; 033import org.nuxeo.osgi.BundleImpl; 034import org.nuxeo.osgi.DirectoryBundleFile; 035import org.nuxeo.osgi.JarBundleFile; 036import org.nuxeo.osgi.OSGiAdapter; 037import org.nuxeo.osgi.SystemBundle; 038import org.nuxeo.osgi.SystemBundleFile; 039import org.osgi.framework.BundleException; 040import org.osgi.framework.FrameworkEvent; 041 042/** 043 * Nuxeo Runtime launcher. 044 * <p> 045 * This launcher assumes all bundles are already on the classpath. 046 * 047 * @author <a href="mailto:[email protected]">Bogdan Stefanescu</a> 048 */ 049public class NuxeoApp { 050 051 protected final ClassLoader loader; 052 053 protected final Environment env; 054 055 private OSGiAdapter osgi; 056 057 public static ClassLoader getDefaultClassLoader() { 058 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 059 return cl == null ? NuxeoApp.class.getClassLoader() : cl; 060 } 061 062 public NuxeoApp() { 063 this(new File("."), getDefaultClassLoader()); 064 } 065 066 public NuxeoApp(File home) { 067 this(home, getDefaultClassLoader()); 068 } 069 070 public NuxeoApp(File home, ClassLoader loader) { 071 this.loader = loader; 072 env = new Environment(home); 073 Environment.setDefault(env); 074 } 075 076 public ClassLoader getLoader() { 077 return loader; 078 } 079 080 public Environment getEnvironment() { 081 return env; 082 } 083 084 public void deployBundles(String bundlePath) throws BundleException, IOException { 085 deployBundles(getBundleFiles(new File("."), bundlePath, ":")); 086 } 087 088 public void deployBundles(File baseDir, String bundlePath) throws BundleException, IOException { 089 deployBundles(getBundleFiles(baseDir, bundlePath, ":")); 090 } 091 092 public synchronized void deployBundles(Collection<File> files) throws BundleException, IOException { 093 if (!isStarted()) { 094 throw new IllegalStateException("Framework not started"); 095 } 096 for (File file : files) { 097 deployBundle(file); 098 } 099 } 100 101 public synchronized void deployBundle(File file) throws BundleException, IOException { 102 if (!isStarted()) { 103 throw new IllegalStateException("Framework not started"); 104 } 105 if (!file.getPath().endsWith(".jar")) { 106 return; // not a valid bundle 107 } 108 BundleFile bf = file.isDirectory() ? new DirectoryBundleFile(file) : new JarBundleFile(file); 109 try { 110 BundleImpl bundle = new BundleImpl(osgi, bf, loader); 111 if (bundle.getSymbolicName() != null) { 112 osgi.install(bundle); 113 } 114 } catch (NullPointerException t) { 115 // do nothing: may happen with non OSGi manifests 116 // System.out.println("Ignore: "+file); 117 } 118 } 119 120 public synchronized void start() { 121 if (osgi != null) { 122 throw new IllegalStateException("Nuxeo Runtime already started"); 123 } 124 osgi = new OSGiAdapter(env.getHome(), env.getData(), env.getProperties()); 125 } 126 127 public synchronized boolean isStarted() { 128 return osgi != null; 129 } 130 131 public synchronized OSGiAdapter getOsgi() { 132 return osgi; 133 } 134 135 public synchronized void shutdown() throws IOException { 136 if (osgi == null) { 137 throw new IllegalStateException("Nuxeo Runtime not started"); 138 } 139 osgi.shutdown(); 140 osgi = null; 141 } 142 143 public static Collection<File> getBundleFiles(File baseDir, String bundles, String delim) throws IOException { 144 Collection<File> result = new LinkedHashSet<File>(); 145 StringTokenizer tokenizer = new StringTokenizer(bundles, delim == null ? " \t\n\r\f" : delim); 146 while (tokenizer.hasMoreTokens()) { 147 String tok = tokenizer.nextToken(); 148 List<File> files = expandFiles(baseDir, tok); 149 for (File file : files) { 150 result.add(file.getCanonicalFile()); 151 } 152 } 153 return result; 154 } 155 156 public static File makeFile(File baseDir, String path) { 157 if (path.startsWith("/")) { 158 return new File(path); 159 } 160 return new File(baseDir, path); 161 } 162 163 public static List<File> expandFiles(File baseDir, String line) { 164 int p = line.lastIndexOf("/"); 165 String fileName = null; 166 if (p > -1) { 167 fileName = line.substring(p + 1); 168 baseDir = makeFile(baseDir, line.substring(0, p)); 169 } else { 170 fileName = line; 171 } 172 if (fileName.length() == 0) { 173 return Arrays.asList(baseDir.listFiles()); 174 } 175 p = fileName.indexOf("*"); 176 if (p == -1) { 177 return Collections.singletonList(makeFile(baseDir, fileName)); 178 } else if (p == 0) { 179 String suffix = fileName.substring(p + 1); 180 List<File> result = new ArrayList<File>(); 181 String[] names = baseDir.list(); 182 if (names != null) { 183 for (String name : names) { 184 if (name.endsWith(suffix)) { 185 result.add(makeFile(baseDir, name)); 186 } 187 } 188 } 189 return result; 190 } else if (p == fileName.length() - 1) { 191 String prefix = fileName.substring(0, p); 192 List<File> result = new ArrayList<File>(); 193 String[] names = baseDir.list(); 194 if (names != null) { 195 for (String name : baseDir.list()) { 196 if (name.startsWith(prefix)) { 197 result.add(makeFile(baseDir, name)); 198 } 199 } 200 } 201 return result; 202 } else { 203 String prefix = fileName.substring(0, p); 204 String suffix = fileName.substring(p + 1); 205 List<File> result = new ArrayList<File>(); 206 String[] names = baseDir.list(); 207 if (names != null) { 208 for (String name : names) { 209 if (name.startsWith(prefix) && name.endsWith(suffix)) { 210 result.add(makeFile(baseDir, name)); 211 } 212 } 213 } 214 return result; 215 } 216 } 217 218 public void fireFrameworkStarted() throws BundleException { 219 if (osgi.getSystemBundle() == null) { 220 SystemBundleFile file; 221 try { 222 file = new SystemBundleFile(osgi.getWorkingDir()); 223 } catch (IOException e) { 224 throw new BundleException("Cannot create system bundle file", e); 225 } 226 osgi.setSystemBundle(new SystemBundle(osgi, file, loader)); 227 } 228 osgi.fireFrameworkEvent(new FrameworkEvent(FrameworkEvent.STARTED, osgi.getSystemBundle(), null)); 229 } 230 231}