html4j-maven-plugin/src/main/java/org/netbeans/html/mojo/ProcessJsAnnotationsMojo.java
author Jaroslav Tulach <jaroslav.tulach@netbeans.org>
Fri, 07 Feb 2014 07:44:34 +0100
changeset 551 7ca2253fa86d
parent 536 83deda5c6ea5
child 728 90fc6f6e508b
permissions -rw-r--r--
Updating copyright headers to mention current year
jaroslav@331
     1
/**
jaroslav@421
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jaroslav@331
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jaroslav@331
     5
 *
jaroslav@421
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@421
     7
 * Other names may be trademarks of their respective owners.
jaroslav@331
     8
 *
jaroslav@421
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@421
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@421
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@421
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@421
    13
 * License. You can obtain a copy of the License at
jaroslav@421
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@421
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@421
    16
 * specific language governing permissions and limitations under the
jaroslav@421
    17
 * License.  When distributing the software, include this License Header
jaroslav@421
    18
 * Notice in each file and include the License file at
jaroslav@421
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@421
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@421
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@421
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@421
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@421
    24
 * your own identifying information:
jaroslav@421
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@421
    26
 *
jaroslav@421
    27
 * Contributor(s):
jaroslav@421
    28
 *
jaroslav@421
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@551
    30
 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
jaroslav@421
    31
 *
jaroslav@421
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@421
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@421
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@421
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@421
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@421
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@421
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@421
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@421
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@421
    41
 * made subject to such option by the copyright holder.
jaroslav@331
    42
 */
jaroslav@536
    43
package org.netbeans.html.mojo;
jaroslav@331
    44
jaroslav@486
    45
import java.io.BufferedReader;
jaroslav@331
    46
import java.io.File;
jaroslav@331
    47
import java.io.FileInputStream;
jaroslav@334
    48
import java.io.FileNotFoundException;
jaroslav@331
    49
import java.io.FileOutputStream;
jaroslav@486
    50
import java.io.FileReader;
jaroslav@486
    51
import java.io.FileWriter;
jaroslav@331
    52
import java.io.IOException;
jaroslav@334
    53
import java.io.InputStream;
jaroslav@486
    54
import java.lang.reflect.Method;
jaroslav@351
    55
import java.net.MalformedURLException;
jaroslav@351
    56
import java.net.URL;
jaroslav@351
    57
import java.net.URLClassLoader;
jaroslav@351
    58
import java.util.ArrayList;
jaroslav@351
    59
import java.util.List;
jaroslav@334
    60
import org.apache.maven.artifact.Artifact;
jaroslav@331
    61
import org.apache.maven.plugin.AbstractMojo;
jaroslav@331
    62
import org.apache.maven.plugin.MojoExecutionException;
jaroslav@331
    63
import org.apache.maven.plugin.MojoFailureException;
jaroslav@486
    64
import org.apache.maven.plugins.annotations.Component;
jaroslav@331
    65
import org.apache.maven.plugins.annotations.LifecyclePhase;
jaroslav@331
    66
import org.apache.maven.plugins.annotations.Mojo;
jaroslav@331
    67
import org.apache.maven.plugins.annotations.Parameter;
jaroslav@331
    68
import org.apache.maven.plugins.annotations.ResolutionScope;
jaroslav@331
    69
import org.apache.maven.project.MavenProject;
jaroslav@489
    70
import org.objectweb.asm.ClassReader;
jaroslav@331
    71
jaroslav@331
    72
@Mojo(
jaroslav@331
    73
    name="process-js-annotations",
jaroslav@486
    74
    requiresDependencyResolution = ResolutionScope.COMPILE,
jaroslav@331
    75
    defaultPhase= LifecyclePhase.PROCESS_CLASSES
jaroslav@331
    76
)
jaroslav@331
    77
