/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, 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.test.server.profileservice.support;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jboss.profileservice.spi.ProfileKey;
import org.jboss.profileservice.spi.metadata.ProfileMetaData;
import org.jboss.profileservice.spi.metadata.SubProfileMetaData;
import org.jboss.system.server.profile.repository.metadata.FilteredProfileMetaData;
import org.jboss.system.server.profile.repository.metadata.HotDeploymentProfileMetaData;
import org.jboss.system.server.profile.repository.metadata.ProfilesMetaData;
import org.jboss.system.server.profileservice.repository.AbstractBootstrapProfileFactory;
import org.jboss.virtual.VFS;
import org.jboss.virtual.VirtualFile;
import org.jboss.xb.binding.JBossXBException;
import org.jboss.xb.binding.Unmarshaller;
import org.jboss.xb.binding.UnmarshallerFactory;
import org.jboss.xb.binding.sunday.unmarshalling.DefaultSchemaResolver;
/**
* A profile factory based which generates the ProfileMetaData based on .xml files.
*
* @author <a href="mailto:emuckenh@redhat.com">Emanuel Muckenhuber</a>
* @version $Revision: 87932 $
*/
public class XmlProfileFactory extends AbstractBootstrapProfileFactory
{
/** The profiles directory name. */
public final static String PROFILES_SUFFIX = ".profile";
/** The attachment store uri. */
private File attachmentStoreRoot;
/** Profile directories */
private Collection<VirtualFile> profileDirectories;
/** The unmarshaller. */
private Unmarshaller unmarshaller;
/** The parsed file list */
private Collection<ProfileKey> processedProfileKeys = new ArrayList<ProfileKey>();
/** The default schema resolver. */
private static final DefaultSchemaResolver resolver = new DefaultSchemaResolver();
static
{
// Add schema bindings
resolver.addClassBinding("urn:jboss:profileservice:profiles:1.0", ProfilesMetaData.class);
resolver.addClassBinding("urn:jboss:profileservice:profile:filtered:1.0", FilteredProfileMetaData.class);
resolver.addClassBinding("urn:jboss:profileservice:profile:hotdeployment:1.0", HotDeploymentProfileMetaData.class);
}
public XmlProfileFactory(URI[] profileDirectories) throws Exception
{
if(profileDirectories == null)
throw new IllegalArgumentException("Null directories");
this.profileDirectories = new ArrayList<VirtualFile>();
for(URI uri : profileDirectories)
{
VirtualFile vf = VFS.getRoot(uri);
if(vf == null)
throw new IllegalArgumentException("Could not find uri: " + vf);
if(vf.isLeaf())
throw new IllegalArgumentException("Not a directory: " + vf);
this.profileDirectories.add(vf);
}
}
public Collection<VirtualFile> getProfileDirectories()
{
return profileDirectories;
}
public void setProfileDirectories(Collection<VirtualFile> profileDirectories)
{
this.profileDirectories = profileDirectories;
}
public File getAttachmentStoreRoot()
{
return attachmentStoreRoot;
}
public void setAttachmentStoreRoot(File attachmentStoreRoot)
{
this.attachmentStoreRoot = attachmentStoreRoot;
}
/**
* Create the profile meta data.
*
* @param rootKey the key of the profile/
* @param the url pointing to the profile file.
* @throws Exception
*/
@Override
protected void createProfileMetaData(ProfileKey rootKey, URL url) throws Exception
{
// Create the unmarshaller
this.unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
// Get the root profile virtual file
VirtualFile vf = getProfileFile(rootKey, url);
// Parse
ProfilesMetaData rootProfiles = parse(vf);
// Process
processProfilesMetaData(rootProfiles);
}
/**
* process the profile meta data.
*
* @param metaData the profile meta data.
* @throws Exception
*/
protected void processProfileMetaData(ProfileMetaData metaData) throws Exception
{
// Create profileKey
ProfileKey key = createProfileKey(metaData);
processProfileMetaData(key, metaData);
}
/**
* process the profile meta data
*
* @param key the profile key.
* @param metaData the meta data.
*
* @throws Exception
*/
protected void processProfileMetaData(ProfileKey key, ProfileMetaData metaData) throws Exception
{
// Don't process the same key twice
if(this.processedProfileKeys.contains(key))
return;
// Add profile meta data
addProfile(key, metaData);
// Process sub profiles
processSubProfiles(key, metaData);
}
/**
* process the sub profiles.
*
* @param key the profile key.
* @param metaData the profile meta data
* @throws Exception
*/
protected void processSubProfiles(ProfileKey key, ProfileMetaData metaData) throws Exception
{
if(metaData.getSubprofiles() != null && metaData.getSubprofiles().isEmpty() == false)
{
for(SubProfileMetaData subProfile : metaData.getSubprofiles())
{
ProfileKey subProfileKey = createProfileKey(subProfile);
processSubProfileMetaData(subProfileKey, subProfile);
}
}
}
/**
* process the sub profile.
*
* @param key the sub profile key.
* @param metaData the sub profile meta data.
* @throws Exception
*/
protected void processSubProfileMetaData(ProfileKey key, SubProfileMetaData metaData) throws Exception
{
// get file
VirtualFile vf = getProfileFile(key, null);
// parse
ProfilesMetaData profiles = parse(vf);
// TODO maybe override the profiles key (as it should be the same - filename and profiles name
// processProfilesMetaData(key, profiles);
processProfilesMetaData(profiles);
}
/**
* process the profiles meta data.
*
* @param key the profiles key.
* @param metaData the profiles meta data.
* @throws Exception
*/
protected void processProfilesMetaData(ProfileKey key, ProfilesMetaData metaData) throws Exception
{
if(metaData.getProfiles() != null && metaData.getProfiles().isEmpty() == false)
{
for(ProfileMetaData profile : metaData.getProfiles())
{
processProfileMetaData(profile);
}
}
// Add the profiles for later resolution
addProfiles(key, metaData.getProfiles());
}
/**
* Process the <profiles> meta data.
* This will add dependencies based on the ordering of the xml.
*
* @param profilesMetaData the profiles meta data
*/
protected void processProfilesMetaData(ProfilesMetaData profilesMetaData) throws Exception
{
// The <profiles> key
ProfileKey profilesKey = createProfileKey(profilesMetaData);
processProfilesMetaData(profilesKey, profilesMetaData);
}
/**
* get the virtual file of the profile.
*
* @param key the profile key.
* @param url the url pointing to the file
* @return a resolved name if the url is null.
*
* @throws Exception
*/
protected VirtualFile getProfileFile(ProfileKey key, URL url) throws Exception
{
if(url != null)
return VFS.getRoot(url);
else
return resolveFile(key.getName());
}
/**
* Try to resolve the profile name.
*
* @param name the profile name.
* @return the virtual file
* @throws Exception
*/
protected VirtualFile resolveFile(String name) throws Exception
{
// ProfileKey.getName() + .profile
if(name.endsWith(PROFILES_SUFFIX) == false)
name = name + PROFILES_SUFFIX;
VirtualFile vf = null;
for(VirtualFile dir : profileDirectories)
{
vf = dir.getChild(name);
if(vf != null)
break;
}
if(vf == null)
throw new FileNotFoundException("Could not find profile configuration file for: " + name);
return vf;
}
/**
* Parse a profile file.
*
* @param vf the virtual file.
* @return the <profiles> meta data
* @throws JBossXBException
* @throws IOException
*/
protected ProfilesMetaData parse(VirtualFile vf) throws JBossXBException, IOException
{
if(log.isTraceEnabled())
log.trace("parsing file: " + vf.getPathName());
return (ProfilesMetaData) unmarshaller.unmarshal(vf.openStream(), resolver);
}
@Override
protected void addProfile(ProfileKey key, ProfileMetaData metaData)
{
// Add to processed keys
processedProfileKeys.add(key);
// Add to parent
super.addProfile(key, metaData);
}
@Override
protected void addProfiles(ProfileKey key, List<ProfileMetaData> metaData)
{
// Add to processed keys
processedProfileKeys.add(key);
// Add to pared
super.addProfiles(key, metaData);
}
}