/*
* (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* Contributors:
* bstefanescu
*
* $Id$
*/
package org.nuxeo.runtime.annotations.loader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
/**
* @deprecated not used
*
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*
*/
public class BundleAnnotationsLoader implements BundleListener {
private static final Log log = LogFactory.getLog(BundleAnnotationsLoader.class);
protected static final BundleAnnotationsLoader instance = new BundleAnnotationsLoader();
public static BundleAnnotationsLoader getInstance() {
return instance;
}
protected final Map<String, AnnotationLoader> loaders;
protected final Map<String, List<Entry>> pendings;
public BundleAnnotationsLoader() {
loaders = new HashMap<String, AnnotationLoader>();
pendings = new HashMap<String, List<Entry>>();
}
public synchronized void addLoader(String annotationType,
AnnotationLoader loader) {
loaders.put(annotationType, loader);
List<Entry> entries = pendings.remove(annotationType);
if (entries != null) {
for (Entry entry : entries) {
try {
loader.loadAnnotation(entry.bundle, annotationType,
entry.className, entry.args);
} catch (Exception e) {
log.error("Failed to load annotation: " + annotationType
+ "@" + entry.className, e);
}
}
}
}
public void loadAnnotationsFromDeployedBundles(Bundle bundle)
throws IOException {
Bundle[] bundles = bundle.getBundleContext().getBundles();
for (Bundle b : bundles) {
loadAnnotations(b);
}
}
public void loadAnnotations(Bundle bundle) throws IOException {
URL url = bundle.getEntry("OSGI-INF/annotations");
if (url != null) {
InputStream in = url.openStream();
try {
log.info("Loading annotations from bundle: "
+ bundle.getSymbolicName());
for (String line : readLines(in)) {
loadAnnotation(bundle, line);
}
} finally {
in.close();
}
}
}
protected void loadAnnotation(Bundle bundle, String line) {
String[] ar = parse(line);
if (ar.length < 2) {
log.error("Invalid annotation entry key '" + line + "' in bundle '"
+ bundle.getLocation() + "'.");
return;
}
String className = ar[0];
String annoType = ar[1];
if (ar.length > 2) {
String[] tmp = new String[ar.length - 2];
System.arraycopy(ar, 2, tmp, 0, tmp.length);
ar = tmp;
}
loadAnnotation(bundle, annoType, className, ar);
}
public static String[] parse(String str) {
ArrayList<String> list = new ArrayList<String>();
char[] chars = str.toCharArray();
boolean esc = false;
StringBuilder buf = new StringBuilder();
char c = 0;
for (int i = 0; i < chars.length; i++) {
c = chars[i];
switch (c) {
case '\\':
if (!esc) {
esc = true;
} else {
esc = false;
buf.append(c);
}
break;
case '|':
if (!esc) {
list.add(buf.toString());
buf.setLength(0);
} else {
// System.out.println("escaped | >>> "+buf.toString());
buf.append(c);
esc = false;
}
break;
default:
buf.append(c);
}
}
if (buf.length() > 0) {
list.add(buf.toString());
} else if (c == '|') {
list.add("");
}
return list.toArray(new String[list.size()]);
}
protected synchronized void loadAnnotation(Bundle bundle,
String annotationType, String className, String[] args) {
AnnotationLoader loader = loaders.get(annotationType);
if (loader != null) {
try {
loader.loadAnnotation(bundle, annotationType, className, args);
} catch (Exception e) {
log.error("Failed to load annotation: " + annotationType + "@"
+ className, e);
}
} else { // queue the entry until a loader is registered
List<Entry> entries = pendings.get(annotationType);
if (entries == null) {
entries = new ArrayList<Entry>();
pendings.put(annotationType, entries);
}
entries.add(new Entry(bundle, className, args));
}
}
static class Entry {
final Bundle bundle;
final String className;
final String[] args;
Entry(Bundle bundle, String className, String[] args) {
this.bundle = bundle;
this.className = className;
this.args = args;
}
}
public void bundleChanged(BundleEvent event) {
try {
switch (event.getType()) {
case BundleEvent.RESOLVED:
loadAnnotations(event.getBundle());
break;
case BundleEvent.UNRESOLVED:
// TODO implement unload
// unloadAnnotations(event.getBundle());
break;
}
} catch (IOException e) {
log.error(e, e);
}
}
public static List<String> readLines(InputStream in) throws IOException {
List<String> lines = new ArrayList<String>();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
return lines;
}
}