public final class ProcessJsAnnotationsMojo extends AbstractMojo {
jaroslav@486
    78
    @Component
jaroslav@331
    79
    private MavenProject prj;
jaroslav@331
    80
    
jaroslav@331
    81
    @Parameter(defaultValue = "${project.build.directory}/classes")
jaroslav@331
    82
    private File classes;
jaroslav@334
    83
    
jaroslav@331
    84
    public ProcessJsAnnotationsMojo() {
jaroslav@331
    85
    }
jaroslav@331
    86
jaroslav@331
    87
    @Override
jaroslav@331
    88
    public void execute() throws MojoExecutionException, MojoFailureException {
jaroslav@486
    89
        List<URL> arr = new ArrayList<URL>();
jaroslav@489
    90
        boolean foundAsm = false;
jaroslav@486
    91
        for (Artifact a : prj.getArtifacts()) {
jaroslav@486
    92
            final File f = a.getFile();
jaroslav@486
    93
            if (f != null) {
jaroslav@489
    94
                if (a.getArtifactId().equals("asm")) {
jaroslav@489
    95
                    foundAsm = true;
jaroslav@489
    96
                }
jaroslav@486
    97
                try {
jaroslav@486
    98
                    arr.add(f.toURI().toURL());
jaroslav@486
    99
                } catch (MalformedURLException ex) {
jaroslav@486
   100
                    throw new IllegalStateException(ex);
jaroslav@486
   101
                }
jaroslav@486
   102
            }
jaroslav@486
   103
        }
jaroslav@489
   104
        if (!foundAsm) {
jaroslav@489
   105
            URL loc = ClassReader.class.getProtectionDomain().getCodeSource().getLocation();
jaroslav@489
   106
            arr.add(loc);
jaroslav@489
   107
        }
jaroslav@486
   108
        URLClassLoader l = new URLClassLoader(arr.toArray(new URL[arr.size()]));
jaroslav@331
   109
        try {
jaroslav@509
   110
            File master = new File(new File(classes, "META-INF"), "net.java.html.js.classes");
jaroslav@509
   111
            processClasses(l, master, classes);
jaroslav@331
   112
        } catch (IOException ex) {
jaroslav@331
   113
            throw new MojoExecutionException("Problem converting JavaScriptXXX annotations", ex);
jaroslav@331
   114
        }
jaroslav@486
   115
    }
jaroslav@486
   116
    
jaroslav@509
   117
    private void processClasses(ClassLoader l, File master, File f) throws IOException, MojoExecutionException {
jaroslav@486
   118
        if (!f.exists()) {
jaroslav@486
   119
            return;
jaroslav@486
   120
        }
jaroslav@486
   121
        if (f.isDirectory()) {
jaroslav@486
   122
            boolean classes = new File(f, "net.java.html.js.classes").exists();
jaroslav@486
   123
            File[] arr = f.listFiles();
jaroslav@486
   124
            if (arr != null) {
jaroslav@486
   125
                for (File file : arr) {
jaroslav@486
   126
                    if (classes || file.isDirectory()) {
jaroslav@509
   127
                        processClasses(l, master, file);
jaroslav@351
   128
                    }
jaroslav@351
   129
                }
jaroslav@351
   130
            }
jaroslav@331
   131
            return;
jaroslav@331
   132
        }
jaroslav@331
   133
        
jaroslav@331
   134
        if (!f.getName().endsWith(".class")) {
jaroslav@331
   135
            return;
jaroslav@331
   136
        }
jaroslav@331
   137
        
jaroslav@331
   138
        byte[] arr = new byte[(int)f.length()];
jaroslav@331
   139
        FileInputStream is = new FileInputStream(f);
jaroslav@331
   140
        try {
jaroslav@334
   141
            readArr(arr, is);
jaroslav@331
   142
        } finally {
jaroslav@331
   143
            is.close();
jaroslav@331
   144
        }
jaroslav@486
   145
jaroslav@486
   146
        byte[] newArr = null;
jaroslav@486
   147
        try {
jaroslav@486
   148
            Class<?> fnUtils = l.loadClass("org.netbeans.html.boot.impl.FnUtils");
jaroslav@486
   149
            Method transform = fnUtils.getMethod("transform", byte[].class, ClassLoader.class);
jaroslav@486
   150
            
jaroslav@486
   151
            newArr = (byte[]) transform.invoke(null, arr, l);
jaroslav@486
   152
            if (newArr == null || newArr == arr) {
jaroslav@486
   153
                return;
jaroslav@486
   154
            }
jaroslav@486
   155
            filterClass(new File(f.getParentFile(), "net.java.html.js.classes"), f.getName());
jaroslav@509
   156
            filterClass(master, f.getName());
jaroslav@486
   157
        } catch (Exception ex) {
jaroslav@486
   158
            throw new MojoExecutionException("Can't process " + f, ex);
jaroslav@331
   159
        }
jaroslav@334
   160
        getLog().info("Processing " + f);
jaroslav@334
   161
        writeArr(f, newArr);        
jaroslav@334
   162
    }
jaroslav@334
   163
jaroslav@334
   164
    private void writeArr(File f, byte[] newArr) throws IOException, FileNotFoundException {
jaroslav@334
   165
        FileOutputStream os = new FileOutputStream(f);
jaroslav@334
   166
        try {
jaroslav@334
   167
            os.write(newArr);
jaroslav@334
   168
        } finally {
jaroslav@334
   169
            os.close();
jaroslav@334
   170
        }
jaroslav@334
   171
    }
jaroslav@334
   172
jaroslav@334
   173
    private static void readArr(byte[] arr, InputStream is) throws IOException {
jaroslav@334
   174
        int off = 0;
jaroslav@334
   175
        while (off< arr.length) {
jaroslav@334
   176
            int read = is.read(arr, off, arr.length - off);
jaroslav@334
   177
            if (read == -1) {
jaroslav@334
   178
                break;
jaroslav@334
   179
            }
jaroslav@334
   180
            off += read;
jaroslav@334
   181
        }
jaroslav@334
   182
    }
jaroslav@334
   183
    
jaroslav@486
   184
    private static void filterClass(File f, String className) throws IOException {
jaroslav@486
   185
        if (!f.exists()) {
jaroslav@486
   186
            return;
jaroslav@486
   187
        }
jaroslav@486
   188
        if (className.endsWith(".class")) {
jaroslav@486
   189
            className = className.substring(0, className.length() - 6);
jaroslav@486
   190
        }
jaroslav@486
   191
        
jaroslav@486
   192
        BufferedReader r = new BufferedReader(new FileReader(f));
jaroslav@486
   193
        List<String> arr = new ArrayList<String>();
jaroslav@486
   194
        boolean modified = false;
jaroslav@486
   195
        for (;;) {
jaroslav@486
   196
            String line = r.readLine();
jaroslav@486
   197
            if (line == null) {
jaroslav@486
   198
                break;
jaroslav@486
   199
            }
jaroslav@486
   200
            if (line.endsWith(className)) {
jaroslav@486
   201
                modified = true;
jaroslav@334
   202
                continue;
jaroslav@334
   203
            }
jaroslav@486
   204
            arr.add(line);
jaroslav@486
   205
        }
jaroslav@486
   206
        r.close();
jaroslav@486
   207
        
jaroslav@486
   208
        if (modified) {
jaroslav@486
   209
            if (arr.isEmpty()) {
jaroslav@486
   210
                f.delete();
jaroslav@486
   211
            } else {
jaroslav@486
   212
                FileWriter w = new FileWriter(f);
jaroslav@486
   213
                for (String l : arr) {
jaroslav@486
   214
                    w.write(l);
jaroslav@486
   215
                    w.write("\n");
jaroslav@334
   216
                }
jaroslav@486
   217
                w.close();
jaroslav@334
   218
            }
jaroslav@334
   219
        }
jaroslav@331
   220
    }
jaroslav@331
   221
}