/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* 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.
*/
package com.liferay.portal.osgi.web.servlet.jsp.compiler.internal;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.JavaDetector;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.SystemProperties;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
/**
* @author Raymond Augé
* @author Shuyang Zhou
*/
public class BundleJavaFileManager
extends ForwardingJavaFileManager<JavaFileManager> {
public static final String OPT_VERBOSE = "-verbose";
public BundleJavaFileManager(
ClassLoader classLoader, JavaFileManager javaFileManager,
List<JavaFileObjectResolver> javaFileObjectResolvers) {
super(javaFileManager);
_classLoader = classLoader;
_javaFileObjectResolvers = javaFileObjectResolvers;
}
@Override
public ClassLoader getClassLoader(Location location) {
if (location != StandardLocation.CLASS_PATH) {
return fileManager.getClassLoader(location);
}
return _classLoader;
}
@Override
public String inferBinaryName(Location location, JavaFileObject file) {
if ((location == StandardLocation.CLASS_PATH) &&
(file instanceof BaseJavaFileObject)) {
BaseJavaFileObject baseJavaFileObject = (BaseJavaFileObject)file;
if (_log.isInfoEnabled()) {
_log.info("Inferring binary name from " + baseJavaFileObject);
}
return baseJavaFileObject.getClassName();
}
Field nameField = _getZipFileIndexFileObjectNameField();
if ((nameField != null) &&
(file.getClass() == nameField.getDeclaringClass())) {
try {
String name = (String)nameField.get(file);
return name.substring(0, name.lastIndexOf(CharPool.PERIOD));
}
catch (ReflectiveOperationException roe) {
}
}
return fileManager.inferBinaryName(location, file);
}
@Override
public Iterable<JavaFileObject> list(
Location location, String packageName, Set<Kind> kinds,
boolean recurse)
throws IOException {
if (!kinds.contains(Kind.CLASS)) {
return Collections.emptyList();
}
if ((location == StandardLocation.CLASS_PATH) && _log.isInfoEnabled()) {
StringBundler sb = new StringBundler(9);
sb.append("List for {kinds=");
sb.append(_kinds);
sb.append(", location=");
sb.append(location);
sb.append(", packageName=");
sb.append(packageName);
sb.append(", recurse=");
sb.append(recurse);
sb.append(StringPool.CLOSE_CURLY_BRACE);
_log.info(sb.toString());
}
String packagePath = packageName.replace(
CharPool.PERIOD, CharPool.SLASH);
if (!packageName.startsWith("java.") &&
(location == StandardLocation.CLASS_PATH)) {
for (JavaFileObjectResolver javaFileObjectResolver :
_javaFileObjectResolvers) {
Collection<JavaFileObject> javaFileObjects =
javaFileObjectResolver.resolveClasses(recurse, packagePath);
if (!javaFileObjects.isEmpty()) {
return javaFileObjects;
}
}
}
return fileManager.list(location, packagePath, _kinds, recurse);
}
private static Field _doGetZipFileIndexFileObjectNameField() {
if ((JavaDetector.isOpenJDK() || JavaDetector.isOracle()) &&
GetterUtil.getBoolean(
SystemProperties.get(
"portal.servlet.jsp.compiler.sun.javac.hack.enabled"),
true)) {
try {
ClassLoader systemToolClassLoader =
ToolProvider.getSystemToolClassLoader();
Class<?> zipFileIndexFileObjectClass =
systemToolClassLoader.loadClass(
"com.sun.tools.javac.file.ZipFileIndexArchive$" +
"ZipFileIndexFileObject");
Field nameField = zipFileIndexFileObjectClass.getDeclaredField(
"name");
nameField.setAccessible(true);
return nameField;
}
catch (ReflectiveOperationException roe) {
}
}
return null;
}
private static Field _getZipFileIndexFileObjectNameField() {
if (_nameFieldReference == null) {
return null;
}
Field nameField = _nameFieldReference.get();
if (nameField != null) {
return nameField;
}
nameField = _doGetZipFileIndexFileObjectNameField();
_nameFieldReference = new SoftReference<>(nameField);
return nameField;
}
private static final Log _log = LogFactoryUtil.getLog(
BundleJavaFileManager.class);
private static final Set<Kind> _kinds = EnumSet.of(Kind.CLASS);
private static SoftReference<Field> _nameFieldReference;
static {
Field nameField = _doGetZipFileIndexFileObjectNameField();
if (nameField != null) {
_nameFieldReference = new SoftReference<>(nameField);
}
}
private final ClassLoader _classLoader;
private final List<JavaFileObjectResolver> _javaFileObjectResolvers;
}