Files
SCM-Manager/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java

776 lines
17 KiB
Java
Raw Normal View History

2010-10-31 19:22:53 +01:00
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
2010-10-12 09:16:40 +02:00
*/
2010-12-01 14:26:29 +01:00
package sonia.scm.plugin;
2010-10-12 09:16:40 +02:00
//~--- non-JDK imports --------------------------------------------------------
2014-01-03 12:56:18 +01:00
import com.github.legman.Subscribe;
import com.google.common.base.Predicate;
2012-09-29 21:44:39 +02:00
import com.google.common.io.Files;
2010-12-13 18:59:00 +01:00
import com.google.inject.Inject;
2010-12-16 07:46:02 +01:00
import com.google.inject.Provider;
2010-12-13 18:59:00 +01:00
import com.google.inject.Singleton;
2010-10-16 11:03:54 +02:00
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
2010-12-13 18:59:00 +01:00
import sonia.scm.ConfigurationException;
import sonia.scm.SCMContextProvider;
2011-02-12 10:52:04 +01:00
import sonia.scm.cache.Cache;
2010-12-13 18:59:00 +01:00
import sonia.scm.cache.CacheManager;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.config.ScmConfigurationChangedEvent;
2012-09-29 21:44:39 +02:00
import sonia.scm.io.ZipUnArchiver;
2011-05-09 12:12:20 +02:00
import sonia.scm.net.HttpClient;
2010-12-18 13:37:34 +01:00
import sonia.scm.util.AssertUtil;
2011-01-05 17:18:01 +01:00
import sonia.scm.util.IOUtil;
2010-12-16 07:46:02 +01:00
import sonia.scm.util.SecurityUtil;
import sonia.scm.util.SystemUtil;
2010-12-29 14:05:30 +01:00
import sonia.scm.util.Util;
import sonia.scm.version.Version;
2010-12-01 14:26:29 +01:00
2010-10-12 09:16:40 +02:00
//~--- JDK imports ------------------------------------------------------------
2012-09-29 21:44:39 +02:00
import java.io.File;
import java.io.IOException;
2011-01-05 17:18:01 +01:00
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
2011-01-05 17:18:01 +01:00
import java.net.URLEncoder;
2010-10-12 09:16:40 +02:00
2010-12-01 14:26:29 +01:00
import java.util.Collection;
2010-12-13 18:59:00 +01:00
import java.util.HashMap;
import java.util.HashSet;
2011-03-18 19:35:19 +01:00
import java.util.Iterator;
2010-12-18 16:25:57 +01:00
import java.util.LinkedHashSet;
2010-12-13 18:59:00 +01:00
import java.util.Map;
import java.util.Set;
2010-10-12 09:16:40 +02:00
2012-09-29 21:44:39 +02:00
import javax.xml.bind.JAXB;
2010-12-13 18:59:00 +01:00
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
2010-10-12 09:16:40 +02:00
/**
* TODO replace aether stuff
2010-10-12 09:16:40 +02:00
*
* @author Sebastian Sdorra
*/
2010-12-13 18:59:00 +01:00
@Singleton
public class DefaultPluginManager implements PluginManager
2010-10-12 09:16:40 +02:00
{
/** Field description */
2010-12-13 18:59:00 +01:00
public static final String CACHE_NAME = "sonia.cache.plugins";
2010-12-01 14:26:29 +01:00
/** Field description */
public static final String ENCODING = "UTF-8";
2010-12-01 14:26:29 +01:00
/** the logger for DefaultPluginManager */
2010-10-12 09:16:40 +02:00
private static final Logger logger =
2010-12-01 14:26:29 +01:00
LoggerFactory.getLogger(DefaultPluginManager.class);
2010-10-12 09:16:40 +02:00
/** enable or disable remote plugins */
private static final boolean REMOTE_PLUGINS_ENABLED = false;
2010-12-18 13:37:34 +01:00
/** Field description */
public static final Predicate<PluginInformation> FILTER_UPDATES =
new StatePluginPredicate(PluginState.UPDATE_AVAILABLE);
2010-12-18 13:37:34 +01:00
2010-12-01 14:26:29 +01:00
//~--- constructors ---------------------------------------------------------
2010-10-12 09:16:40 +02:00
/**
2010-12-01 14:26:29 +01:00
* Constructs ...
2010-10-12 09:16:40 +02:00
*
* @param context
2010-12-13 18:59:00 +01:00
* @param configuration
* @param pluginLoader
* @param cacheManager
2011-09-06 12:17:29 +02:00
* @param clientProvider
2010-10-12 09:16:40 +02:00
*/
2010-12-13 18:59:00 +01:00
@Inject
2012-09-29 21:44:39 +02:00
public DefaultPluginManager(SCMContextProvider context,
ScmConfiguration configuration, PluginLoader pluginLoader,
CacheManager cacheManager, Provider<HttpClient> clientProvider)
2010-10-12 09:16:40 +02:00
{
this.context = context;
2010-12-13 18:59:00 +01:00
this.configuration = configuration;
2014-01-09 20:06:07 +01:00
this.cache = cacheManager.getCache(CACHE_NAME);
2011-09-06 12:17:29 +02:00
this.clientProvider = clientProvider;
installedPlugins = new HashMap<>();
2010-12-13 18:59:00 +01:00
for (PluginWrapper wrapper : pluginLoader.getInstalledPlugins())
2010-12-13 18:59:00 +01:00
{
Plugin plugin = wrapper.getPlugin();
2010-12-13 18:59:00 +01:00
PluginInformation info = plugin.getInformation();
2010-12-16 07:46:02 +01:00
if ((info != null) && info.isValid())
2010-12-13 18:59:00 +01:00
{
2010-12-18 16:25:57 +01:00
installedPlugins.put(info.getId(), plugin);
2010-12-13 18:59:00 +01:00
}
}
2010-10-12 09:16:40 +02:00
2010-12-01 14:26:29 +01:00
try
2010-10-12 09:16:40 +02:00
{
2010-12-13 18:59:00 +01:00
unmarshaller =
JAXBContext.newInstance(PluginCenter.class).createUnmarshaller();
2010-12-01 14:26:29 +01:00
}
2010-12-13 18:59:00 +01:00
catch (JAXBException ex)
2010-12-01 14:26:29 +01:00
{
2010-12-13 18:59:00 +01:00
throw new ConfigurationException(ex);
2010-10-12 09:16:40 +02:00
}
}
2010-12-01 14:26:29 +01:00
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*/
@Override
public void clearCache()
{
2011-09-06 12:17:29 +02:00
if (logger.isDebugEnabled())
{
logger.debug("clear plugin cache");
}
cache.clear();
}
2011-09-06 12:17:29 +02:00
/**
* Method description
*
*
* @param config
*/
@Subscribe
public void configChanged(ScmConfigurationChangedEvent config)
2011-09-06 12:17:29 +02:00
{
clearCache();
}
2010-10-12 09:16:40 +02:00
/**
* Method description
*
*
2010-12-13 18:59:00 +01:00
* @param id
2010-10-12 09:16:40 +02:00
*/
2010-12-01 14:26:29 +01:00
@Override
2010-12-13 18:59:00 +01:00
public void install(String id)
2010-10-12 09:16:40 +02:00
{
SecurityUtil.assertIsAdmin();
2010-12-16 07:46:02 +01:00
2010-12-29 14:05:30 +01:00
PluginCenter center = getPluginCenter();
// pluginHandler.install(id);
2010-12-29 14:05:30 +01:00
for (PluginInformation plugin : center.getPlugins())
{
String pluginId = plugin.getId();
if (Util.isNotEmpty(pluginId) && pluginId.equals(id))
{
plugin.setState(PluginState.INSTALLED);
// ugly workaround
Plugin newPlugin = new Plugin();
// TODO check
// newPlugin.setInformation(plugin);
2010-12-29 14:05:30 +01:00
installedPlugins.put(id, newPlugin);
}
}
2010-12-13 18:59:00 +01:00
}
2010-12-01 14:26:29 +01:00
2012-09-29 21:44:39 +02:00
/**
* Method description
*
*
* @param packageStream
*
* @throws IOException
*/
@Override
public void installPackage(InputStream packageStream) throws IOException
{
2012-10-16 07:08:28 +02:00
SecurityUtil.assertIsAdmin();
2012-09-29 21:44:39 +02:00
File tempDirectory = Files.createTempDir();
try
{
new ZipUnArchiver().extractArchive(packageStream, tempDirectory);
Plugin plugin = JAXB.unmarshal(new File(tempDirectory, "plugin.xml"),
Plugin.class);
2012-09-30 09:43:11 +02:00
PluginCondition condition = plugin.getCondition();
if ((condition != null) &&!condition.isSupported())
{
throw new PluginConditionFailedException(condition);
}
2012-09-29 21:44:39 +02:00
/*
* AetherPluginHandler aph = new AetherPluginHandler(this, context,
* configuration);
* Collection<PluginRepository> repositories =
* Sets.newHashSet(new PluginRepository("package-repository",
* "file://".concat(tempDirectory.getAbsolutePath())));
*
* aph.setPluginRepositories(repositories);
*
* aph.install(plugin.getInformation().getId());
*/
2012-09-29 21:44:39 +02:00
plugin.getInformation().setState(PluginState.INSTALLED);
installedPlugins.put(plugin.getInformation().getId(), plugin);
}
finally
{
IOUtil.delete(tempDirectory);
}
}
2010-12-13 18:59:00 +01:00
/**
* Method description
*
*
* @param id
*/
@Override
public void uninstall(String id)
{
SecurityUtil.assertIsAdmin();
2010-12-16 07:46:02 +01:00
2010-12-18 16:25:57 +01:00
Plugin plugin = installedPlugins.get(id);
2011-09-09 12:26:31 +02:00
if (plugin == null)
{
String pluginPrefix = getPluginIdPrefix(id);
for (String nid : installedPlugins.keySet())
{
if (nid.startsWith(pluginPrefix))
{
id = nid;
plugin = installedPlugins.get(nid);
break;
}
}
}
2010-12-18 16:25:57 +01:00
if (plugin == null)
{
2010-12-18 18:21:21 +01:00
throw new PluginNotInstalledException(id.concat(" is not install"));
2010-12-18 16:25:57 +01:00
}
/*
* if (pluginHandler == null)
* {
* getPluginCenter();
* }
*
* pluginHandler.uninstall(id);
*/
2010-12-29 14:05:30 +01:00
installedPlugins.remove(id);
preparePlugins(getPluginCenter());
2010-10-12 09:16:40 +02:00
}
2010-12-18 13:37:34 +01:00
/**
* Method description
*
*
* @param id
*/
@Override
public void update(String id)
{
SecurityUtil.assertIsAdmin();
2010-12-18 13:37:34 +01:00
2010-12-18 18:21:21 +01:00
String[] idParts = id.split(":");
String groupId = idParts[0];
String artefactId = idParts[1];
PluginInformation installed = null;
for (PluginInformation info : getInstalled())
{
if (groupId.equals(info.getGroupId())
2012-09-29 21:44:39 +02:00
&& artefactId.equals(info.getArtifactId()))
2010-12-18 18:21:21 +01:00
{
installed = info;
break;
}
}
if (installed == null)
{
StringBuilder msg = new StringBuilder(groupId);
msg.append(":").append(groupId).append(" is not install");
throw new PluginNotInstalledException(msg.toString());
}
2010-12-29 14:08:31 +01:00
uninstall(installed.getId());
install(id);
2010-12-18 13:37:34 +01:00
}
2010-10-12 09:16:40 +02:00
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
2010-12-13 18:59:00 +01:00
* @param id
*
2010-10-12 09:16:40 +02:00
* @return
*/
2010-12-01 14:26:29 +01:00
@Override
2010-12-13 18:59:00 +01:00
public PluginInformation get(String id)
2010-10-12 09:16:40 +02:00
{
SecurityUtil.assertIsAdmin();
2010-12-16 07:46:02 +01:00
PluginInformation result = null;
for (PluginInformation info : getPluginCenter().getPlugins())
{
if (id.equals(info.getId()))
{
result = info;
break;
}
}
return result;
2010-10-12 09:16:40 +02:00
}
2010-12-18 13:37:34 +01:00
/**
* Method description
*
*
* @param predicate
2010-12-18 13:37:34 +01:00
*
* @return
*/
@Override
public Set<PluginInformation> get(Predicate<PluginInformation> predicate)
2010-12-18 13:37:34 +01:00
{
AssertUtil.assertIsNotNull(predicate);
SecurityUtil.assertIsAdmin();
2010-12-18 13:37:34 +01:00
Set<PluginInformation> infoSet = new HashSet<>();
2010-12-18 13:37:34 +01:00
filter(infoSet, getInstalled(), predicate);
filter(infoSet, getPluginCenter().getPlugins(), predicate);
2010-12-18 13:37:34 +01:00
return infoSet;
}
/**
* Method description
*
*
* @return
*/
@Override
public Collection<PluginInformation> getAll()
{
SecurityUtil.assertIsAdmin();
2010-12-18 13:37:34 +01:00
2010-12-18 16:25:57 +01:00
Set<PluginInformation> infoSet = getInstalled();
2010-12-18 13:37:34 +01:00
infoSet.addAll(getPluginCenter().getPlugins());
return infoSet;
}
2010-12-01 14:26:29 +01:00
/**
* Method description
*
*
2010-12-13 18:59:00 +01:00
* @return
2010-12-01 14:26:29 +01:00
*/
2010-12-13 18:59:00 +01:00
@Override
public Collection<PluginInformation> getAvailable()
2010-12-01 14:26:29 +01:00
{
SecurityUtil.assertIsAdmin();
2010-12-16 07:46:02 +01:00
Set<PluginInformation> availablePlugins = new HashSet<>();
Set<PluginInformation> centerPlugins = getPluginCenter().getPlugins();
for (PluginInformation info : centerPlugins)
{
if (!installedPlugins.containsKey(info.getId()))
{
availablePlugins.add(info);
}
}
return availablePlugins;
2010-12-01 14:26:29 +01:00
}
2010-12-18 13:37:34 +01:00
/**
* Method description
*
*
* @return
*/
@Override
2010-12-18 16:25:57 +01:00
public Set<PluginInformation> getAvailableUpdates()
2010-12-18 13:37:34 +01:00
{
SecurityUtil.assertIsAdmin();
2010-12-18 13:37:34 +01:00
return get(FILTER_UPDATES);
}
2010-10-12 09:16:40 +02:00
/**
* Method description
*
*
2010-12-13 18:59:00 +01:00
* @return
2010-10-12 09:16:40 +02:00
*/
2010-12-13 18:59:00 +01:00
@Override
2010-12-18 16:25:57 +01:00
public Set<PluginInformation> getInstalled()
2010-10-12 09:16:40 +02:00
{
SecurityUtil.assertIsAdmin();
2010-12-16 07:46:02 +01:00
Set<PluginInformation> infoSet = new LinkedHashSet<>();
2010-12-18 16:25:57 +01:00
for (Plugin plugin : installedPlugins.values())
{
infoSet.add(plugin.getInformation());
}
return infoSet;
2010-12-13 18:59:00 +01:00
}
2010-12-01 14:26:29 +01:00
2010-12-18 13:37:34 +01:00
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
*
* @param url
* @return
*/
private String buildPluginUrl(String url)
{
String os = SystemUtil.getOS();
String arch = SystemUtil.getArch();
try
{
os = URLEncoder.encode(os, ENCODING);
}
catch (UnsupportedEncodingException ex)
{
logger.error(ex.getMessage(), ex);
}
return url.replace("{version}", context.getVersion()).replace("{os}",
2012-09-29 21:44:39 +02:00
os).replace("{arch}", arch);
}
2010-12-18 13:37:34 +01:00
/**
* Method description
*
*
* @param target
* @param source
* @param predicate
2010-12-18 13:37:34 +01:00
*/
private void filter(Set<PluginInformation> target,
Collection<PluginInformation> source,
Predicate<PluginInformation> predicate)
2010-12-18 13:37:34 +01:00
{
for (PluginInformation info : source)
{
if (predicate.apply(info))
2010-12-18 13:37:34 +01:00
{
target.add(info);
}
}
}
/**
* Method description
*
*
* @param available
*/
private void preparePlugin(PluginInformation available)
{
PluginState state = PluginState.AVAILABLE;
2010-12-18 16:25:57 +01:00
for (PluginInformation installed : getInstalled())
2010-12-18 13:37:34 +01:00
{
if (isSamePlugin(available, installed))
{
if (installed.getVersion().equals(available.getVersion()))
{
2010-12-18 18:21:21 +01:00
state = PluginState.INSTALLED;
2010-12-18 13:37:34 +01:00
}
2011-01-28 17:41:11 +01:00
else if (isNewer(available, installed))
2010-12-18 13:37:34 +01:00
{
2010-12-18 18:21:21 +01:00
state = PluginState.UPDATE_AVAILABLE;
2010-12-18 13:37:34 +01:00
}
2011-01-28 17:41:11 +01:00
else
{
state = PluginState.NEWER_VERSION_INSTALLED;
}
2010-12-18 18:21:21 +01:00
break;
2010-12-18 13:37:34 +01:00
}
}
available.setState(state);
}
/**
* Method description
*
*
* @param pc
*/
private void preparePlugins(PluginCenter pc)
{
Set<PluginInformation> infoSet = pc.getPlugins();
if (infoSet != null)
{
2011-03-18 19:35:19 +01:00
Iterator<PluginInformation> pit = infoSet.iterator();
while (pit.hasNext())
2010-12-18 13:37:34 +01:00
{
2011-03-18 19:35:19 +01:00
PluginInformation available = pit.next();
if (isCorePluging(available))
{
pit.remove();
}
else
{
preparePlugin(available);
}
2010-12-18 13:37:34 +01:00
}
}
}
//~--- get methods ----------------------------------------------------------
2010-12-13 18:59:00 +01:00
/**
* Method description
*
*
* @return
*/
private PluginCenter getPluginCenter()
{
PluginCenter center = cache.get(PluginCenter.class.getName());
2010-10-12 09:16:40 +02:00
2010-12-13 18:59:00 +01:00
if (center == null)
{
synchronized (DefaultPluginManager.class)
2010-12-13 18:59:00 +01:00
{
String pluginUrl = configuration.getPluginUrl();
pluginUrl = buildPluginUrl(pluginUrl);
if (logger.isInfoEnabled())
{
logger.info("fetch plugin informations from {}", pluginUrl);
}
/**
* remote plugins are disabled for early 2.0.0-SNAPSHOTS
* TODO enable remote plugins later
*/
if (REMOTE_PLUGINS_ENABLED && Util.isNotEmpty(pluginUrl))
{
2011-01-05 17:18:01 +01:00
InputStream input = null;
2011-01-05 17:18:01 +01:00
try
{
2011-09-06 12:17:29 +02:00
input = clientProvider.get().get(pluginUrl).getContent();
/*
* TODO: add gzip support
*
* if (gzip)
* {
* input = new GZIPInputStream(input);
* }
*/
2011-01-05 17:18:01 +01:00
center = (PluginCenter) unmarshaller.unmarshal(input);
preparePlugins(center);
cache.put(PluginCenter.class.getName(), center);
/*
* if (pluginHandler == null)
* {
* pluginHandler = new AetherPluginHandler(this,
* SCMContext.getContext(), configuration,
* advancedPluginConfiguration);
* }
*
* pluginHandler.setPluginRepositories(center.getRepositories());
*/
2011-01-05 17:18:01 +01:00
}
catch (IOException | JAXBException ex)
2011-01-05 17:18:01 +01:00
{
logger.error("could not load plugins from plugin center", ex);
2011-01-05 17:18:01 +01:00
}
finally
{
IOUtil.close(input);
}
}
if (center == null)
{
center = new PluginCenter();
}
2010-12-13 18:59:00 +01:00
}
2010-10-12 09:16:40 +02:00
}
2010-12-13 18:59:00 +01:00
return center;
}
2010-12-01 14:26:29 +01:00
2011-09-09 12:26:31 +02:00
/**
* Method description
*
*
* @param pluginId
*
* @return
*/
private String getPluginIdPrefix(String pluginId)
{
return pluginId.substring(0, pluginId.lastIndexOf(':'));
2011-09-09 12:26:31 +02:00
}
2011-03-18 19:35:19 +01:00
/**
* Method description
*
*
* @param available
*
* @return
*/
private boolean isCorePluging(PluginInformation available)
{
boolean core = false;
for (Plugin installedPlugin : installedPlugins.values())
{
PluginInformation installed = installedPlugin.getInformation();
if (isSamePlugin(available, installed)
2012-09-29 21:44:39 +02:00
&& (installed.getState() == PluginState.CORE))
2011-03-18 19:35:19 +01:00
{
core = true;
break;
}
}
return core;
}
2011-01-28 17:41:11 +01:00
/**
* Method description
*
*
* @param available
* @param installed
*
* @return
*/
private boolean isNewer(PluginInformation available,
2012-09-29 21:44:39 +02:00
PluginInformation installed)
2011-01-28 17:41:11 +01:00
{
boolean result = false;
Version version = Version.parse(available.getVersion());
2011-01-28 17:41:11 +01:00
if (version != null)
{
2011-07-29 19:19:25 +02:00
result = version.isNewer(installed.getVersion());
2011-01-28 17:41:11 +01:00
}
return result;
}
2010-12-18 13:37:34 +01:00
/**
* Method description
*
*
* @param p1
* @param p2
*
* @return
*/
private boolean isSamePlugin(PluginInformation p1, PluginInformation p2)
{
return p1.getGroupId().equals(p2.getGroupId())
2012-09-29 21:44:39 +02:00
&& p1.getArtifactId().equals(p2.getArtifactId());
2010-12-18 13:37:34 +01:00
}
2010-10-12 09:16:40 +02:00
//~--- fields ---------------------------------------------------------------
/** Field description */
private final Cache<String, PluginCenter> cache;
2010-12-13 18:59:00 +01:00
2011-05-09 12:12:20 +02:00
/** Field description */
private final Provider<HttpClient> clientProvider;
2011-05-09 12:12:20 +02:00
2010-12-13 18:59:00 +01:00
/** Field description */
private final ScmConfiguration configuration;
2010-12-13 18:59:00 +01:00
/** Field description */
private final SCMContextProvider context;
2010-12-13 18:59:00 +01:00
/** Field description */
private final Map<String, Plugin> installedPlugins;
2010-12-13 18:59:00 +01:00
/** Field description */
private Unmarshaller unmarshaller;
2010-10-12 09:16:40 +02:00
}