org.netbeans.html.mojo.ProcessJsAnnotations Maven / Gradle / Ivy
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.html.mojo;
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.objectweb.asm.ClassReader;
abstract class ProcessJsAnnotations {
private Boolean addAsm;
private final LinkedList cp = new LinkedList<>();
private final List roots = new LinkedList<>();
protected abstract void log(String msg);
public void addClasspathEntry(File f) {
try {
cp.add(f.toURI().toURL());
} catch (MalformedURLException ex) {
throw new IllegalStateException(ex);
}
}
public void setAddAsm(boolean add) {
this.addAsm = add;
}
public void addRoot(File file) {
roots.add(file);
}
public void process() throws IOException {
MultiFile classes = new MultiFile(roots);
for (File r : roots) {
cp.add(r.toURI().toURL());
}
URLClassLoader l = new URLClassLoader(cp.toArray(new URL[cp.size()]));
Boolean asm = addAsm;
if (asm == null) {
try {
l.loadClass(ClassReader.class.getName());
// OK
asm = false;
} catch (ClassNotFoundException ex) {
asm = true;
}
}
if (asm) {
URL loc = ClassReader.class.getProtectionDomain().getCodeSource().getLocation();
cp.addFirst(loc);
l = new URLClassLoader(cp.toArray(new URL[cp.size()]));
}
MultiFile master = classes.child("META-INF", "net.java.html.js.classes");
processClasses(l, master, classes);
}
private void processClasses(ClassLoader l, MultiFile master, MultiFile f) throws IOException {
if (!f.exists()) {
return;
}
if (f.isDirectory()) {
boolean classes = f.child("net.java.html.js.classes").exists();
MultiFile[] arr = f.listFiles();
if (arr != null) {
for (MultiFile file : arr) {
if (classes || file.isDirectory()) {
processClasses(l, master, file);
}
}
}
}
if (!f.isFile() || !f.getName().endsWith(".class")) {
return;
}
byte[] arr = f.readFully();
byte[] newArr = null;
try {
Class> fnUtils = l.loadClass("org.netbeans.html.boot.impl.FnUtils");
Method transform = fnUtils.getMethod("transform", byte[].class, ClassLoader.class);
newArr = (byte[]) transform.invoke(null, arr, l);
if (newArr == null || newArr == arr) {
return;
}
filterClass(f.getParentFile().child("net.java.html.js.classes"), f.getName());
filterClass(master, f.getName());
} catch (Exception ex) {
throw new IOException("Can't process " + f, ex);
}
log("Processing " + f);
f.writeArr(newArr);
}
private static void filterClass(MultiFile f, String className) throws IOException {
if (!f.exists()) {
return;
}
if (className.endsWith(".class")) {
className = className.substring(0, className.length() - 6);
}
List arr;
boolean modified;
try (BufferedReader r = new BufferedReader(f.reader())) {
arr = new ArrayList<>();
modified = false;
for (;;) {
String line = r.readLine();
if (line == null) {
break;
}
if (line.endsWith(className)) {
modified = true;
continue;
}
arr.add(line);
}
}
if (modified) {
if (arr.isEmpty()) {
f.delete();
} else {
try (BufferedWriter w = new BufferedWriter(f.writer())) {
for (String l : arr) {
w.write(l);
w.write("\n");
}
}
}
}
}
private static final class MultiFile {
private final List roots;
MultiFile(List roots) {
this.roots = roots;
}
MultiFile child(String... names) {
List arr = new ArrayList<>();
for (File r : roots) {
for (String n : names) {
r = new File(r, n);
}
arr.add(r);
}
return new MultiFile(arr);
}
boolean exists() {
for (File r : roots) {
if (r.exists()) {
return true;
}
}
return false;
}
boolean isDirectory() {
for (File r : roots) {
if (r.isDirectory()) {
return true;
}
}
return false;
}
String getName() {
for (File r : roots) {
return r.getName();
}
return null;
}
MultiFile[] listFiles() {
Set names = new TreeSet<>();
for (File r : roots) {
final String[] children = r.list();
if (children == null) {
continue;
}
names.addAll(Arrays.asList(children));
}
MultiFile[] arr = new MultiFile[names.size()];
int at = 0;
for (String name : names) {
arr[at++] = child(name);
}
return arr;
}
boolean isFile() {
for (File r : roots) {
if (r.isFile()) {
return true;
}
}
return false;
}
private MultiFile getParentFile() {
List arr = new ArrayList<>();
for (File r : roots) {
arr.add(r.getParentFile());
}
return new MultiFile(arr);
}
byte[] readFully() throws IOException {
for (File f : roots) {
if (f.isFile()) {
byte[] arr;
try (FileInputStream is = new FileInputStream(f)) {
arr = new byte[(int)f.length()];
int off = 0;
while (off < arr.length) {
int read = is.read(arr, off, arr.length - off);
if (read == -1) {
break;
}
off += read;
}
}
return arr;
}
}
throw new FileNotFoundException();
}
private void writeArr(byte[] newArr) throws IOException, FileNotFoundException {
for (File f : roots) {
if (f.isDirectory()) {
continue;
}
f.getParentFile().mkdirs();
try (FileOutputStream os = new FileOutputStream(f)) {
os.write(newArr);
}
return;
}
throw new FileNotFoundException();
}
private Reader reader() throws FileNotFoundException {
for (File r : roots) {
if (r.isFile()) {
return new FileReader(r);
}
}
throw new FileNotFoundException();
}
private void delete() {
for (File r : roots) {
r.delete();
}
}
private FileWriter writer() throws IOException {
for (File r : roots) {
if (r.isFile()) {
return new FileWriter(r);
}
}
throw new FileNotFoundException();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
String sep = "";
for (File r : roots) {
sb.append(sep);
sb.append(r.toString());
sep = ", ";
}
return sb.toString();
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy