工作空间有点类似于一个目录,而geoserver的工作空间是数据目录下的特定文件夹。创建工作空间的代码位于如下图的位置。
对应的新建工作区页面则如下图所示。
我们来看一下,创建的该页面的代码。WorkspaceNewPage.java的构造函数利用wickte来创建填写提交表单。
public WorkspaceNewPage() {
WorkspaceInfo ws = getCatalog().getFactory().createWorkspace();
form =
new Form<WorkspaceInfo>("form", new CompoundPropertyModel<WorkspaceInfo>(ws)) {
private static final long serialVersionUID = 6088042051374665053L;
@Override
protected void onSubmit() {
handleOnSubmit(form);
}
};
add(form);
TextField<String> nameTextField = new TextField<String>("name");
nameTextField.setRequired(true);
nameTextField.add(new XMLNameValidator());
nameTextField.add(
new StringValidator() {
private static final long serialVersionUID = -5475431734680134780L;
@Override
public void validate(IValidatable<String> validatable) {
if (CatalogImpl.DEFAULT.equals(validatable.getValue())) {
validatable.error(
new ValidationError("defaultWsError").addKey("defaultWsError"));
}
}
});
form.add(nameTextField.setRequired(true));
nsUriTextField = new TextField<String>("uri", new Model<String>());
// maybe a bit too restrictive, but better than not validation at all
nsUriTextField.setRequired(true);
nsUriTextField.add(new URIValidator());
form.add(nsUriTextField);
CheckBox defaultChk =
new CheckBox("default", new PropertyModel<Boolean>(this, "defaultWs"));
form.add(defaultChk);
// add checkbox for isolated workspaces
CheckBox isolatedChk = new CheckBox("isolated", new PropertyModel<>(ws, "isolated"));
if (!getCatalog().getCatalogCapabilities().supportsIsolatedWorkspaces()) {
// is isolated workspaces are not supported by the current catalog disable them
isolatedChk.setEnabled(false);
}
form.add(isolatedChk);
SubmitLink submitLink = new SubmitLink("submit", form);
form.add(submitLink);
form.setDefaultButton(submitLink);
AjaxLink<Void> cancelLink =
new AjaxLink<Void>("cancel") {
private static final long serialVersionUID = -1731475076965108576L;
@Override
public void onClick(AjaxRequestTarget target) {
doReturn(WorkspacePage.class);
}
};
form.add(cancelLink);
}
注意里面的表单提交后的回调函数handleOnSubmit,
private void handleOnSubmit(Form form) {
Catalog catalog = getCatalog();
// get the workspace information from the form
WorkspaceInfo workspace = (WorkspaceInfo) form.getModelObject();
NamespaceInfo namespace = catalog.getFactory().createNamespace();
namespace.setPrefix(workspace.getName());
namespace.setURI(nsUriTextField.getDefaultModelObjectAsString());
namespace.setIsolated(workspace.isIsolated());
// validate the workspace information adn associated namespace
if (!validateAndReport(() -> catalog.validate(workspace, true), form)
|| !validateAndReport(() -> catalog.validate(namespace, true), form)) {
// at least one validation fail
return;
}
// store the workspace and associated namespace in the catalog
try {
catalog.add(workspace);
catalog.add(namespace);
} catch (Exception exception) {
LOGGER.log(Level.INFO, "Error storing workspace related objects.", exception);
cleanAndReport(exception, form);
}
// let's see if we need to tag this workspace as the default one
if (defaultWs) {
catalog.setDefaultWorkspace(workspace);
}
doReturn(WorkspacePage.class);
}
catalog对工作空间进行了检校。然后再将工作空间和名字空间放到catalog中。检校函数主要做类似于是否名字重复等验证工作。函数如下所示。
private boolean validateAndReport(Supplier<ValidationResult> validation, Form form) {
// execute the validation
ValidationResult validationResult;
try {
validationResult = validation.get();
} catch (Exception exception) {
// the validation it self may fail, for example if the workspace already exists
LOGGER.log(Level.INFO, "Error validating workspace related objects.", exception);
form.error(exception.getMessage());
return false;
}
// if the validation was not successful report the found exceptions
if (!validationResult.isValid()) {
String message = validationResult.getErrosAsString(System.lineSeparator());
LOGGER.log(Level.INFO, message);
form.error(message);
return false;
}
// validation was successful
return true;
}
如果说出现两次名字重复的工作空间,那么会抛出异常。在代码中则会抛出这样的异常。
而对应的桌面则显示如下的红色警告。
好了,看完工作空间后,下面来看数据存储。
我们这里选择【栅格数据源】,当然这个展示界面还为我们提供其他的数据源,具体的没有一一去研究,可以参考一下代码。
public NewDataPage() {
final boolean thereAreWorkspaces = !getCatalog().getWorkspaces().isEmpty();
if (!thereAreWorkspaces) {
super.error(
(String) new ResourceModel("NewDataPage.noWorkspacesErrorMessage").getObject());
}
final Form storeForm = new Form("storeForm");
add(storeForm);
final ArrayList<String> sortedDsNames =
new ArrayList<String>(getAvailableDataStores().keySet());
Collections.sort(sortedDsNames);
final CatalogIconFactory icons = CatalogIconFactory.get();
final ListView dataStoreLinks =
new ListView("vectorResources", sortedDsNames) {
@Override
protected void populateItem(ListItem item) {
final String dataStoreFactoryName = item.getDefaultModelObjectAsString();
final DataAccessFactory factory =
getAvailableDataStores().get(dataStoreFactoryName);
final String description = factory.getDescription();
SubmitLink link;
link =
new SubmitLink("resourcelink") {
@Override
public void onSubmit() {
setResponsePage(
new DataAccessNewPage(dataStoreFactoryName));
}
};
link.setEnabled(thereAreWorkspaces);
link.add(new Label("resourcelabel", dataStoreFactoryName));
item.add(link);
item.add(new Label("resourceDescription", description));
Image icon = new Image("storeIcon", icons.getStoreIcon(factory.getClass()));
// TODO: icons could provide a description too to be used in alt=...
icon.add(new AttributeModifier("alt", new Model("")));
item.add(icon);
}
};
final List<String> sortedCoverageNames = new ArrayList<String>();
sortedCoverageNames.addAll(getAvailableCoverageStores().keySet());
Collections.sort(sortedCoverageNames);
final ListView coverageLinks =
new ListView("rasterResources", sortedCoverageNames) {
@Override
protected void populateItem(ListItem item) {
final String coverageFactoryName = item.getDefaultModelObjectAsString();
final Map<String, Format> coverages = getAvailableCoverageStores();
Format format = coverages.get(coverageFactoryName);
final String description = format.getDescription();
SubmitLink link;
link =
new SubmitLink("resourcelink") {
@Override
public void onSubmit() {
setResponsePage(
new CoverageStoreNewPage(coverageFactoryName));
}
};
link.setEnabled(thereAreWorkspaces);
link.add(new Label("resourcelabel", coverageFactoryName));
item.add(link);
item.add(new Label("resourceDescription", description));
Image icon = new Image("storeIcon", icons.getStoreIcon(format.getClass()));
// TODO: icons could provide a description too to be used in alt=...
icon.add(new AttributeModifier("alt", new Model("")));
item.add(icon);
}
};
final List<OtherStoreDescription> otherStores = getOtherStores();
final ListView otherStoresLinks =
new ListView("otherStores", otherStores) {
@Override
protected void populateItem(ListItem item) {
final OtherStoreDescription store =
(OtherStoreDescription) item.getModelObject();
SubmitLink link;
link =
new SubmitLink("resourcelink") {
@Override
public void onSubmit() {
setResponsePage(store.configurationPage);
}
};
link.setEnabled(thereAreWorkspaces);
link.add(
new Label(
"resourcelabel",
new ParamResourceModel(
"other." + store.key, NewDataPage.this)));
item.add(link);
item.add(
new Label(
"resourceDescription",
new ParamResourceModel(
"other." + store.key + ".description",
NewDataPage.this)));
Image icon = new Image("storeIcon", store.icon);
// TODO: icons could provide a description too to be used in alt=...
icon.add(new AttributeModifier("alt", new Model("")));
item.add(icon);
}
};
storeForm.add(dataStoreLinks);
storeForm.add(coverageLinks);
storeForm.add(otherStoresLinks);
}
栅格数据源则使用下面的函数展示出来。
/** @return the name/description set of available raster formats */
private Map<String, Format> getAvailableCoverageStores() {
if (coverages == null) {
Format[] availableFormats = GridFormatFinder.getFormatArray();
Map<String, Format> formatNames = new HashMap<String, Format>();
for (Format format : availableFormats) {
formatNames.put(format.getName(), format);
}
coverages = formatNames;
}
return coverages;
}
当点击数据源后,进入到如下的界面。
显然进入到一个page页面,而这里是对应CoverageStoreNewPage类。到选择好数据,并点击【保存】后,如下图进入到如的代码。
protected void onSave(final CoverageStoreInfo info, AjaxRequestTarget target)
throws IllegalArgumentException {
final Catalog catalog = getCatalog();
/*
* Try saving a copy of it so if the process fails somehow the original "info" does not end
* up with an id set
*/
CoverageStoreInfo expandedStore = getCatalog().getResourcePool().clone(info, true);
CoverageStoreInfo savedStore = catalog.getFactory().createCoverageStore();
// GR: this shouldn't fail, the Catalog.save(StoreInfo) API does not declare any action in
// case
// of a failure!... strange, why a save can't fail?
// Still, be cautious and wrap it in a try/catch block so the page does not blow up
try {
// GeoServer Env substitution; validate first
catalog.validate(expandedStore, false).throwIfInvalid();
// GeoServer Env substitution; force to *AVOID* resolving env placeholders...
savedStore = catalog.getResourcePool().clone(info, false);
// ... and save
catalog.save(savedStore);
} catch (RuntimeException e) {
LOGGER.log(Level.INFO, "Adding the store for " + info.getURL(), e);
throw new IllegalArgumentException(
"The coverage store could not be saved. Failure message: " + e.getMessage());
}
onSuccessfulSave(info, catalog, savedStore);
}
protected void onSuccessfulSave(
final CoverageStoreInfo info, final Catalog catalog, CoverageStoreInfo savedStore) {
// the StoreInfo save succeeded... try to present the list of coverages (well, _the_
// coverage while the getotools coverage api does not allow for more than one
NewLayerPage layerChooserPage;
CoverageStoreInfo expandedStore;
try {
expandedStore = catalog.getResourcePool().clone(savedStore, true);
// The ID is assigned by the catalog and therefore cannot be cloned
layerChooserPage = new NewLayerPage(savedStore.getId());
} catch (RuntimeException e) {
LOGGER.log(Level.INFO, "Getting list of coverages for saved store " + info.getURL(), e);
// doh, can't present the list of coverages, means saving the StoreInfo is meaningless.
try { // be extra cautious
catalog.remove(savedStore);
} catch (RuntimeErrorException shouldNotHappen) {
LOGGER.log(Level.WARNING, "Can't remove CoverageStoreInfo after adding it!", e);
}
// tell the caller why we failed...
throw new IllegalArgumentException(e.getMessage(), e);
}
setResponsePage(layerChooserPage);
}