WW-3984 Adds support for Convention plugin which based on actions in a Jar file embedded in Ear file on JBoss 5 server

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@1447442 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Lukasz Lenart
2013-02-18 19:13:44 +00:00
parent 44615af72b
commit e6e1976f39
5 changed files with 90 additions and 68 deletions
@@ -2,12 +2,14 @@ package org.apache.struts2.util.fs;
import com.opensymphony.xwork2.util.fs.DefaultFileManager;
import com.opensymphony.xwork2.util.fs.FileRevision;
import com.opensymphony.xwork2.util.fs.JarEntryRevision;
import com.opensymphony.xwork2.util.fs.Revision;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
@@ -45,7 +47,7 @@ public class JBossFileManager extends DefaultFileManager {
return true;
} catch (ClassNotFoundException e) {
if (LOG.isDebugEnabled()) {
LOG.debug("Cannot load [#0] class, not a JBoss 5!", VFS_JBOSS7);
LOG.debug("Cannot load [#0] class, not a JBoss 5!", VFS_JBOSS5);
}
return false;
}
@@ -70,7 +72,15 @@ public class JBossFileManager extends DefaultFileManager {
if (LOG.isDebugEnabled()) {
LOG.debug("Creating revision for URL: " + fileName);
}
Revision revision = FileRevision.build(normalizeToFileProtocol(fileUrl));
URL normalizedUrl = normalizeToFileProtocol(fileUrl);
Revision revision;
if ("file".equals(normalizedUrl.getProtocol())) {
revision = FileRevision.build(normalizedUrl);
} else if ("jar".equals(normalizedUrl.getProtocol())) {
revision = JarEntryRevision.build(normalizedUrl);
} else {
revision = Revision.build(normalizedUrl);
}
files.put(fileName, revision);
} else {
super.monitorFile(fileUrl);
@@ -122,43 +132,68 @@ public class JBossFileManager extends DefaultFileManager {
*/
protected URL getJBossPhysicalUrl(URL url) throws IOException {
Object content = url.openConnection().getContent();
try {
String s = content.getClass().toString();
if (s.startsWith("class org.jboss.vfs.VirtualFile")) { // JBoss 7 and probably 6
File physicalFile = readJBossPhysicalFile(content);
return physicalFile.toURI().toURL();
} else if (s.startsWith("class org.jboss.virtual.VirtualFile")) { // JBoss 5
String fileName = url.toExternalForm();
return new URL("file", null, fileName.substring(fileName.indexOf(":") + 1));
}
} catch (Exception e) {
LOG.warn("Error calling getPhysicalFile() on JBoss VirtualFile.", e);
String classContent = content.getClass().toString();
if (classContent.startsWith("class org.jboss.vfs.VirtualFile")) { // JBoss 7 and probably 6
File physicalFile = readJBossPhysicalFile(content);
return physicalFile.toURI().toURL();
} else if (classContent.startsWith("class org.jboss.virtual.VirtualFile")) { // JBoss 5
return readJBoss5Url(content);
}
return url;
}
private File readJBossPhysicalFile(Object content) throws Exception {
Method method = content.getClass().getDeclaredMethod("getPhysicalFile");
return (File) method.invoke(content);
}
private List<URL> getAllJBossPhysicalUrls(URL url) throws IOException {
List<URL> urls = new ArrayList<URL>();
Object content = url.openConnection().getContent();
try {
if (content.getClass().toString().startsWith("class org.jboss.vfs.VirtualFile")) {
File physicalFile = readJBossPhysicalFile(content);
String classContent = content.getClass().toString();
if (classContent.startsWith("class org.jboss.vfs.VirtualFile")) {
File physicalFile = readJBossPhysicalFile(content);
if (physicalFile != null) {
readFile(urls, physicalFile);
readFile(urls, physicalFile.getParentFile());
} else {
urls.add(url);
}
} catch (Exception e) {
LOG.warn("Error calling getPhysicalFile() on JBoss VirtualFile!", e);
} else if (classContent.startsWith("class org.jboss.virtual.VirtualFile")) {
URL physicalUrl = readJBoss5Url(content);
if (physicalUrl != null) {
urls.add(physicalUrl);
}
} else {
urls.add(url);
}
return urls;
}
private File readJBossPhysicalFile(Object content) {
try {
Method method = content.getClass().getDeclaredMethod("getPhysicalFile");
return (File) method.invoke(content);
} catch (NoSuchMethodException e) {
LOG.error("Provided class content [#0] is not a JBoss VirtualFile, getPhysicalFile() method not found!", e, content.getClass().getSimpleName());
} catch (InvocationTargetException e) {
LOG.error("Cannot invoke getPhysicalFile() method!", e);
} catch (IllegalAccessException e) {
LOG.error("Cannot access getPhysicalFile() method!", e);
}
return null;
}
private URL readJBoss5Url(Object content) {
try {
Method method = content.getClass().getDeclaredMethod("getHandler");
method.setAccessible(true);
Object handler = method.invoke(content);
method = handler.getClass().getMethod("getRealURL");
return (URL) method.invoke(handler);
} catch (NoSuchMethodException e) {
LOG.error("Provided class content [#0] is not a JBoss VirtualFile, getHandler() or getRealURL() method not found!", e, content.getClass().getSimpleName());
} catch (InvocationTargetException e) {
LOG.error("Cannot invoke getHandler() or getRealURL() method!", e);
} catch (IllegalAccessException e) {
LOG.error("Cannot access getHandler() or getRealURL() method!", e);
}
return null;
}
private void readFile(List<URL> urls, File physicalFile) throws MalformedURLException {
File[] files = physicalFile.listFiles();
if (physicalFile.isDirectory() && files != null) {
@@ -94,7 +94,7 @@ public class DefaultFileManager implements FileManager {
LOG.debug("Creating revision for URL: " + fileName);
}
if (isJarURL(fileUrl)) {
revision = JarEntryRevision.build(fileUrl, this);
revision = JarEntryRevision.build(normalizeToFileProtocol(fileUrl));
} else {
revision = FileRevision.build(fileUrl);
}
@@ -45,14 +45,6 @@ public class FileRevision extends Revision {
return file;
}
public void setLastModified(long lastModified) {
this.lastModified = lastModified;
}
public long getLastModified() {
return lastModified;
}
public boolean needsReloading() {
return this.lastModified < this.file.lastModified();
}
@@ -1,6 +1,5 @@
package com.opensymphony.xwork2.util.fs;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.io.FileUtils;
@@ -13,7 +12,7 @@ import java.util.zip.ZipEntry;
/**
* Represents jar resource revision, used for jar://* resource
*/
class JarEntryRevision extends Revision {
public class JarEntryRevision extends Revision {
private static Logger LOG = LoggerFactory.getLogger(JarEntryRevision.class);
@@ -24,28 +23,7 @@ class JarEntryRevision extends Revision {
private String fileNameInJar;
private long lastModified;
public JarEntryRevision(String jarFileName, String fileNameInJar, long lastModified) {
if ((jarFileName == null) || (fileNameInJar == null)) {
throw new IllegalArgumentException("JarFileName and FileNameInJar cannot be null");
}
this.jarFileName = jarFileName;
this.fileNameInJar = fileNameInJar;
this.lastModified = lastModified;
}
public boolean needsReloading() {
ZipEntry entry;
try {
JarFile jarFile = new JarFile(this.jarFileName);
entry = jarFile.getEntry(this.fileNameInJar);
} catch (IOException e) {
entry = null;
}
return entry != null && (lastModified < entry.getTime());
}
public static Revision build(URL fileUrl, FileManager fileManager) {
public static Revision build(URL fileUrl) {
// File within a Jar
// Find separator index of jar filename and filename within jar
String jarFileName = "";
@@ -66,19 +44,36 @@ class JarEntryRevision extends Revision {
int index = separatorIndex + JAR_FILE_NAME_SEPARATOR.length();
String fileNameInJar = fileName.substring(index).replaceAll("%20", " ");
URL url = fileManager.normalizeToFileProtocol(fileUrl);
if (url != null) {
JarFile jarFile = new JarFile(FileUtils.toFile(url));
ZipEntry entry = jarFile.getEntry(fileNameInJar);
return new JarEntryRevision(jarFileName.toString(), fileNameInJar, entry.getTime());
} else {
return null;
}
JarFile jarFile = new JarFile(FileUtils.toFile(fileUrl));
ZipEntry entry = jarFile.getEntry(fileNameInJar);
return new JarEntryRevision(jarFileName, fileNameInJar, entry.getTime());
} catch (Throwable e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not create JarEntryRevision for [" + jarFileName + "]!", e);
LOG.warn("Could not create JarEntryRevision for [#0]!", e, jarFileName);
}
return null;
}
}
private JarEntryRevision(String jarFileName, String fileNameInJar, long lastModified) {
if ((jarFileName == null) || (fileNameInJar == null)) {
throw new IllegalArgumentException("JarFileName and FileNameInJar cannot be null");
}
this.jarFileName = jarFileName;
this.fileNameInJar = fileNameInJar;
this.lastModified = lastModified;
}
public boolean needsReloading() {
ZipEntry entry;
try {
JarFile jarFile = new JarFile(this.jarFileName);
entry = jarFile.getEntry(this.fileNameInJar);
} catch (IOException e) {
entry = null;
}
return entry != null && (lastModified < entry.getTime());
}
}
@@ -7,7 +7,7 @@ import java.net.URL;
*/
public class Revision {
public Revision() {
protected Revision() {
}
public boolean needsReloading() {