/*
* JBoss, Home of Professional Open Source.
* Copyright 2007, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.deployers.vfs.plugins.structure;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Arrays;
import org.jboss.deployers.structure.spi.DeploymentUnit;
import org.jboss.deployers.structure.spi.helpers.AbstractDeploymentContext;
import org.jboss.deployers.vfs.spi.structure.VFSDeploymentContext;
import org.jboss.deployers.vfs.spi.structure.VFSDeploymentResourceLoader;
import org.jboss.logging.Logger;
import org.jboss.virtual.VFSUtils;
import org.jboss.virtual.VirtualFile;
/**
* AbstractVFSDeploymentContext.
*
* @author <a href="adrian@jboss.org">Adrian Brock</a>
* @author <a href="ales.justin@jboss.org">Ales Justin</a>
* @version $Revision: 1.1 $
*/
public class AbstractVFSDeploymentContext extends AbstractDeploymentContext implements VFSDeploymentContext
{
/** The serialVersionUID */
private static final long serialVersionUID = 4474515937180482776L;
/** The log */
private static final Logger log = Logger.getLogger(AbstractVFSDeploymentContext.class);
/** The root virtual file */
private VirtualFile root;
/** The meta data locations */
private List<VirtualFile> metaDataLocations;
/** The class paths */
private List<VirtualFile> classPath;
/** The loader */
private transient VFSDeploymentResourceLoader loader;
/**
* Get the vfs file name safely
*
* @param root the virutal file
* @return the name
*/
static final String safeVirtualFileName(VirtualFile root)
{
if (root == null)
throw new IllegalArgumentException("Null root");
try
{
return root.toURI().toString();
}
catch (Exception e)
{
return root.getName();
}
}
/**
* For serialization
*/
public AbstractVFSDeploymentContext()
{
}
/**
* Create a new AbstractVFSDeploymentContext.
*
* @param name the name
* @param simpleName the simple name
* @param root the virtual file
* @param relativePath the relative path
*/
public AbstractVFSDeploymentContext(String name, String simpleName, VirtualFile root, String relativePath)
{
super(name, simpleName, relativePath);
this.root = root;
}
/**
* Create a new AbstractVFSDeploymentContext.
*
* @param root the virtual file
* @param relativePath the relative path
*/
public AbstractVFSDeploymentContext(VirtualFile root, String relativePath)
{
super(safeVirtualFileName(root), root.getName(), relativePath);
this.root = root;
}
public VirtualFile getRoot()
{
return root;
}
public void setMetaDataPath(List<String> paths)
{
if (paths == null)
{
setMetaDataLocations(null);
return;
}
try
{
List<VirtualFile> locations = new ArrayList<VirtualFile>();
for (String path : paths)
{
if (path == null)
throw new IllegalArgumentException("Null path in paths: " + paths);
VirtualFile child = root.getChild(path);
if (child != null)
locations.add(child);
else
log.debug("Meta data path does not exist: root=" + root.getPathName() + " path=" + path);
}
setMetaDataLocations(locations);
}
catch (IOException e)
{
log.warn("Exception while applying paths: root=" + root.getPathName() + " paths=" + paths);
}
}
public List<VirtualFile> getMetaDataLocations()
{
if (metaDataLocations == null)
return Collections.emptyList();
return metaDataLocations;
}
public void setMetaDataLocations(List<VirtualFile> locations)
{
this.metaDataLocations = locations;
}
public VirtualFile getMetaDataFile(String name)
{
if (name == null)
throw new IllegalArgumentException("Null name");
try
{
// There isn't a metadata locations so let's see whether the root matches.
if (metaDataLocations == null || metaDataLocations.isEmpty())
{
// It has to be a plain file
if (root != null && SecurityActions.isLeaf(root))
{
String fileName = root.getName();
if (fileName.equals(name))
return root;
}
// No match
return null;
}
// Look in the meta data locations
return searchMetaDataLocations(name);
}
catch (Exception e)
{
if (log.isTraceEnabled())
log.trace("Error retrieving meta data: " + name + " reason=" + e);
return null;
}
}
/**
* Search the metadata locations.
* In this impl the first one matching is returned.
*
* @param name the file name to find
* @return found file or null if not found
*/
protected VirtualFile searchMetaDataLocations(String name)
{
VirtualFile result = null;
for(VirtualFile location : getMetaDataLocations())
{
try
{
result = location.getChild(name);
if (result != null)
{
if (log.isTraceEnabled())
log.trace("Found " + name + " in " + location.getName());
deployed();
break;
}
}
catch (IOException e)
{
log.debug("Search exception invocation for metafile " + name + " in " + location.getName() + ", reason: " + e);
}
}
return result;
}
public List<VirtualFile> getMetaDataFiles(String name, String suffix)
{
if (name == null && suffix == null)
throw new IllegalArgumentException("Null name and suffix");
try
{
// There isn't a metadata location so let's see whether the root matches.
// i.e. the top level is an xml
if (metaDataLocations == null || metaDataLocations.isEmpty())
{
// It has to be a plain file
if (root != null && SecurityActions.isLeaf(root))
{
String fileName = root.getName();
if (name != null && fileName.equals(name))
return Collections.singletonList(root);
if (suffix != null && fileName.endsWith(suffix))
return Collections.singletonList(root);
}
// No match
return Collections.emptyList();
}
// Look in the meta data location
List<VirtualFile> results = new ArrayList<VirtualFile>();
for (VirtualFile location : metaDataLocations)
{
List<VirtualFile> result = location.getChildren(new MetaDataMatchFilter(name, suffix));
if (result != null && result.isEmpty() == false)
{
if (log.isTraceEnabled())
log.trace("Found name=" + name + ", suffix=" + suffix + " in " + location.getName());
results.addAll(result);
deployed();
}
}
return results;
}
catch (Exception e)
{
log.debug("Error retrieving meta data: name=" + name + " suffix=" + suffix, e);
return Collections.emptyList();
}
}
public VirtualFile getFile(String name)
{
return getResourceLoader().getFile(name);
}
public List<VirtualFile> getClassPath()
{
return classPath;
}
public void setClassPath(List<VirtualFile> paths)
{
this.classPath = paths;
if (log.isTraceEnabled() && paths != null)
log.trace("ClassPath for " + root.getPathName() + " is " + VFSUtils.getPathsString(paths));
}
public void appendClassPath(List<VirtualFile> files)
{
if (files == null)
throw new IllegalArgumentException("Null files");
List<VirtualFile> classPath = getClassPath();
if (classPath == null)
classPath = new ArrayList<VirtualFile>();
for (VirtualFile file : files)
{
if (file == null)
throw new IllegalArgumentException("Null virtual file in " + files);
classPath.add(file);
}
setClassPath(classPath);
}
public void prependClassPath(VirtualFile... files)
{
if (files == null)
throw new IllegalArgumentException("Null files");
List<VirtualFile> classPath = getClassPath();
if (classPath == null)
classPath = new ArrayList<VirtualFile>();
for (int i = files.length-1; i >= 0; --i)
{
VirtualFile file = files[i];
if (file == null)
throw new IllegalArgumentException("Null virtual file in " + Arrays.toString(files));
classPath.add(0, file);
}
setClassPath(classPath);
}
public void prependClassPath(List<VirtualFile> files)
{
if (files == null)
throw new IllegalArgumentException("Null files");
List<VirtualFile> classPath = getClassPath();
if (classPath == null)
classPath = new ArrayList<VirtualFile>();
for (int i = files.size()-1; i >= 0; --i)
{
VirtualFile file = files.get(i);
if (file == null)
throw new IllegalArgumentException("Null virtual file in " + files);
classPath.add(0, file);
}
setClassPath(classPath);
}
public void appendClassPath(VirtualFile... files)
{
if (files == null)
throw new IllegalArgumentException("Null files");
List<VirtualFile> classPath = getClassPath();
if (classPath == null)
classPath = new ArrayList<VirtualFile>();
for (VirtualFile file : files)
{
if (file == null)
throw new IllegalArgumentException("Null virtual file in " + Arrays.toString(files));
classPath.add(file);
}
setClassPath(classPath);
}
@Override
public VFSDeploymentContext getTopLevel()
{
return (VFSDeploymentContext) super.getTopLevel();
}
@Override
public VFSDeploymentResourceLoader getResourceLoader()
{
if (loader != null)
return loader;
loader = new VFSDeploymentResourceLoaderImpl(getRoot());
return loader;
}
protected DeploymentUnit createDeploymentUnit()
{
return new AbstractVFSDeploymentUnit(this);
}
@SuppressWarnings("unchecked")
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
{
super.readExternal(in);
root = (VirtualFile) in.readObject();
boolean isNullOrEmpty = in.readBoolean();
if (isNullOrEmpty == false)
metaDataLocations = (List<VirtualFile>) in.readObject();
classPath = (List) in.readObject();
}
public void writeExternal(ObjectOutput out) throws IOException
{
super.writeExternal(out);
out.writeObject(root);
boolean isNullOrEmpty = metaDataLocations == null || metaDataLocations.isEmpty();
out.writeBoolean(isNullOrEmpty);
if (isNullOrEmpty == false)
out.writeObject(metaDataLocations);
out.writeObject(classPath);
}
}