blob: 63d68e5c1f750974c3b4544a048c9ba9c536c9b6 [file] [log] [blame]
/*
* 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.apache.myfaces.extensions.scripting.core.engine;
import org.apache.myfaces.extensions.scripting.core.api.WeavingContext;
import org.apache.myfaces.extensions.scripting.core.common.util.ClassUtils;
import org.apache.myfaces.extensions.scripting.core.monitor.ClassResource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.util.logging.Level.SEVERE;
/**
* @author Werner Punz (latest modification by $Author$)
* @version $Revision$ $Date$
*/
public class ThrowAwayClassloader extends ClassLoader
{
static final Logger _logger = Logger.getLogger(ThrowAwayClassloader.class.getName());
boolean _untaint = true;
public ThrowAwayClassloader(ClassLoader classLoader, boolean untaint)
{
super(classLoader);
_untaint = untaint;
}
public ThrowAwayClassloader(ClassLoader classLoader)
{
super(classLoader);
}
public ThrowAwayClassloader()
{
}
@Override
protected Class<?> findClass(String s) throws ClassNotFoundException
{
return super.findClass(s);
}
@Override
protected synchronized Class<?> loadClass(String s, boolean b) throws ClassNotFoundException
{
return super.loadClass(s, b);
}
@Override
/**
* load called either if the class is not loaded at all
* or if the class has been recompiled (check upfront)
*/
public Class<?> loadClass(String className) throws ClassNotFoundException
{
ClassResource res = (ClassResource) WeavingContext.getInstance().getResource(className);
if (res == null) return super.loadClass(className);
if (!res.isTainted() && res.getAClass() != null) return res.getAClass();
File target = resolveClassFile(className);
//a load must happen anyway because the target was recompiled
int fileLength;
byte[] fileContent;
FileInputStream iStream = null;
//we cannot load while a compile is in progress
//we have to wait until it is one
try
{
fileLength = (int) target.length();
fileContent = new byte[fileLength];
iStream = new FileInputStream(target);
int result = iStream.read(fileContent);
_logger.log(Level.FINER, "read {0} bytes", String.valueOf(result));
}
catch (FileNotFoundException e)
{
throw new ClassNotFoundException(e.toString());
}
catch (IOException e)
{
throw new ClassNotFoundException(e.toString());
}
finally
{
if (iStream != null)
{
try
{
iStream.close();
}
catch (Exception e)
{
Logger log = Logger.getLogger(this.getClass().getName());
log.log(SEVERE, "", e);
}
}
}
//here we use trick17 we can store as many classes of the same name
//as long as we store with a new classloader every time it needs refresh
//we need to do it because the classloader can call itself recursively
//TODO we might run into issues here with inner classes
Class retVal;
if (res != null) {
retVal = (new ThrowAwayClassloader(getParent(),_untaint)).defineClass(className, fileContent, 0, fileLength);
if(_untaint) {
res.setAClass(retVal);
res.setTainted(false);
}
} else {
retVal = super.defineClass(className, fileContent, 0, fileLength);
}
return retVal;
}
@Override
public InputStream getResourceAsStream(String name)
{
File resource = new File(WeavingContext.getInstance().getConfiguration().getCompileTarget().getAbsolutePath()+File
.separator+name); //resolveClassFile(name);
if (resource.exists())
{
try
{
return new FileInputStream(resource);
}
catch (FileNotFoundException e)
{
return super.getResourceAsStream(name);
}
}
return super.getResourceAsStream(name);
}
private File resolveClassFile(String name)
{
return ClassUtils.classNameToFile(WeavingContext.getInstance().getConfiguration().getCompileTarget()
.getAbsolutePath
(), name);
}
}