2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.sal.binding.generator.util;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Collection;
13 import java.util.List;
15 import java.util.WeakHashMap;
16 import java.util.concurrent.locks.Lock;
17 import java.util.concurrent.locks.ReentrantLock;
19 import javassist.CannotCompileException;
20 import javassist.ClassClassPath;
21 import javassist.ClassPath;
22 import javassist.ClassPool;
23 import javassist.CtClass;
24 import javassist.CtField;
25 import javassist.CtMethod;
26 import javassist.LoaderClassPath;
27 import javassist.Modifier;
28 import javassist.NotFoundException;
30 import org.eclipse.xtext.xbase.lib.Conversions;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 import com.google.common.base.Preconditions;
36 public class JavassistUtils {
37 private static final Logger LOG = LoggerFactory.getLogger(JavassistUtils.class);
39 private final Map<ClassLoader, ClassPath> loaderClassPaths = new WeakHashMap<>();
40 private final Lock lock = new ReentrantLock();
41 private final ClassPool classPool;
43 public JavassistUtils(final ClassPool pool) {
44 classPool = Preconditions.checkNotNull(pool);
47 public Lock getLock() {
51 public void method(final CtClass it, final Class<? extends Object> returnType, final String name,
52 final Class<? extends Object> parameter, final MethodGenerator function1) throws CannotCompileException {
53 List<CtClass> _asList = Arrays.<CtClass> asList(asCtClass(parameter));
54 CtMethod _ctMethod = new CtMethod(asCtClass(returnType), name, ((CtClass[]) Conversions.unwrapArray(
55 _asList, CtClass.class)), it);
57 final CtMethod method = _ctMethod;
58 function1.process(method);
62 public void method(final CtClass it, final Class<? extends Object> returnType, final String name,
63 final Collection<? extends Class<?>> parameters, final MethodGenerator function1) throws CannotCompileException {
64 List<CtClass> _asList = new ArrayList<>();
65 for (Class<? extends Object> parameter : parameters) {
66 _asList.add(asCtClass(parameter));
68 CtMethod method = new CtMethod(asCtClass(returnType), name, ((CtClass[]) Conversions.unwrapArray(_asList,
70 function1.process(method);
74 public void staticMethod(final CtClass it, final Class<? extends Object> returnType, final String name,
75 final Class<? extends Object> parameter, final MethodGenerator function1) throws CannotCompileException {
76 List<CtClass> _asList = Arrays.<CtClass> asList(asCtClass(parameter));
77 CtMethod _ctMethod = new CtMethod(asCtClass(returnType), name, ((CtClass[]) Conversions.unwrapArray(
78 _asList, CtClass.class)), it);
79 final CtMethod method = _ctMethod;
80 function1.process(method);
84 public void implementMethodsFrom(final CtClass target, final CtClass source, final MethodGenerator function1) throws CannotCompileException {
85 for (CtMethod method : source.getMethods()) {
86 if (method.getDeclaringClass() == source) {
87 CtMethod redeclaredMethod = new CtMethod(method, target, null);
88 function1.process(redeclaredMethod);
89 target.addMethod(redeclaredMethod);
94 public CtClass createClass(final String fqn, final ClassGenerator cls) {
95 CtClass target = classPool.makeClass(fqn);
100 public CtClass createClass(final String fqn, final CtClass superInterface, final ClassGenerator cls) {
101 CtClass target = classPool.makeClass(fqn);
102 implementsType(target, superInterface);
107 public void implementsType(final CtClass it, final CtClass supertype) {
108 Preconditions.checkArgument(supertype.isInterface(), "Supertype must be interface");
109 it.addInterface(supertype);
112 public CtClass asCtClass(final Class<? extends Object> class1) {
113 return get(this.classPool, class1);
116 public CtField field(final CtClass it, final String name, final Class<? extends Object> returnValue) throws CannotCompileException {
117 final CtField field = new CtField(asCtClass(returnValue), name, it);
118 field.setModifiers(Modifier.PUBLIC);
123 public CtField staticField(final CtClass it, final String name, final Class<? extends Object> returnValue) throws CannotCompileException {
124 final CtField field = new CtField(asCtClass(returnValue), name, it);
125 field.setModifiers(Modifier.PUBLIC + Modifier.STATIC);
130 public CtClass get(final ClassPool pool, final Class<? extends Object> cls) {
132 return pool.get(cls.getName());
133 } catch (NotFoundException nfe1) {
134 appendClassLoaderIfMissing(cls.getClassLoader());
136 return pool.get(cls.getName());
137 } catch (final NotFoundException nfe2) {
138 LOG.warn("Appending ClassClassPath for {}", cls, nfe2);
139 pool.appendClassPath(new ClassClassPath(cls));
141 return pool.get(cls.getName());
142 } catch (NotFoundException e) {
143 LOG.warn("Failed to load class {} from pool {}", cls, pool, e);
144 throw new IllegalStateException("Failed to load class", e);
150 public synchronized void appendClassLoaderIfMissing(final ClassLoader loader) {
151 // FIXME: this works as long as the ClassPool is not shared between instances of this class
152 // How is synchronization across multiple instances done? The ClassPool itself just
153 // keeps on adding the loaders and does not check for duplicates!
154 if (!loaderClassPaths.containsKey(loader)) {
155 final ClassPath ctLoader = new LoaderClassPath(loader);
156 classPool.appendClassPath(ctLoader);
157 loaderClassPaths.put(loader, ctLoader);
161 public void ensureClassLoader(final Class<?> child) {
162 appendClassLoaderIfMissing(child.getClassLoader());