001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.aspectj;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.StreamUtil;
021    
022    import java.io.File;
023    import java.io.FileOutputStream;
024    import java.io.IOException;
025    import java.io.InputStream;
026    
027    import java.net.URL;
028    import java.net.URLClassLoader;
029    
030    import java.security.ProtectionDomain;
031    
032    import java.util.Arrays;
033    
034    /**
035     * @author Shuyang Zhou
036     */
037    public class WeavingClassLoader extends URLClassLoader {
038    
039            public WeavingClassLoader(
040                    URL[] urls, Class<?>[] aspectClasses, File dumpDir) {
041    
042                    super(urls, null);
043    
044                    _dumpDir = dumpDir;
045    
046                    _urlWeavingAdaptor = new URLWeavingAdaptor(urls, aspectClasses);
047            }
048    
049            @Override
050            protected Class<?> findClass(String name) throws ClassNotFoundException {
051                    String resourcePath = name.replace('.', '/') + ".class";
052    
053                    InputStream inputStream = getResourceAsStream(resourcePath);
054    
055                    byte[] data = null;
056    
057                    try {
058                            if (inputStream == null) {
059    
060                                    // It may be a generated inner class
061    
062                                    data = _urlWeavingAdaptor.removeGeneratedClassDate(name);
063                            }
064                            else {
065                                    UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
066                                            new UnsyncByteArrayOutputStream();
067    
068                                    StreamUtil.transfer(
069                                            inputStream, unsyncByteArrayOutputStream, true);
070    
071                                    data = unsyncByteArrayOutputStream.toByteArray();
072                            }
073    
074                            if (data == null) {
075                                    throw new ClassNotFoundException(name);
076                            }
077    
078                            byte[] oldData = data;
079    
080                            data = _urlWeavingAdaptor.weaveClass(name, data, false);
081    
082                            if (Arrays.equals(oldData, data)) {
083                                    return _generateClass(name, data);
084                            }
085    
086                            if (_dumpDir != null) {
087                                    File dumpFile = new File(_dumpDir, resourcePath);
088    
089                                    File dumpDir = dumpFile.getParentFile();
090    
091                                    dumpDir.mkdirs();
092    
093                                    FileOutputStream fileOutputStream =
094                                            new FileOutputStream(dumpFile);
095    
096                                    fileOutputStream.write(data);
097    
098                                    fileOutputStream.close();
099    
100                                    if (_log.isInfoEnabled()) {
101                                            _log.info(
102                                                    "Woven class " + name + " result in " +
103                                                            dumpFile.getCanonicalPath());
104                                    }
105                            }
106                            else {
107                                    if (_log.isInfoEnabled()) {
108                                            _log.info("Woven class " + name);
109                                    }
110                            }
111    
112                            return _generateClass(name, data);
113                    }
114                    catch (IOException ioe) {
115                            throw new ClassNotFoundException(name, ioe);
116                    }
117            }
118    
119            private Class<?> _generateClass(String name, byte[] data) {
120                    Class<?> clazz = defineClass(
121                            name, data, 0, data.length, (ProtectionDomain)null);
122    
123                    String packageName = null;
124    
125                    int index = name.lastIndexOf('.');
126    
127                    if (index != -1) {
128                            packageName = name.substring(0, index);
129                    }
130    
131                    if (packageName != null) {
132                            Package pkg = getPackage(packageName);
133    
134                            if (pkg == null) {
135                                    definePackage(
136                                            packageName, null, null, null, null, null, null, null);
137                            }
138                    }
139    
140                    return clazz;
141            }
142    
143            private static Log _log = LogFactoryUtil.getLog(WeavingClassLoader.class);
144    
145            private File _dumpDir;
146            private URLWeavingAdaptor _urlWeavingAdaptor;
147    
148    }