XStreamPersister类用于加载目录和配置类对象,首先该类定义了一个接口。如下所示,那么这里需要注意的是HierarchicalStreamWriter是一个结构输出流,MarshallingContext是序列化上下文信息。具体的将还会在该类的其他函数与类中有使用。
private boolean unwrapNulls = true;
/** Callback interface or xstream persister. */
public static class Callback {
/** Return the CatalogInfo object being modified by the current request */
protected CatalogInfo getCatalogObject() {
return null;
}
/** Return the ServiceInfo object being modified by the current request */
protected ServiceInfo getServiceObject() {
return null;
}
/** Return the class of the object being acted upon by the current request */
protected Class extends Info> getObjectClass() {
return null;
}
protected void postEncodeWorkspace(
WorkspaceInfo ws, HierarchicalStreamWriter writer, MarshallingContext context) {}
protected void postEncodeNamespace(
NamespaceInfo ns, HierarchicalStreamWriter writer, MarshallingContext context) {}
protected void postEncodeDataStore(
DataStoreInfo ds, HierarchicalStreamWriter writer, MarshallingContext context) {}
protected void postEncodeCoverageStore(
CoverageStoreInfo ds,
HierarchicalStreamWriter writer,
MarshallingContext context) {}
protected void postEncodeFeatureType(
FeatureTypeInfo ds, HierarchicalStreamWriter writer, MarshallingContext context) {}
protected void postEncodeWMSLayer(
WMSLayerInfo ds, HierarchicalStreamWriter writer, MarshallingContext context) {}
protected void postEncodeWMTSLayer(
WMTSLayerInfo ds, HierarchicalStreamWriter writer, MarshallingContext context) {}
protected void postEncodeCoverage(
CoverageInfo ds, HierarchicalStreamWriter writer, MarshallingContext context) {}
protected void postEncodeLayer(
LayerInfo ls, HierarchicalStreamWriter writer, MarshallingContext context) {}
protected void postEncodeLayerGroup(
LayerGroupInfo ls, HierarchicalStreamWriter writer, MarshallingContext context) {}
protected void postEncodeReference(
Object obj,
String ref,
String prefix,
HierarchicalStreamWriter writer,
MarshallingContext context) {}
protected void postEncodeWMSStore(
WMSStoreInfo store, HierarchicalStreamWriter writer, MarshallingContext context) {}
protected void postEncodeWMTSStore(
WMTSStoreInfo store, HierarchicalStreamWriter writer, MarshallingContext context) {}
}
我们先来看一下该类的一些属性。
/** logging instance */
static Logger LOGGER = Logging.getLogger("org.geoserver");
/** internal xstream instance */
XStream xs;
/** GeoServer reference used to resolve references to gloal from services */
GeoServer geoserver;
/** Catalog reference, used to resolve references to stores, workspaces + namespaces */
Catalog catalog;
/** Callback instance. */
Callback callback;
/** Flag controlling how references to objects are encoded. */
boolean referenceByName = false;
/** The type map used in {@link BreifMapConverter} to handle complex objects */
Map> forwardBreifMap = new HashMap>();
Map, String> backwardBreifMap = new HashMap, String>();
private Level forceLevel = LOGGER.getLevel() == null ? Level.INFO : LOGGER.getLevel();
/** Flag controlling whether the persister should perform encryption on password fields */
boolean encryptPasswordFields = true;
接着是在构造函数中的Init方法。
/**
* Sets null handling in proxy objects. Defaults to unwrap. If set to false, proxy object are
* not transformed to nulls.
*/
public void setUnwrapNulls(boolean unwrapNulls) {
this.unwrapNulls = unwrapNulls;
}
protected void init(XStream xs) {
// Default implementations
initImplementationDefaults(xs);
// ignore unkonwn fields, this should help using data dirs that has new config elements
// with older versions of GeoServer
xs.ignoreUnknownElements();
// Aliases
xs.alias("global", GeoServerInfo.class);
xs.alias("settings", SettingsInfo.class);
xs.alias("logging", LoggingInfo.class);
xs.alias("jai", JAIInfo.class);
xs.alias("coverageAccess", CoverageAccessInfo.class);
xs.alias("catalog", Catalog.class);
xs.alias("namespace", NamespaceInfo.class);
xs.alias("workspace", WorkspaceInfo.class);
xs.alias("dataStore", DataStoreInfo.class);
xs.alias("wmsStore", WMSStoreInfo.class);
xs.alias("wmtsStore", WMTSStoreInfo.class);
xs.alias("coverageStore", CoverageStoreInfo.class);
xs.alias("style", StyleInfo.class);
xs.alias("legend", LegendInfo.class);
xs.alias("featureType", FeatureTypeInfo.class);
xs.alias("coverage", CoverageInfo.class);
xs.alias("wmsLayer", WMSLayerInfo.class);
xs.alias("wmtsLayer", WMTSLayerInfo.class);
xs.alias("coverageDimension", CoverageDimensionInfo.class);
xs.alias("coverageBand", CoverageBand.class);
xs.alias("inputCoverageBand", InputCoverageBand.class);
xs.alias("metadataLink", MetadataLinkInfo.class);
xs.alias("dataLink", DataLinkInfo.class);
xs.alias("attribute", AttributeTypeInfo.class);
xs.alias("layer", LayerInfo.class);
xs.alias("layerGroup", LayerGroupInfo.class);
xs.alias("published", PublishedInfo.class);
xs.alias("gridGeometry", GridGeometry2D.class);
xs.alias("projected", DefaultProjectedCRS.class);
xs.alias("attribution", AttributionInfo.class);
xs.aliasField("abstract", ResourceInfoImpl.class, "_abstract");
xs.alias("AuthorityURL", AuthorityURLInfo.class);
xs.alias("Identifier", LayerIdentifierInfo.class);
// GeoServerInfo
xs.omitField(impl(GeoServerInfo.class), "clientProperties");
xs.omitField(impl(GeoServerInfo.class), "geoServer");
xs.registerLocalConverter(
impl(GeoServerInfo.class), "metadata", new MetadataMapConverter());
// ServiceInfo
xs.omitField(impl(ServiceInfo.class), "clientProperties");
xs.omitField(impl(ServiceInfo.class), "geoServer");
xs.registerLocalConverter(
impl(ServiceInfo.class), "workspace", new ReferenceConverter(WorkspaceInfo.class));
xs.registerLocalConverter(impl(ServiceInfo.class), "metadata", new MetadataMapConverter());
xs.registerLocalConverter(impl(ServiceInfo.class), "keywords", new KeywordListConverter());
// Catalog
xs.omitField(impl(Catalog.class), "resourcePool");
xs.omitField(impl(Catalog.class), "resourceLoader");
xs.omitField(impl(Catalog.class), "listeners");
xs.omitField(impl(Catalog.class), "LOGGER");
xs.omitField(impl(DefaultCatalogFacade.class), "catalog");
xs.omitField(impl(DefaultCatalogFacade.class), "resources");
xs.omitField(impl(DefaultCatalogFacade.class), "layers");
xs.omitField(impl(DefaultCatalogFacade.class), "maps");
xs.omitField(impl(DefaultCatalogFacade.class), "layerGroups");
xs.registerLocalConverter(
DefaultCatalogFacade.class, "stores", new StoreMultiValueMapConverter());
xs.registerLocalConverter(
DefaultCatalogFacade.class, "namespaces", new SpaceMapConverter("namespace"));
xs.registerLocalConverter(
DefaultCatalogFacade.class, "workspaces", new SpaceMapConverter("workspace"));
// WorkspaceInfo
xs.omitField(impl(WorkspaceInfo.class), "_default");
xs.registerLocalConverter(
impl(WorkspaceInfo.class), "metadata", new MetadataMapConverter());
// NamespaceInfo
xs.omitField(impl(NamespaceInfo.class), "catalog");
xs.omitField(impl(NamespaceInfo.class), "_default");
xs.registerLocalConverter(
impl(NamespaceInfo.class), "metadata", new MetadataMapConverter());
// StoreInfo
xs.omitField(impl(StoreInfo.class), "catalog");
xs.omitField(impl(StoreInfo.class), "error");
// xs.omitField(StoreInfo.class), "workspace"); //handled by StoreInfoConverter
xs.registerLocalConverter(
impl(StoreInfo.class), "workspace", new ReferenceConverter(WorkspaceInfo.class));
xs.registerLocalConverter(
impl(StoreInfo.class), "connectionParameters", new BreifMapConverter());
xs.registerLocalConverter(impl(StoreInfo.class), "metadata", new MetadataMapConverter());
xs.registerLocalConverter(
impl(WMSStoreInfo.class), "password", new EncryptedFieldConverter());
xs.registerLocalConverter(
impl(WMTSStoreInfo.class), "password", new EncryptedFieldConverter());
// StyleInfo
xs.omitField(impl(StyleInfo.class), "catalog");
xs.registerLocalConverter(
impl(StyleInfo.class), "workspace", new ReferenceConverter(WorkspaceInfo.class));
xs.registerLocalConverter(impl(StyleInfo.class), "metadata", new MetadataMapConverter());
// ResourceInfo
xs.omitField(impl(ResourceInfo.class), "catalog");
xs.omitField(impl(ResourceInfo.class), "crs");
xs.registerLocalConverter(impl(ResourceInfo.class), "nativeCRS", new CRSConverter());
xs.registerLocalConverter(
impl(ResourceInfo.class), "store", new ReferenceConverter(StoreInfo.class));
xs.registerLocalConverter(
impl(ResourceInfo.class), "namespace", new ReferenceConverter(NamespaceInfo.class));
xs.registerLocalConverter(impl(ResourceInfo.class), "metadata", new MetadataMapConverter());
xs.registerLocalConverter(impl(ResourceInfo.class), "keywords", new KeywordListConverter());
// FeatureTypeInfo
PackageAliasingMapper bindingAliasingMapper =
new OneWayPackageAliasingMapper(
new DefaultMapper(new ClassLoaderReference(xs.getClassLoader())));
// For compatibility with JTS 1.15 and older bindings
bindingAliasingMapper.addPackageAlias(
"com.vividsolutions.jts.geom", "org.locationtech.jts.geom");
xs.registerLocalConverter(
impl(AttributeTypeInfo.class),
"binding",
(SingleValueConverter)
new SingleValueConverterWrapper(
new JavaClassConverter(bindingAliasingMapper) {}));
// CoverageInfo
xs.registerLocalConverter(
impl(CoverageInfo.class),
"supportedFormats",
new LaxCollectionConverter(xs.getMapper()));
xs.registerLocalConverter(
impl(CoverageInfo.class), "requestSRS", new LaxCollectionConverter(xs.getMapper()));
xs.registerLocalConverter(
impl(CoverageInfo.class),
"responseSRS",
new LaxCollectionConverter(xs.getMapper()));
xs.registerLocalConverter(
impl(CoverageInfo.class),
"interpolationMethods",
new LaxCollectionConverter(xs.getMapper()));
xs.registerLocalConverter(
impl(CoverageInfo.class), "dimensions", new LaxCollectionConverter(xs.getMapper()));
// CoverageDimensionInfo
xs.registerLocalConverter(
impl(CoverageDimensionInfo.class), "range", new NumberRangeConverter());
// AttributeTypeInfo
xs.omitField(impl(AttributeTypeInfo.class), "featureType");
xs.omitField(impl(AttributeTypeInfo.class), "attribute");
// LayerInfo
// xs.omitField( LayerInfo.class), "resource");
xs.registerLocalConverter(
impl(LayerInfo.class), "resource", new ReferenceConverter(ResourceInfo.class));
xs.registerLocalConverter(
impl(LayerInfo.class), "defaultStyle", new ReferenceConverter(StyleInfo.class));
xs.registerLocalConverter(
impl(LayerInfo.class), "styles", new ReferenceCollectionConverter(StyleInfo.class));
xs.registerLocalConverter(impl(LayerInfo.class), "metadata", new MetadataMapConverter());
// LayerGroupInfo
xs.registerLocalConverter(
impl(LayerGroupInfo.class),
"workspace",
new ReferenceConverter(WorkspaceInfo.class));
xs.registerLocalConverter(
impl(LayerGroupInfo.class), "rootLayer", new ReferenceConverter(LayerInfo.class));
xs.registerLocalConverter(
impl(LayerGroupInfo.class),
"rootLayerStyle",
new ReferenceConverter(StyleInfo.class));
xs.registerLocalConverter(
impl(LayerGroupInfo.class),
"layers",
new ReferenceCollectionConverter(LayerInfo.class));
xs.registerLocalConverter(
impl(LayerGroupInfo.class),
"publishables",
new ReferenceCollectionConverter(
PublishedInfo.class, LayerInfo.class, LayerGroupInfo.class));
xs.registerLocalConverter(
impl(LayerGroupInfo.class),
"styles",
new ReferenceCollectionConverter(StyleInfo.class));
xs.registerLocalConverter(
impl(LayerGroupInfo.class), "metadata", new MetadataMapConverter());
xs.registerLocalConverter(
impl(LayerGroupInfo.class), "keywords", new KeywordListConverter());
// ReferencedEnvelope
xs.registerLocalConverter(ReferencedEnvelope.class, "crs", new SRSConverter());
xs.registerLocalConverter(GeneralEnvelope.class, "crs", new SRSConverter());
// ServiceInfo
xs.registerConverter(new ServiceInfoConverter());
xs.omitField(impl(ServiceInfo.class), "geoServer");
// Converters
xs.registerConverter(new SpaceInfoConverter());
xs.registerConverter(new StoreInfoConverter());
xs.registerConverter(new ResourceInfoConverter());
xs.registerConverter(new FeatureTypeInfoConverter());
xs.registerConverter(new CoverageInfoConverter());
xs.registerConverter(new LayerInfoConverter());
xs.registerConverter(new LayerGroupInfoConverter());
xs.registerConverter(new GridGeometry2DConverter());
xs.registerConverter(new ProxyCollectionConverter(xs.getMapper()));
xs.registerConverter(new VirtualTableConverter());
xs.registerConverter(new KeywordInfoConverter());
xs.registerConverter(new SettingsInfoConverter());
xs.registerConverter(new WMSLayerInfoConverter());
// this should have been a metadata map too, but was not registered as such and got a plain
// map converter. Switched to SettingsTolerantMapConverter to make it work when plugins get
// removed and leave configuration that cannot be parsed anymore in there
xs.registerLocalConverter(
impl(SettingsInfo.class),
"metadata",
new SettingsTolerantMapConverter(xs.getMapper(), MetadataMap.class));
xs.registerConverter(new MeasureConverter());
xs.registerConverter(new MultimapConverter(xs.getMapper()));
// register Virtual structure handling
registerBreifMapComplexType("virtualTable", VirtualTable.class);
registerBreifMapComplexType("coverageView", CoverageView.class);
registerBreifMapComplexType("dimensionInfo", DimensionInfoImpl.class);
callback = new Callback();
// setup white list of accepted classes
xs.allowTypeHierarchy(Info.class);
xs.allowTypeHierarchy(Multimap.class);
xs.allowTypeHierarchy(JAIInfo.class);
xs.allowTypes(new Class[] {DynamicProxyMapper.DynamicProxy.class});
xs.allowTypes(new String[] {"java.util.Collections$SingletonList"});
xs.allowTypesByWildcard(new String[] {"org.geoserver.catalog.**"});
xs.allowTypesByWildcard(new String[] {"org.geoserver.security.**"});
}
那么这里需要注意的是xs.alias("global", GeoServerInfo.class),xs.omitField(impl(ServiceInfo.class), "clientProperties"),xs.registerLocalConverter(impl(ServiceInfo.class), "keywords", new KeywordListConverter());分别为别名设置,属性忽略,设置转换器。那么这里还需要注意几个函数,一个是加载,另外一个是保存函数,这些函数后面都将会使用得到。
/**
* Saves an object to persistence.
*
* @param obj The object to save.
* @param out The stream to save the object to.
*/
public void save(Object obj, OutputStream out) throws IOException {
// unwrap dynamic proxies
Object unwrapped = unwrapProxies(obj);
xs.toXML(unwrapped, new OutputStreamWriter(out, "UTF-8"));
}
/**
* Unwraps any proxies around the object.
*
* If the object is not being proxied it is passed back.
*/
public static Object unwrapProxies(Object obj) {
obj = SecureCatalogImpl.unwrap(obj);
obj = GeoServerImpl.unwrap(obj);
obj = CatalogImpl.unwrap(obj);
return obj;
}
/**
* Loads an object from peristence.
*
* @param in The input stream to read the object from.
* @param clazz The class of the expected object.
*/
public T load(InputStream in, Class clazz) throws IOException {
T obj = clazz.cast(xs.fromXML(in));
// call resolve() to ensure that any references created during loading
// get resolved to actual objects, for instance for links from datastores
// to workspaces
if (obj instanceof CatalogImpl) {
((CatalogImpl) obj).resolve();
}
return obj;
}
/**
* Builds a converter that will marshal/unmarshal the target class by reference, that is, by
* storing the object id as opposed to fully serializing it
*/
public ReferenceConverter buildReferenceConverter(Class clazz) {
return new ReferenceConverter(clazz);
}
/**
* Same as {@link #buildReferenceConverter(Class)}, but works against a collection of objects
*/
public ReferenceCollectionConverter buildReferenceCollectionConverter(Class clazz) {
return new ReferenceCollectionConverter(clazz);
}