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.util.Collection; 027import java.util.jar.JarFile; 028import java.util.jar.Manifest; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.nuxeo.common.utils.FileNamePattern; 033import org.nuxeo.common.utils.JarUtils; 034import org.nuxeo.osgi.BundleFile; 035import org.nuxeo.osgi.DirectoryBundleFile; 036import org.nuxeo.osgi.JarBundleFile; 037import org.osgi.framework.Constants; 038 039/** 040 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 041 */ 042public class BundleWalker extends FileWalker.Visitor { 043 044 private static final Log log = LogFactory.getLog(BundleWalker.class); 045 046 public static final FileNamePattern[] DEFAULT_PATTERNS = { new FileNamePattern("*.jar"), 047 new FileNamePattern("*.war"), new FileNamePattern("*.rar"), new FileNamePattern("*.sar"), // jboss sar 048 new FileNamePattern("*_jar"), new FileNamePattern("*_war"), new FileNamePattern("*_rar") }; 049 050 private FileNamePattern[] patterns; 051 052 private final Callback callback; 053 054 public BundleWalker(Callback cb) { 055 this(cb, DEFAULT_PATTERNS); 056 } 057 058 public BundleWalker(Callback cb, String[] patterns) { 059 if (patterns != null) { 060 this.patterns = new FileNamePattern[patterns.length]; 061 for (int i = 0; i < patterns.length; i++) { 062 this.patterns[i] = new FileNamePattern(patterns[i]); 063 } 064 } 065 callback = cb; 066 } 067 068 public BundleWalker(Callback cb, FileNamePattern[] patterns) { 069 this.patterns = patterns; 070 callback = cb; 071 } 072 073 public void visit(File root) { 074 FileWalker.walk(root, this); 075 } 076 077 public void visit(Collection<File> files) { 078 for (File file : files) { 079 if (file.isFile()) { 080 if (file.isFile()) { 081 visitFile(file); 082 } else if (file.isDirectory()) { 083 visitDirectory(file); 084 } 085 } 086 } 087 } 088 089 public void visit(File... files) { 090 for (File file : files) { 091 if (file.isFile()) { 092 if (file.isFile()) { 093 visitFile(file); 094 } else if (file.isDirectory()) { 095 visitDirectory(file); 096 } 097 } 098 } 099 } 100 101 @Override 102 public int visitDirectory(File file) { 103 // System.out.println("###### Processing DIR: " + file); 104 // first check if this is a possible bundle 105 String fileName = file.getName(); 106 if (patterns != null) { 107 if (!acceptFile(fileName, patterns)) { 108 return FileWalker.CONTINUE; 109 } 110 } 111 // check if this is an OSGi bundle 112 try { 113 Manifest mf = JarUtils.getDirectoryManifest(file); 114 if (mf == null) { 115 return FileWalker.CONTINUE; 116 } 117 String bundleName = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME); 118 if (bundleName != null) { 119 // notify the callback about the new bundle 120 callback.visitBundle(new DirectoryBundleFile(file, mf)); 121 // assume that a directory OSGi bundle cannot contain other bundles so skip it 122 return FileWalker.BREAK; 123 } 124 } catch (IOException e) { 125 log.error(e, e); 126 } 127 return FileWalker.CONTINUE; 128 } 129 130 @Override 131 public int visitFile(File file) { 132 // first check if this is a possible bundle 133 String fileName = file.getName(); 134 if (patterns != null) { 135 if (!acceptFile(fileName, patterns)) { 136 return FileWalker.CONTINUE; 137 } 138 } 139 // check if this is an OSGi bundle 140 try (JarFile jarFile = new JarFile(file)) { 141 if (jarFile.getManifest() == null) { 142 return FileWalker.CONTINUE; 143 } 144 BundleFile bundleFile = new JarBundleFile(jarFile); 145 if (bundleFile.getSymbolicName() != null) { 146 // notify the callback about the new bundle 147 callback.visitBundle(bundleFile); 148 } else { 149 // notify the callback about the new jar 150 callback.visitJar(bundleFile); 151 } 152 } catch (IOException e) { 153 // ignore 154 } 155 return FileWalker.CONTINUE; 156 } 157 158 protected boolean acceptFile(String fileName, FileNamePattern[] patterns) { 159 int i = 0; 160 for (; i < patterns.length; i++) { 161 if (patterns[i].match(fileName)) { 162 break; 163 } 164 } 165 return i < patterns.length; 166 } 167 168 public interface Callback { 169 void visitBundle(BundleFile bundleFile) throws IOException; 170 171 void visitJar(BundleFile bundleFile) throws IOException; 172 } 173 174}