@Test
  public void testUploadImageMosaic() throws Exception {
    URL zip = MockData.class.getResource("watertemp.zip");
    InputStream is = null;
    byte[] bytes;
    try {
      is = zip.openStream();
      bytes = IOUtils.toByteArray(is);
    } finally {
      IOUtils.closeQuietly(is);
    }

    MockHttpServletResponse response =
        putAsServletResponse(
            "/rest/workspaces/gs/coveragestores/watertemp/file.imagemosaic",
            bytes,
            "application/zip");
    assertEquals(201, response.getStatusCode());

    // check the response contents
    String content = response.getOutputStreamContent();
    Document d = dom(new ByteArrayInputStream(content.getBytes()));

    XMLAssert.assertXpathEvaluatesTo("watertemp", "//coverageStore/name", d);
    XMLAssert.assertXpathEvaluatesTo("ImageMosaic", "//coverageStore/type", d);

    // check the coverage is actually there
    CoverageStoreInfo storeInfo = getCatalog().getCoverageStoreByName("watertemp");
    assertNotNull(storeInfo);
    CoverageInfo ci = getCatalog().getCoverageByName("watertemp");
    assertNotNull(ci);
    assertEquals(storeInfo, ci.getStore());
  }
    @Override
    public void validate(IValidatable<String> validatable) {
      String vcName = validatable.getValue();

      final CoverageStoreInfo store = getCatalog().getStore(storeId, CoverageStoreInfo.class);
      List<CoverageInfo> coverages = getCatalog().getCoveragesByCoverageStore(store);
      for (CoverageInfo curr : coverages) {
        CoverageView currvc =
            curr.getMetadata().get(CoverageView.COVERAGE_VIEW, CoverageView.class);
        if (currvc != null) {
          if (coverageInfoId == null || !coverageInfoId.equals(curr.getId())) {
            if (currvc.getName().equals(vcName) && newCoverage) {
              Map<String, Object> map = new HashMap<>();
              map.put("name", vcName);
              map.put("coverageName", curr.getName());
              IValidationError err =
                  new ValidationError("duplicateCoverageViewName")
                      .addKey("duplicateCoverageViewName")
                      .setVariables(map);
              validatable.error(err);
              return;
            }
          }
        }
      }
    }
  @Test
  public void testSkipMisconfigured() throws Exception {
    // enable skipping of misconfigured layers
    GeoServerInfo global = getGeoServer().getGlobal();
    global.setResourceErrorHandling(ResourceErrorHandling.SKIP_MISCONFIGURED_LAYERS);
    getGeoServer().save(global);

    // manually misconfigure one layer
    CoverageInfo cvInfo = getCatalog().getCoverageByName(getLayerId(MockData.TASMANIA_DEM));
    ReferencedEnvelope BBox = cvInfo.getLatLonBoundingBox();
    try {
      cvInfo.setLatLonBoundingBox(null);
      getCatalog().save(cvInfo);

      // check we got everything but that specific layer, and that the output is still schema
      // compliant
      Document dom = getAsDOM(BASEPATH + "?request=GetCapabilities&service=WCS&version=1.1.1");
      checkValidationErrors(dom, WCS11_SCHEMA);
      // print(dom);
      int count = getCatalog().getCoverages().size();
      assertEquals(count - 2, dom.getElementsByTagName("wcs:CoverageSummary").getLength());
    } finally {
      cvInfo.setLatLonBoundingBox(BBox);
      getCatalog().save(cvInfo);
    }
  }
    /** @param cv */
    private void handleCoverageOfferingBrief(CoverageInfo cv) {
      if (cv.isEnabled()) {
        start("wcs:CoverageOfferingBrief");

        String tmp;

        for (MetadataLinkInfo mdl : cv.getMetadataLinks()) handleMetadataLink(mdl);

        tmp = cv.getDescription();

        if ((tmp != null) && (tmp != "")) {
          element("wcs:description", tmp);
        }

        tmp = cv.getPrefixedName();

        if ((tmp != null) && (tmp != "")) {
          element("wcs:name", tmp);
        }

        tmp = cv.getTitle();

        if ((tmp != null) && (tmp != "")) {
          element("wcs:label", tmp);
        }

        CoverageStoreInfo csinfo = cv.getStore();

        if (csinfo == null) {
          throw new WcsException(
              "Unable to acquire coverage store resource for coverage: " + cv.getName());
        }

        AbstractGridCoverage2DReader reader = null;
        try {
          reader =
              (AbstractGridCoverage2DReader)
                  catalog
                      .getResourcePool()
                      .getGridCoverageReader(csinfo, GeoTools.getDefaultHints());
        } catch (IOException e) {
          LOGGER.severe(
              "Unable to acquire a reader for this coverage with format: "
                  + csinfo.getFormat().getName());
        }

        if (reader == null)
          throw new WcsException(
              "Unable to acquire a reader for this coverage with format: "
                  + csinfo.getFormat().getName());

        DimensionInfo timeInfo = cv.getMetadata().get(ResourceInfo.TIME, DimensionInfo.class);
        ReaderDimensionsAccessor dimensions = new ReaderDimensionsAccessor(reader);
        handleEnvelope(cv.getLatLonBoundingBox(), timeInfo, dimensions);
        handleKeywords(cv.getKeywords());

        end("wcs:CoverageOfferingBrief");
      }
    }
Exemple #5
0
  public GridCoverageReader getCoverageReader() throws IOException {
    if (type != TYPE_RASTER) {
      throw new IllegalArgumentException("Layer type is not raster");
    }

    CoverageInfo resource = (CoverageInfo) layerInfo.getResource();
    return resource.getGridCoverageReader(null, GeoTools.getDefaultHints());
  }
  private LayerReference rasterLayer() throws IOException {
    Catalog catalog = getCatalog();
    CoverageInfo coverageInfo = catalog.getCoverageByName(RASTER_LAYER_NAME);
    GridCoverage2DReader reader;
    reader = (GridCoverage2DReader) coverageInfo.getGridCoverageReader(null, null);

    LayerReference layerReference = new LayerReference(RASTER_LAYER_NAME, reader);
    return layerReference;
  }
  @Test
  public void testModifyCoverage() throws Exception {
    testAddCoverage();

    NamespaceInfo ns = dao.getNamespaceByPrefix("acme");
    CoverageInfo ft = dao.getResourceByName(ns, "anvil", CoverageInfo.class);

    ft.setName("dynamite");
    dao.save(ft);

    assertNull(dao.getResourceByName(ns, "anvil", CoverageInfo.class));
    assertNotNull(dao.getResourceByName(ns, "dynamite", CoverageInfo.class));
  }
  private void configureCoverageInfo(
      CatalogBuilder builder, CoverageStoreInfo storeInfo, GridCoverage2DReader reader)
      throws Exception, IOException {
    // coverage read params
    final Map customParameters = new HashMap();

    CoverageInfo cinfo = builder.buildCoverage(reader, customParameters);

    // get the coverage name
    String name = reader.getGridCoverageNames()[0];
    cinfo.setName(name);
    cinfo.setNativeCoverageName(name);

    // add the store
    getCatalog().add(cinfo);
  }
  @Test
  public void testForceCoverage() throws Exception {
    // force the data to another projection
    Catalog catalog = getCatalog();
    CoverageInfo ci = catalog.getCoverageByName("usa");
    ci.setProjectionPolicy(ProjectionPolicy.FORCE_DECLARED);
    ci.setSRS("EPSG:3857");
    catalog.save(ci);

    ci = catalog.getCoverageByName("usa");
    assertEquals(ProjectionPolicy.FORCE_DECLARED, ci.getProjectionPolicy());
    assertEquals("EPSG:3857", ci.getSRS());

    // now get the reader via the coverage info
    AbstractGridCoverage2DReader r;
    r = (AbstractGridCoverage2DReader) ci.getGridCoverageReader(null, GeoTools.getDefaultHints());
    assertTrue(CRS.equalsIgnoreMetadata(CRS.decode("EPSG:3857"), r.getCrs()));

    // and again without any hint
    r = (AbstractGridCoverage2DReader) ci.getGridCoverageReader(null, null);
    assertTrue(CRS.equalsIgnoreMetadata(CRS.decode("EPSG:3857"), r.getCrs()));

    // get the reader straight: we should get back the native projection
    CoverageStoreInfo store = catalog.getCoverageStoreByName("usa");
    final ResourcePool rpool = catalog.getResourcePool();
    r =
        (AbstractGridCoverage2DReader)
            rpool.getGridCoverageReader(store, GeoTools.getDefaultHints());
    assertTrue(CRS.equalsIgnoreMetadata(CRS.decode("EPSG:4326"), r.getCrs()));
  }
  @Test
  public void testAddCoverage() throws Exception {
    testAddCoverageStore();
    testAddNamespace();

    CoverageStoreInfo ds =
        dao.getStoreByName(dao.getWorkspaceByName("acme"), "widgets", CoverageStoreInfo.class);
    NamespaceInfo ns = dao.getNamespaceByPrefix("acme");

    assertNull(dao.getResourceByName(ns, "anvil", CoverageInfo.class));

    CoverageInfo ft = dao.getCatalog().getFactory().createCoverage();
    ft.setName("anvil");
    ft.setNativeName("anvil");
    ft.setStore(ds);
    ft.setNamespace(ns);

    dao.add(ft);

    assertNotNull(dao.getResourceByName(ns, "anvil", CoverageInfo.class));
  }
  /**
   * Test that changing a datastore's workspace updates the datastore's "namespace" parameter as
   * well as the namespace of its previously configured resources
   */
  public void testWorkspaceSyncsUpWithNamespace() {
    final Catalog catalog = getCatalog();

    final FormTester formTester = tester.newFormTester("rasterStoreForm");

    final String wsDropdownPath = "rasterStoreForm:workspacePanel:border:paramValue";

    tester.assertModelValue(wsDropdownPath, catalog.getWorkspaceByName(MockData.WCS_PREFIX));

    // select the fifth item in the drop down, which is the cdf workspace
    formTester.select("workspacePanel:border:paramValue", 2);

    // weird on this test I need to both call form.submit() and also simulate clicking on the
    // ajax "save" link for the model to be updated. On a running geoserver instance it works ok
    // though
    formTester.submit();

    final boolean isAjax = true;
    tester.clickLink("rasterStoreForm:save", isAjax);

    // did the save finish normally?
    tester.assertRenderedPage(StorePage.class);

    CoverageStoreInfo store = catalog.getCoverageStore(coverageStore.getId());
    WorkspaceInfo workspace = store.getWorkspace();
    assertFalse(MockData.WCS_PREFIX.equals(workspace.getName()));

    // was the namespace for the datastore resources updated?
    List<CoverageInfo> resourcesByStore;
    resourcesByStore = catalog.getResourcesByStore(store, CoverageInfo.class);

    assertTrue(resourcesByStore.size() > 0);

    for (CoverageInfo cv : resourcesByStore) {
      assertEquals(
          "Namespace for " + cv.getName() + " was not updated",
          workspace.getName(),
          cv.getNamespace().getPrefix());
    }
  }
  @Test
  public void testMetadataLink() throws Exception {
    Catalog catalog = getCatalog();
    CoverageInfo ci = catalog.getCoverageByName(getLayerId(TASMANIA_DEM));
    MetadataLinkInfo ml = catalog.getFactory().createMetadataLink();
    ml.setContent("http://www.geoserver.org/tasmania/dem.xml");
    ml.setAbout("http://www.geoserver.org");
    ci.getMetadataLinks().add(ml);
    catalog.save(ci);

    Document dom = getAsDOM("wcs?request=GetCapabilities");
    // print(dom);
    checkValidationErrors(dom, WCS11_SCHEMA);
    String xpathBase =
        "//wcs:CoverageSummary[wcs:Identifier = '"
            + TASMANIA_DEM.getLocalPart()
            + "']/ows:Metadata";
    assertXpathEvaluatesTo("http://www.geoserver.org", xpathBase + "/@about", dom);
    assertXpathEvaluatesTo("simple", xpathBase + "/@xlink:type", dom);
    assertXpathEvaluatesTo(
        "http://www.geoserver.org/tasmania/dem.xml", xpathBase + "/@xlink:href", dom);
  }
Exemple #13
0
  public void validate(LayerInfo lyr, boolean isNew) {
    if (lyr.isEnabled() == false) {
      // short-circuit - for disabled layers we don't need to validate
      // anything because it won't cause service exceptions for anyone
      return;
    }

    if (lyr.getResource() == null
        || (hasGeometry(lyr)
            && (lyr.getResource().getSRS() == null
                || lyr.getResource().getLatLonBoundingBox() == null)))
      throw new RuntimeException("Layer's resource is not fully configured");

    // Resource-dependent checks
    if (lyr.getType() == PublishedType.RASTER) {
      if (!(lyr.getResource() instanceof CoverageInfo))
        throw new RuntimeException("Layer with type RASTER doesn't have a coverage associated");
      CoverageInfo cvinfo = (CoverageInfo) lyr.getResource();
      try {
        cvinfo
            .getCatalog()
            .getResourcePool()
            .getGridCoverageReader(cvinfo, GeoTools.getDefaultHints());
      } catch (Throwable t) {
        throw new RuntimeException("Couldn't connect to raster layer's resource");
      }
    } else if (lyr.getType() == PublishedType.VECTOR) {
      if (!(lyr.getResource() instanceof FeatureTypeInfo))
        throw new RuntimeException("Layer with type VECTOR doesn't have a featuretype associated");
      FeatureTypeInfo ftinfo = (FeatureTypeInfo) lyr.getResource();
    } else throw new RuntimeException("Layer is neither RASTER nor VECTOR type");

    // Style-dependent checks
    if (hasGeometry(lyr) && (lyr.getDefaultStyle() == null || lyr.getStyles().contains(null)))
      throw new RuntimeException("Layer has null styles!");
  }
  public MockCatalogBuilder coverage(QName qName, String fileName, String srs, Class scope) {
    scope = scope != null ? scope : getClass();

    String cId = newId();
    final CoverageStoreInfo cs = coverageStores.peekLast();
    NamespaceInfo ns = namespaces.peekLast();

    final String name = qName.getLocalPart();
    File dir = new File(dataDirRoot, name);
    dir.mkdir();

    try {
      IOUtils.copy(scope.getResourceAsStream(fileName), new File(dir, fileName));
    } catch (IOException e) {
      throw new RuntimeException(e);
    }

    // initialize the mock by actually building a real one first
    CatalogBuilder cb = new CatalogBuilder(new CatalogImpl());
    cb.setStore(cs);

    GridCoverage2DReader reader = cs.getFormat().getReader(cs.getURL());
    if (reader == null) {
      throw new RuntimeException("No reader for " + cs.getURL());
    }

    CoverageInfo real = null;
    try {
      real = cb.buildCoverage(reader, null);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }

    final CoverageInfo c = createNiceMock(CoverageInfo.class);
    coverages.add(c);
    final List<CoverageInfo> coverageList = coverages;

    if (srs == null) {
      srs = real.getSRS();
    }
    initResource(
        c,
        CoverageInfo.class,
        cId,
        name,
        cs,
        ns,
        srs,
        real.getProjectionPolicy(),
        real.getNativeBoundingBox(),
        real.getLatLonBoundingBox());

    expect(c.getDefaultInterpolationMethod())
        .andReturn(real.getDefaultInterpolationMethod())
        .anyTimes();
    expect(c.getDimensions()).andReturn(real.getDimensions()).anyTimes();
    expect(c.getGrid()).andReturn(real.getGrid()).anyTimes();

    expect(c.getInterpolationMethods()).andReturn(real.getInterpolationMethods()).anyTimes();
    expect(c.getRequestSRS()).andReturn(real.getRequestSRS()).anyTimes();
    expect(c.getResponseSRS()).andReturn(real.getResponseSRS()).anyTimes();

    try {
      expect(c.getGridCoverageReader(null, null)).andReturn(reader).anyTimes();
    } catch (IOException e) {
    }

    expect(catalog.getCoverageByName(or(eq(name), eq(ns.getPrefix() + ":" + name))))
        .andReturn(c)
        .anyTimes();
    expect(
            catalog.getCoverageByName(
                or(eq(new NameImpl(ns.getPrefix(), name)), eq(new NameImpl(ns.getURI(), name)))))
        .andReturn(c)
        .anyTimes();
    expect(catalog.getCoverageByName(ns, name)).andReturn(c).anyTimes();

    expect(catalog.getCoverageByName(ns.getPrefix(), name)).andReturn(c).anyTimes();
    // expect(catalog.getFeatureTypeByName(or(eq(ns.getPrefix()), eq(ns.getURI())), name))
    //    .andReturn(ft).anyTimes();

    // expect(catalog.getCoverageByStore(cs, name)).andReturn(c).anyTimes();
    expect(catalog.getCoveragesByStore(cs)).andReturn(coverageList).anyTimes();
    expect(catalog.getCoverageByCoverageStore(cs, name)).andReturn(c).anyTimes();

    c.accept((CatalogVisitor) anyObject());
    expectLastCall()
        .andAnswer(
            new VisitAnswer() {
              @Override
              protected void doVisit(CatalogVisitor visitor) {
                visitor.visit(c);
              }
            })
        .anyTimes();

    callback.onResource(name, c, cs, this);
    replay(c, createLayer(c, name, ns));
    return this;
  }
  public CoverageViewAbstractPage(
      String workspaceName, String storeName, String coverageName, CoverageInfo coverageInfo)
      throws IOException {
    storeId =
        getCatalog().getStoreByName(workspaceName, storeName, CoverageStoreInfo.class).getId();
    Catalog catalog = getCatalog();
    CoverageStoreInfo store = catalog.getStore(storeId, CoverageStoreInfo.class);

    GridCoverage2DReader reader =
        (GridCoverage2DReader) catalog.getResourcePool().getGridCoverageReader(store, null);
    String[] coverageNames = reader.getGridCoverageNames();
    if (availableCoverages == null) {
      availableCoverages = new ArrayList<String>();
    }
    for (String coverage : coverageNames) {
      ImageLayout layout = reader.getImageLayout(coverage);
      SampleModel sampleModel = layout.getSampleModel(null);
      final int numBands = sampleModel.getNumBands();
      if (numBands == 1) {
        // simple syntax for simple case
        availableCoverages.add(coverage);
      } else {
        for (int i = 0; i < numBands; i++) {
          availableCoverages.add(coverage + CoverageView.BAND_SEPARATOR + i);
        }
      }
    }
    Collections.sort(availableCoverages);
    name = COVERAGE_VIEW_NAME;
    if (coverageName != null) {
      newCoverage = false;

      // grab the coverage view
      coverageViewInfo =
          coverageInfo != null
              ? coverageInfo
              : catalog.getResourceByStore(store, coverageName, CoverageInfo.class);
      CoverageView coverageView =
          coverageViewInfo.getMetadata().get(CoverageView.COVERAGE_VIEW, CoverageView.class);
      // the type can be still not saved
      if (coverageViewInfo != null) {
        coverageInfoId = coverageViewInfo.getId();
      }
      if (coverageView == null) {
        throw new IllegalArgumentException(
            "The specified coverage does not have a coverage view attached to it");
      }
      outputBands = new ArrayList<CoverageBand>(coverageView.getCoverageBands());
      name = coverageView.getName();
    } else {
      outputBands = new ArrayList<CoverageBand>();
      newCoverage = true;
      coverageViewInfo = null;
    }
    selectedCoverages = new ArrayList<String>(availableCoverages);

    // build the form and the text area
    Form<CoverageViewAbstractPage> form = new Form<>("form", new CompoundPropertyModel<>(this));
    add(form);

    final TextField<String> nameField = new TextField<>("name");
    nameField.setRequired(true);
    nameField.add(new CoverageViewNameValidator());
    form.add(nameField);

    coverageEditor =
        new CoverageViewEditor(
            "coverages",
            new PropertyModel<>(this, "selectedCoverages"),
            new PropertyModel<>(this, "outputBands"),
            availableCoverages);
    form.add(coverageEditor);

    // save and cancel at the bottom of the page
    form.add(
        new SubmitLink("save") {
          @Override
          public void onSubmit() {
            onSave();
          }
        });
    form.add(
        new Link<Void>("cancel") {

          @Override
          public void onClick() {
            onCancel();
          }
        });
  }
Exemple #16
0
  /**
   * Returns the read parameters for the specified layer, merging some well known request parameters
   * into the read parameters if possible
   *
   * @param request
   * @param mapLayerInfo
   * @param layerFilter
   * @param reader
   * @return
   */
  public GeneralParameterValue[] getWMSReadParameters(
      final GetMapRequest request,
      final MapLayerInfo mapLayerInfo,
      final Filter layerFilter,
      final List<Object> times,
      final List<Object> elevations,
      final GridCoverage2DReader reader,
      boolean readGeom)
      throws IOException {
    // setup the scene
    final ParameterValueGroup readParametersDescriptor = reader.getFormat().getReadParameters();
    CoverageInfo coverage = mapLayerInfo.getCoverage();
    MetadataMap metadata = coverage.getMetadata();
    GeneralParameterValue[] readParameters =
        CoverageUtils.getParameters(readParametersDescriptor, coverage.getParameters(), readGeom);
    ReaderDimensionsAccessor dimensions = new ReaderDimensionsAccessor(reader);
    // pass down time
    final DimensionInfo timeInfo = metadata.get(ResourceInfo.TIME, DimensionInfo.class);
    // add the descriptors for custom dimensions
    final List<GeneralParameterDescriptor> parameterDescriptors =
        new ArrayList<GeneralParameterDescriptor>(
            readParametersDescriptor.getDescriptor().descriptors());
    Set<ParameterDescriptor<List>> dynamicParameters = reader.getDynamicParameters();
    parameterDescriptors.addAll(dynamicParameters);
    if (timeInfo != null && timeInfo.isEnabled()) {
      // handle "default"
      List<Object> fixedTimes = new ArrayList<Object>(times);
      for (int i = 0; i < fixedTimes.size(); i++) {
        if (fixedTimes.get(i) == null) {
          fixedTimes.set(i, getDefaultTime(coverage));
        }
      }
      // pass down the parameters
      readParameters =
          CoverageUtils.mergeParameter(
              parameterDescriptors, readParameters, fixedTimes, "TIME", "Time");
    }

    // pass down elevation
    final DimensionInfo elevationInfo = metadata.get(ResourceInfo.ELEVATION, DimensionInfo.class);
    if (elevationInfo != null && elevationInfo.isEnabled()) {
      // handle "default"
      List<Object> fixedElevations = new ArrayList<Object>(elevations);
      for (int i = 0; i < fixedElevations.size(); i++) {
        if (fixedElevations.get(i) == null) {
          fixedElevations.set(i, getDefaultElevation(coverage));
        }
      }
      readParameters =
          CoverageUtils.mergeParameter(
              parameterDescriptors, readParameters, fixedElevations, "ELEVATION", "Elevation");
    }

    if (layerFilter != null && readParameters != null) {
      // test for default [empty is replaced with INCLUDE filter] ]filter
      for (int i = 0; i < readParameters.length; i++) {

        GeneralParameterValue param = readParameters[i];
        GeneralParameterDescriptor pd = param.getDescriptor();

        if (pd.getName().getCode().equalsIgnoreCase("FILTER")) {
          final ParameterValue pv = (ParameterValue) pd.createValue();
          // if something different from the default INCLUDE filter is specified
          if (layerFilter != Filter.INCLUDE) {
            // override the default filter
            pv.setValue(layerFilter);
            readParameters[i] = pv;
          }
          break;
        }
      }
    }

    // custom dimensions

    List<String> customDomains = new ArrayList(dimensions.getCustomDomains());
    for (String domain : new ArrayList<String>(customDomains)) {
      List<String> values = request.getCustomDimension(domain);
      if (values != null) {
        readParameters =
            CoverageUtils.mergeParameter(parameterDescriptors, readParameters, values, domain);
        customDomains.remove(domain);
      }
    }

    // see if we have any custom domain for which we have to set the default value
    if (!customDomains.isEmpty()) {
      for (String name : customDomains) {
        final DimensionInfo customInfo =
            metadata.get(ResourceInfo.CUSTOM_DIMENSION_PREFIX + name, DimensionInfo.class);
        if (customInfo != null && customInfo.isEnabled()) {
          final ArrayList<String> val = new ArrayList<String>(1);
          val.add(getDefaultCustomDimensionValue(name, coverage, String.class));
          readParameters =
              CoverageUtils.mergeParameter(parameterDescriptors, readParameters, val, name);
        }
      }
    }

    return readParameters;
  }
Exemple #17
0
  /**
   * Adds a raster layer to the setup.
   *
   * <p>This method configures a raster layer with the name <code>qName.getLocalPart()</code>. A
   * coverage store is created (if it doesn't already exist) with the same name. The workspace of
   * the resulting store and layer is determined by <code>qName.getPrefix()</code>.
   *
   * <p>The <tt>filename</tt> parameter defines the raster file to be loaded from the classpath and
   * copied into the data directory. The <tt>scope</tt> is used as the class from which to load the
   * file from.
   *
   * <p>In the case of adding a zipped archive that contains multiple file the <tt>filename</tt>
   * paramter should have a ".zip" extension and the <tt>extension</tt> parameter must define the
   * extension of the main raster file. The parameter is not necessary and may be null if the
   * <tt>filename</tt> does not refer to a zip file.
   *
   * <p>The <tt>props</tt> parameter is used to define custom properties for the layer. See the
   * {@link LayerProperty} class for supported properties.
   *
   * @param qName The name of the raster layer.
   * @param filename The name of the file containing the raster, to be loaded from the classpath.
   * @param extension The file extension (without a ".") of the main raster file. This parameter my
   *     be <code>null</code> only if <tt>filename</tt> does not refer to a zip file.
   * @param props Custom properties to assign to the created raster layer.
   * @param scope The class from which to load the <tt>filename</tt> resource from.
   */
  public void addRasterLayer(
      QName qName,
      String filename,
      String extension,
      Map<LayerProperty, Object> props,
      Class scope,
      Catalog catalog)
      throws IOException {

    String prefix = qName.getPrefix();
    String name = qName.getLocalPart();

    // setup the data
    File dir = new File(data, name);
    dir.mkdirs();

    File file = new File(dir, filename);
    catalog.getResourceLoader().copyFromClassPath(filename, file, scope);

    String ext = FilenameUtils.getExtension(filename);
    if ("zip".equalsIgnoreCase(ext)) {

      // unpack the archive
      IOUtils.decompress(file, dir);

      // delete archive
      file.delete();

      if (extension == null) {
        // zip with no extension, we just the directory as the file
        file = dir;
      } else {
        // files may have been top level, or one directory level deep
        file = new File(dir, FilenameUtils.getBaseName(filename) + "." + extension);
        if (!file.exists()) {
          File file2 = new File(new File(dir, dir.getName()), file.getName());
          if (file2.exists()) {
            file = file2;
          }
        }
      }

      if (!file.exists()) {
        throw new FileNotFoundException(file.getPath());
      }
    }

    // load the format/reader
    AbstractGridFormat format = (AbstractGridFormat) GridFormatFinder.findFormat(file);
    if (format == null) {
      throw new RuntimeException("No format for " + file.getCanonicalPath());
    }
    AbstractGridCoverage2DReader reader = null;
    try {
      reader = (AbstractGridCoverage2DReader) format.getReader(file);
      if (reader == null) {
        throw new RuntimeException(
            "No reader for " + file.getCanonicalPath() + " with format " + format.getName());
      }

      // configure workspace if it doesn;t already exist
      if (catalog.getWorkspaceByName(prefix) == null) {
        addWorkspace(prefix, qName.getNamespaceURI(), catalog);
      }
      // create the store
      CoverageStoreInfo store = catalog.getCoverageStoreByName(prefix, name);
      if (store == null) {
        store = catalog.getFactory().createCoverageStore();
      }

      store.setName(name);
      store.setWorkspace(catalog.getWorkspaceByName(prefix));
      store.setEnabled(true);
      store.setURL(DataUtilities.fileToURL(file).toString());
      store.setType(format.getName());

      if (store.getId() == null) {
        catalog.add(store);
      } else {
        catalog.save(store);
      }

      // create the coverage
      CatalogBuilder builder = new CatalogBuilder(catalog);
      builder.setStore(store);

      CoverageInfo coverage = null;

      try {

        coverage = builder.buildCoverage(reader, null);
        // coverage read params
        if (format instanceof ImageMosaicFormat) {
          //  make sure we work in immediate mode
          coverage
              .getParameters()
              .put(AbstractGridFormat.USE_JAI_IMAGEREAD.getName().getCode(), Boolean.FALSE);
        }
      } catch (Exception e) {
        throw new IOException(e);
      }

      coverage.setName(name);
      coverage.setTitle(name);
      coverage.setDescription(name);
      coverage.setEnabled(true);

      CoverageInfo cov = catalog.getCoverageByCoverageStore(store, name);
      if (cov == null) {
        catalog.add(coverage);
      } else {
        builder.updateCoverage(cov, coverage);
        catalog.save(cov);
        coverage = cov;
      }

      LayerInfo layer = catalog.getLayerByName(new NameImpl(qName));
      if (layer == null) {
        layer = catalog.getFactory().createLayer();
      }
      layer.setResource(coverage);

      layer.setDefaultStyle(
          catalog.getStyleByName(LayerProperty.STYLE.get(props, DEFAULT_RASTER_STYLE)));
      layer.setType(LayerInfo.Type.RASTER);
      layer.setEnabled(true);

      if (layer.getId() == null) {
        catalog.add(layer);
      } else {
        catalog.save(layer);
      }
    } finally {
      if (reader != null) {
        reader.dispose();
      }
    }
  }
  @Test
  public void testHarvestExternalImageMosaic() throws Exception {
    // Check if an already existing directory called "mosaic" is present
    URL resource = getClass().getResource("test-data/mosaic");
    if (resource != null) {
      File oldDir = DataUtilities.urlToFile(resource);
      if (oldDir.exists()) {
        FileUtils.deleteDirectory(oldDir);
      }
    }
    // reading of the mosaic directory
    File mosaic = readMosaic();
    // Creation of the builder for building a new CoverageStore
    CatalogBuilder builder = new CatalogBuilder(getCatalog());
    // Definition of the workspace associated to the coverage
    WorkspaceInfo ws = getCatalog().getWorkspaceByName("gs");
    // Creation of a CoverageStore
    CoverageStoreInfo store = builder.buildCoverageStore("watertemp4");
    store.setURL(DataUtilities.fileToURL(mosaic).toExternalForm());
    store.setWorkspace(ws);
    ImageMosaicFormat imageMosaicFormat = new ImageMosaicFormat();
    store.setType((imageMosaicFormat.getName()));
    // Addition to the catalog
    getCatalog().add(store);
    builder.setStore(store);
    // Input reader used for reading the mosaic folder
    GridCoverage2DReader reader = null;
    // Reader used for checking if the mosaic has been configured correctly
    StructuredGridCoverage2DReader reader2 = null;

    try {
      // Selection of the reader to use for the mosaic
      reader = (GridCoverage2DReader) imageMosaicFormat.getReader(DataUtilities.fileToURL(mosaic));

      // configure the coverage
      configureCoverageInfo(builder, store, reader);

      // check the coverage is actually there
      CoverageStoreInfo storeInfo = getCatalog().getCoverageStoreByName("watertemp4");
      assertNotNull(storeInfo);
      CoverageInfo ci = getCatalog().getCoverageByName("mosaic");
      assertNotNull(ci);
      assertEquals(storeInfo, ci.getStore());

      // Harvesting of the Mosaic
      URL zipHarvest = getClass().getResource("test-data/harvesting.zip");
      // Extract a Byte array from the zip file
      InputStream is = null;
      byte[] bytes;
      try {
        is = zipHarvest.openStream();
        bytes = IOUtils.toByteArray(is);
      } finally {
        IOUtils.closeQuietly(is);
      }
      // Create the POST request
      MockHttpServletRequest request =
          createRequest("/rest/workspaces/gs/coveragestores/watertemp4/file.imagemosaic");
      request.setMethod("POST");
      request.setContentType("application/zip");
      request.setBodyContent(bytes);
      request.setHeader("Content-type", "application/zip");
      // Get The response
      MockHttpServletResponse response = dispatch(request);
      // Get the Mosaic Reader
      reader2 =
          (StructuredGridCoverage2DReader)
              storeInfo.getGridCoverageReader(null, GeoTools.getDefaultHints());
      // Test if all the TIME DOMAINS are present
      String[] metadataNames = reader2.getMetadataNames();
      assertNotNull(metadataNames);
      assertEquals("true", reader2.getMetadataValue("HAS_TIME_DOMAIN"));
      assertEquals(
          "2008-10-31T00:00:00.000Z,2008-11-01T00:00:00.000Z,2008-11-02T00:00:00.000Z",
          reader2.getMetadataValue(metadataNames[0]));
      // Removal of all the data associated to the mosaic
      reader2.delete(true);
    } finally {
      // Reader disposal
      if (reader != null) {
        try {
          reader.dispose();
        } catch (Throwable t) {
          // Does nothing
        }
      }
      if (reader2 != null) {
        try {
          reader2.dispose();
        } catch (Throwable t) {
          // Does nothing
        }
      }
    }
  }
  @Test
  public void testHarvestImageMosaicWithDirectory() throws Exception {
    // Upload of the Mosaic via REST
    URL zip = MockData.class.getResource("watertemp.zip");
    InputStream is = null;
    byte[] bytes;
    try {
      is = zip.openStream();
      bytes = IOUtils.toByteArray(is);
    } finally {
      IOUtils.closeQuietly(is);
    }

    MockHttpServletResponse response =
        putAsServletResponse(
            "/rest/workspaces/gs/coveragestores/watertemp3/file.imagemosaic",
            bytes,
            "application/zip");
    assertEquals(201, response.getStatusCode());

    // check the response contents
    String content = response.getOutputStreamContent();
    Document d = dom(new ByteArrayInputStream(content.getBytes()));

    XMLAssert.assertXpathEvaluatesTo("watertemp3", "//coverageStore/name", d);
    XMLAssert.assertXpathEvaluatesTo("ImageMosaic", "//coverageStore/type", d);

    // check the coverage is actually there
    CoverageStoreInfo storeInfo = getCatalog().getCoverageStoreByName("watertemp3");
    assertNotNull(storeInfo);
    CoverageInfo ci = getCatalog().getCoverageByName("watertemp3");
    assertNotNull(ci);
    assertEquals(storeInfo, ci.getStore());

    // Harvesting of the Mosaic
    URL zipHarvest = getClass().getResource("test-data/harvesting.zip");
    File zipFile = DataUtilities.urlToFile(zipHarvest);
    // Creation of another zip file which is a copy of the one before
    File newZip = new File(zipFile.getParentFile(), "harvesting2.zip");
    // Copy the content of the first zip to the second
    FileUtils.copyFile(zipFile, newZip);
    File outputDirectory = new File(zipFile.getParentFile(), "harvesting");
    outputDirectory.mkdir();
    RESTUtils.unzipFile(newZip, outputDirectory);
    // Create the POST request
    MockHttpServletRequest request =
        createRequest("/rest/workspaces/gs/coveragestores/watertemp3/external.imagemosaic");
    request.setMethod("POST");
    request.setContentType("text/plain");
    request.setBodyContent("file:///" + outputDirectory.getAbsolutePath());
    request.setHeader("Content-type", "text/plain");
    // Get The response
    response = dispatch(request);
    // Get the Mosaic Reader
    GridCoverageReader reader = storeInfo.getGridCoverageReader(null, GeoTools.getDefaultHints());
    // Test if all the TIME DOMAINS are present
    String[] metadataNames = reader.getMetadataNames();
    assertNotNull(metadataNames);
    assertEquals("true", reader.getMetadataValue("HAS_TIME_DOMAIN"));
    assertEquals(
        "2008-10-31T00:00:00.000Z,2008-11-01T00:00:00.000Z,2008-11-02T00:00:00.000Z",
        reader.getMetadataValue(metadataNames[0]));
    // Removal of the temporary directory
    FileUtils.deleteDirectory(outputDirectory);
  }
Exemple #20
0
  public WCSLayerConfig(String id, IModel model) {
    super(id, model);

    final CoverageInfo coverage = (CoverageInfo) getLayerInfo().getResource();
    add(
        new ListMultipleChoice(
            "requestSRS",
            new PropertyModel(this, "selectedRequestSRSs"),
            coverage.getRequestSRS()));

    add(new TextField("newRequestSRS", new PropertyModel(this, "newRequestSRS")));

    add(
        new Button("deleteSelectedRequestSRSs") {
          public void onSubmit() {
            coverage.getRequestSRS().removeAll(selectedRequestSRSs);
            selectedRequestSRSs.clear();
          }
        });

    add(
        new Button("addNewRequestSRS") {
          public void onSubmit() {
            coverage.getRequestSRS().add(newRequestSRS);
            newRequestSRS = "";
          }
        });

    add(
        new ListMultipleChoice(
            "responseSRS",
            new PropertyModel(this, "selectedResponseSRSs"),
            coverage.getResponseSRS()));

    add(new TextField("newResponseSRS", new PropertyModel(this, "newResponseSRS")));

    add(
        new Button("deleteSelectedResponseSRSs") {
          public void onSubmit() {
            coverage.getResponseSRS().removeAll(selectedResponseSRSs);
            selectedResponseSRSs.clear();
          }
        });

    add(
        new Button("addNewResponseSRS") {
          public void onSubmit() {
            coverage.getResponseSRS().add(newResponseSRS);
            newResponseSRS = "";
          }
        });

    add(
        new DropDownChoice(
            "defaultInterpolationMethod",
            new PropertyModel(coverage, "defaultInterpolationMethod"),
            new WCSInterpolationModel()));

    Palette interpolationMethods =
        new Palette(
            "interpolationMethods",
            LiveCollectionModel.list(new PropertyModel(coverage, "interpolationMethods")),
            new WCSInterpolationModel(),
            new SimpleChoiceRenderer(),
            7,
            false) {
          /** Override otherwise the header is not i18n'ized */
          @Override
          public Component newSelectedHeader(final String componentId) {
            return new Label(
                componentId, new ResourceModel("InterpolationMethodsPalette.selectedHeader"));
          }

          /** Override otherwise the header is not i18n'ized */
          @Override
          public Component newAvailableHeader(final String componentId) {
            return new Label(
                componentId, new ResourceModel("InterpolationMethodsPalette.availableHeader"));
          }
        };
    add(interpolationMethods);

    // don't allow editing the native format
    TextField nativeFormat =
        new TextField("nativeFormat", new PropertyModel(coverage, "nativeFormat"));
    nativeFormat.setEnabled(false);
    add(nativeFormat);

    Palette formatPalette =
        new Palette(
            "formatPalette",
            LiveCollectionModel.list(new PropertyModel(coverage, "supportedFormats")),
            new WCSFormatsModel(),
            new SimpleChoiceRenderer(),
            10,
            false) {
          /** Override otherwise the header is not i18n'ized */
          @Override
          public Component newSelectedHeader(final String componentId) {
            return new Label(componentId, new ResourceModel("FormatsPalette.selectedHeader"));
          }

          /** Override otherwise the header is not i18n'ized */
          @Override
          public Component newAvailableHeader(final String componentId) {
            return new Label(componentId, new ResourceModel("FormatsPalette.availableHeader"));
          }
        };
    add(formatPalette);
  }
  @DescribeResult(name = "layerName", description = "Name of the new featuretype, with workspace")
  public String execute(
      @DescribeParameter(name = "features", min = 0, description = "Input feature collection")
          SimpleFeatureCollection features,
      @DescribeParameter(name = "coverage", min = 0, description = "Input raster")
          GridCoverage2D coverage,
      @DescribeParameter(
              name = "workspace",
              min = 0,
              description = "Target workspace (default is the system default)")
          String workspace,
      @DescribeParameter(
              name = "store",
              min = 0,
              description = "Target store (default is the workspace default)")
          String store,
      @DescribeParameter(
              name = "name",
              min = 0,
              description =
                  "Name of the new featuretype/coverage (default is the name of the features in the collection)")
          String name,
      @DescribeParameter(
              name = "srs",
              min = 0,
              description =
                  "Target coordinate reference system (default is based on source when possible)")
          CoordinateReferenceSystem srs,
      @DescribeParameter(
              name = "srsHandling",
              min = 0,
              description =
                  "Desired SRS handling (default is FORCE_DECLARED, others are REPROJECT_TO_DECLARED or NONE)")
          ProjectionPolicy srsHandling,
      @DescribeParameter(
              name = "styleName",
              min = 0,
              description =
                  "Name of the style to be associated with the layer (default is a standard geometry-specific style)")
          String styleName)
      throws ProcessException {

    // first off, decide what is the target store
    WorkspaceInfo ws;
    if (workspace != null) {
      ws = catalog.getWorkspaceByName(workspace);
      if (ws == null) {
        throw new ProcessException("Could not find workspace " + workspace);
      }
    } else {
      ws = catalog.getDefaultWorkspace();
      if (ws == null) {
        throw new ProcessException("The catalog is empty, could not find a default workspace");
      }
    }

    // create a builder to help build catalog objects
    CatalogBuilder cb = new CatalogBuilder(catalog);
    cb.setWorkspace(ws);

    // ok, find the target store
    StoreInfo storeInfo = null;
    boolean add = false;
    if (store != null) {
      if (features != null) {
        storeInfo = catalog.getDataStoreByName(ws.getName(), store);
      } else if (coverage != null) {
        storeInfo = catalog.getCoverageStoreByName(ws.getName(), store);
      }
      if (storeInfo == null) {
        throw new ProcessException("Could not find store " + store + " in workspace " + workspace);
        // TODO: support store creation
      }
    } else if (features != null) {
      storeInfo = catalog.getDefaultDataStore(ws);
      if (storeInfo == null) {
        throw new ProcessException("Could not find a default store in workspace " + ws.getName());
      }
    } else if (coverage != null) {
      // create a new coverage store
      LOGGER.info(
          "Auto-configuring coverage store: "
              + (name != null ? name : coverage.getName().toString()));

      storeInfo = cb.buildCoverageStore((name != null ? name : coverage.getName().toString()));
      add = true;
      store = (name != null ? name : coverage.getName().toString());

      if (storeInfo == null) {
        throw new ProcessException("Could not find a default store in workspace " + ws.getName());
      }
    }

    // check the target style if any
    StyleInfo targetStyle = null;
    if (styleName != null) {
      targetStyle = catalog.getStyleByName(styleName);
      if (targetStyle == null) {
        throw new ProcessException("Could not find style " + styleName);
      }
    }

    if (features != null) {
      // check if the target layer and the target feature type are not
      // already there (this is a half-assed attempt as we don't have
      // an API telling us how the feature type name will be changed
      // by DataStore.createSchema(...), but better than fully importing
      // the data into the target store to find out we cannot create the layer...)
      String tentativeTargetName = null;
      if (name != null) {
        tentativeTargetName = ws.getName() + ":" + name;
      } else {
        tentativeTargetName = ws.getName() + ":" + features.getSchema().getTypeName();
      }
      if (catalog.getLayer(tentativeTargetName) != null) {
        throw new ProcessException("Target layer " + tentativeTargetName + " already exists");
      }

      // check the target crs
      String targetSRSCode = null;
      if (srs != null) {
        try {
          Integer code = CRS.lookupEpsgCode(srs, true);
          if (code == null) {
            throw new WPSException("Could not find a EPSG code for " + srs);
          }
          targetSRSCode = "EPSG:" + code;
        } catch (Exception e) {
          throw new ProcessException("Could not lookup the EPSG code for the provided srs", e);
        }
      } else {
        // check we can extract a code from the original data
        GeometryDescriptor gd = features.getSchema().getGeometryDescriptor();
        if (gd == null) {
          // data is geometryless, we need a fake SRS
          targetSRSCode = "EPSG:4326";
          srsHandling = ProjectionPolicy.FORCE_DECLARED;
        } else {
          CoordinateReferenceSystem nativeCrs = gd.getCoordinateReferenceSystem();
          if (nativeCrs == null) {
            throw new ProcessException(
                "The original data has no native CRS, " + "you need to specify the srs parameter");
          } else {
            try {
              Integer code = CRS.lookupEpsgCode(nativeCrs, true);
              if (code == null) {
                throw new ProcessException(
                    "Could not find an EPSG code for data "
                        + "native spatial reference system: "
                        + nativeCrs);
              } else {
                targetSRSCode = "EPSG:" + code;
              }
            } catch (Exception e) {
              throw new ProcessException(
                  "Failed to loookup an official EPSG code for "
                      + "the source data native "
                      + "spatial reference system",
                  e);
            }
          }
        }
      }

      // import the data into the target store
      SimpleFeatureType targetType;
      try {
        targetType = importDataIntoStore(features, name, (DataStoreInfo) storeInfo);
      } catch (IOException e) {
        throw new ProcessException("Failed to import data into the target store", e);
      }

      // now import the newly created layer into GeoServer
      try {
        cb.setStore(storeInfo);

        // build the typeInfo and set CRS if necessary
        FeatureTypeInfo typeInfo = cb.buildFeatureType(targetType.getName());
        if (targetSRSCode != null) {
          typeInfo.setSRS(targetSRSCode);
        }
        if (srsHandling != null) {
          typeInfo.setProjectionPolicy(srsHandling);
        }
        // compute the bounds
        cb.setupBounds(typeInfo);

        // build the layer and set a style
        LayerInfo layerInfo = cb.buildLayer(typeInfo);
        if (targetStyle != null) {
          layerInfo.setDefaultStyle(targetStyle);
        }

        catalog.add(typeInfo);
        catalog.add(layerInfo);

        return layerInfo.prefixedName();
      } catch (Exception e) {
        throw new ProcessException("Failed to complete the import inside the GeoServer catalog", e);
      }
    } else if (coverage != null) {
      try {
        final File directory =
            catalog.getResourceLoader().findOrCreateDirectory("data", workspace, store);
        final File file = File.createTempFile(store, ".tif", directory);
        ((CoverageStoreInfo) storeInfo).setURL(file.toURL().toExternalForm());
        ((CoverageStoreInfo) storeInfo).setType("GeoTIFF");

        // check the target crs
        CoordinateReferenceSystem cvCrs = coverage.getCoordinateReferenceSystem();
        String targetSRSCode = null;
        if (srs != null) {
          try {
            Integer code = CRS.lookupEpsgCode(srs, true);
            if (code == null) {
              throw new WPSException("Could not find a EPSG code for " + srs);
            }
            targetSRSCode = "EPSG:" + code;
          } catch (Exception e) {
            throw new ProcessException("Could not lookup the EPSG code for the provided srs", e);
          }
        } else {
          // check we can extract a code from the original data
          if (cvCrs == null) {
            // data is geometryless, we need a fake SRS
            targetSRSCode = "EPSG:4326";
            srsHandling = ProjectionPolicy.FORCE_DECLARED;
            srs = DefaultGeographicCRS.WGS84;
          } else {
            CoordinateReferenceSystem nativeCrs = cvCrs;
            if (nativeCrs == null) {
              throw new ProcessException(
                  "The original data has no native CRS, "
                      + "you need to specify the srs parameter");
            } else {
              try {
                Integer code = CRS.lookupEpsgCode(nativeCrs, true);
                if (code == null) {
                  throw new ProcessException(
                      "Could not find an EPSG code for data "
                          + "native spatial reference system: "
                          + nativeCrs);
                } else {
                  targetSRSCode = "EPSG:" + code;
                  srs = CRS.decode(targetSRSCode, true);
                }
              } catch (Exception e) {
                throw new ProcessException(
                    "Failed to loookup an official EPSG code for "
                        + "the source data native "
                        + "spatial reference system",
                    e);
              }
            }
          }
        }

        MathTransform tx = CRS.findMathTransform(cvCrs, srs);

        if (!tx.isIdentity() || !CRS.equalsIgnoreMetadata(cvCrs, srs)) {
          coverage =
              WCSUtils.resample(
                  coverage,
                  cvCrs,
                  srs,
                  null,
                  Interpolation.getInstance(Interpolation.INTERP_NEAREST));
        }

        GeoTiffWriter writer = new GeoTiffWriter(file);

        // setting the write parameters for this geotiff
        final ParameterValueGroup params = new GeoTiffFormat().getWriteParameters();
        params
            .parameter(AbstractGridFormat.GEOTOOLS_WRITE_PARAMS.getName().toString())
            .setValue(DEFAULT_WRITE_PARAMS);
        final GeneralParameterValue[] wps =
            (GeneralParameterValue[]) params.values().toArray(new GeneralParameterValue[1]);

        try {
          writer.write(coverage, wps);
        } finally {
          try {
            writer.dispose();
          } catch (Exception e) {
            // we tried, no need to fuss around this one
          }
        }

        // add or update the datastore info
        if (add) {
          catalog.add((CoverageStoreInfo) storeInfo);
        } else {
          catalog.save((CoverageStoreInfo) storeInfo);
        }

        cb.setStore((CoverageStoreInfo) storeInfo);

        AbstractGridCoverage2DReader reader = new GeoTiffReader(file);
        if (reader == null) {
          throw new ProcessException("Could not aquire reader for coverage.");
        }

        // coverage read params
        final Map customParameters = new HashMap();
        /*String useJAIImageReadParam = "USE_JAI_IMAGEREAD";
        if (useJAIImageReadParam != null) {
        	customParameters.put(AbstractGridFormat.USE_JAI_IMAGEREAD.getName().toString(), Boolean.valueOf(useJAIImageReadParam));
        }*/

        CoverageInfo cinfo = cb.buildCoverage(reader, customParameters);

        // check if the name of the coverage was specified
        if (name != null) {
          cinfo.setName(name);
        }

        if (!add) {
          // update the existing
          CoverageInfo existing =
              catalog.getCoverageByCoverageStore(
                  (CoverageStoreInfo) storeInfo,
                  name != null ? name : coverage.getName().toString());
          if (existing == null) {
            // grab the first if there is only one
            List<CoverageInfo> coverages =
                catalog.getCoveragesByCoverageStore((CoverageStoreInfo) storeInfo);
            if (coverages.size() == 1) {
              existing = coverages.get(0);
            }
            if (coverages.size() == 0) {
              // no coverages yet configured, change add flag and continue on
              add = true;
            } else {
              // multiple coverages, and one to configure not specified
              throw new ProcessException("Unable to determine coverage to configure.");
            }
          }

          if (existing != null) {
            cb.updateCoverage(existing, cinfo);
            catalog.save(existing);
            cinfo = existing;
          }
        }

        // do some post configuration, if srs is not known or unset, transform to 4326
        if ("UNKNOWN".equals(cinfo.getSRS())) {
          // CoordinateReferenceSystem sourceCRS =
          // cinfo.getBoundingBox().getCoordinateReferenceSystem();
          // CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326", true);
          // ReferencedEnvelope re = cinfo.getBoundingBox().transform(targetCRS, true);
          cinfo.setSRS("EPSG:4326");
          // cinfo.setCRS( targetCRS );
          // cinfo.setBoundingBox( re );
        }

        // add/save
        if (add) {
          catalog.add(cinfo);

          LayerInfo layerInfo = cb.buildLayer(cinfo);
          if (styleName != null && targetStyle != null) {
            layerInfo.setDefaultStyle(targetStyle);
          }
          // JD: commenting this out, these sorts of edits should be handled
          // with a second PUT request on the created coverage
          /*
          String styleName = form.getFirstValue("style");
          if ( styleName != null ) {
              StyleInfo style = catalog.getStyleByName( styleName );
              if ( style != null ) {
                  layerInfo.setDefaultStyle( style );
                  if ( !layerInfo.getStyles().contains( style ) ) {
                      layerInfo.getStyles().add( style );
                  }
              }
              else {
                  LOGGER.warning( "Client specified style '" + styleName + "'but no such style exists.");
              }
          }

          String path = form.getFirstValue( "path");
          if ( path != null ) {
              layerInfo.setPath( path );
          }
          */

          boolean valid = true;
          try {
            if (!catalog.validate(layerInfo, true).isEmpty()) {
              valid = false;
            }
          } catch (Exception e) {
            valid = false;
          }

          layerInfo.setEnabled(valid);
          catalog.add(layerInfo);

          return layerInfo.prefixedName();
        } else {
          catalog.save(cinfo);

          LayerInfo layerInfo = catalog.getLayerByName(cinfo.getName());
          if (styleName != null && targetStyle != null) {
            layerInfo.setDefaultStyle(targetStyle);
          }

          return layerInfo.prefixedName();
        }

      } catch (MalformedURLException e) {
        throw new ProcessException("URL Error", e);
      } catch (IOException e) {
        throw new ProcessException("I/O Exception", e);
      } catch (Exception e) {
        e.printStackTrace();
        throw new ProcessException("Exception", e);
      }
    }

    return null;
  }
  /** Reads the catalog from disk. */
  Catalog readCatalog(XStreamPersister xp) throws Exception {
    CatalogImpl catalog = new CatalogImpl();
    catalog.setResourceLoader(resourceLoader);
    xp.setCatalog(catalog);
    xp.setUnwrapNulls(false);

    CatalogFactory factory = catalog.getFactory();

    // global styles
    loadStyles(resourceLoader.find("styles"), catalog, xp);

    // workspaces, stores, and resources
    File workspaces = resourceLoader.find("workspaces");
    if (workspaces != null) {
      // do a first quick scan over all workspaces, setting the default
      File dws = new File(workspaces, "default.xml");
      WorkspaceInfo defaultWorkspace = null;
      if (dws.exists()) {
        try {
          defaultWorkspace = depersist(xp, dws, WorkspaceInfo.class);
          LOGGER.info("Loaded default workspace " + defaultWorkspace.getName());
        } catch (Exception e) {
          LOGGER.log(Level.WARNING, "Failed to load default workspace", e);
        }
      } else {
        LOGGER.warning("No default workspace was found.");
      }

      for (File wsd : list(workspaces, DirectoryFileFilter.INSTANCE)) {
        File f = new File(wsd, "workspace.xml");
        if (!f.exists()) {
          continue;
        }

        WorkspaceInfo ws = null;
        try {
          ws = depersist(xp, f, WorkspaceInfo.class);
          catalog.add(ws);
        } catch (Exception e) {
          LOGGER.log(Level.WARNING, "Failed to load workspace '" + wsd.getName() + "'", e);
          continue;
        }

        LOGGER.info("Loaded workspace '" + ws.getName() + "'");

        // load the namespace
        File nsf = new File(wsd, "namespace.xml");
        NamespaceInfo ns = null;
        if (nsf.exists()) {
          try {
            ns = depersist(xp, nsf, NamespaceInfo.class);
            catalog.add(ns);
          } catch (Exception e) {
            LOGGER.log(Level.WARNING, "Failed to load namespace for '" + wsd.getName() + "'", e);
          }
        }

        // set the default workspace, this value might be null in the case of coming from a
        // 2.0.0 data directory. See http://jira.codehaus.org/browse/GEOS-3440
        if (defaultWorkspace != null) {
          if (ws.getName().equals(defaultWorkspace.getName())) {
            catalog.setDefaultWorkspace(ws);
            if (ns != null) {
              catalog.setDefaultNamespace(ns);
            }
          }
        } else {
          // create the default.xml file
          defaultWorkspace = catalog.getDefaultWorkspace();
          if (defaultWorkspace != null) {
            try {
              persist(xp, defaultWorkspace, dws);
            } catch (Exception e) {
              LOGGER.log(
                  Level.WARNING, "Failed to persist default workspace '" + wsd.getName() + "'", e);
            }
          }
        }

        // load the styles for the workspace
        File styles = resourceLoader.find(wsd, "styles");
        if (styles != null) {
          loadStyles(styles, catalog, xp);
        }
      }

      for (File wsd : list(workspaces, DirectoryFileFilter.INSTANCE)) {

        // load the stores for this workspace
        for (File sd : list(wsd, DirectoryFileFilter.INSTANCE)) {
          File f = new File(sd, "datastore.xml");
          if (f.exists()) {
            // load as a datastore
            DataStoreInfo ds = null;
            try {
              ds = depersist(xp, f, DataStoreInfo.class);
              catalog.add(ds);

              LOGGER.info("Loaded data store '" + ds.getName() + "'");

              if (ds.isEnabled()) {
                // connect to the datastore to determine if we should disable it
                try {
                  ds.getDataStore(null);
                } catch (Throwable t) {
                  LOGGER.warning("Error connecting to '" + ds.getName() + "'. Disabling.");
                  LOGGER.log(Level.INFO, "", t);

                  ds.setError(t);
                  ds.setEnabled(false);
                }
              }
            } catch (Exception e) {
              LOGGER.log(Level.WARNING, "Failed to load data store '" + sd.getName() + "'", e);
              continue;
            }

            // load feature types
            for (File ftd : list(sd, DirectoryFileFilter.INSTANCE)) {
              f = new File(ftd, "featuretype.xml");
              if (f.exists()) {
                FeatureTypeInfo ft = null;
                try {
                  ft = depersist(xp, f, FeatureTypeInfo.class);
                } catch (Exception e) {
                  LOGGER.log(
                      Level.WARNING, "Failed to load feature type '" + ftd.getName() + "'", e);
                  continue;
                }

                catalog.add(ft);

                LOGGER.info("Loaded feature type '" + ds.getName() + "'");

                f = new File(ftd, "layer.xml");
                if (f.exists()) {
                  try {
                    LayerInfo l = depersist(xp, f, LayerInfo.class);
                    catalog.add(l);

                    LOGGER.info("Loaded layer '" + l.getName() + "'");
                  } catch (Exception e) {
                    LOGGER.log(
                        Level.WARNING,
                        "Failed to load layer for feature type '" + ft.getName() + "'",
                        e);
                  }
                }
              } else {
                LOGGER.warning("Ignoring feature type directory " + ftd.getAbsolutePath());
              }
            }
          } else {
            // look for a coverage store
            f = new File(sd, "coveragestore.xml");
            if (f.exists()) {
              CoverageStoreInfo cs = null;
              try {
                cs = depersist(xp, f, CoverageStoreInfo.class);
                catalog.add(cs);

                LOGGER.info("Loaded coverage store '" + cs.getName() + "'");
              } catch (Exception e) {
                LOGGER.log(
                    Level.WARNING, "Failed to load coverage store '" + sd.getName() + "'", e);
                continue;
              }

              // load coverages
              for (File cd : list(sd, DirectoryFileFilter.INSTANCE)) {
                f = new File(cd, "coverage.xml");
                if (f.exists()) {
                  CoverageInfo c = null;
                  try {
                    c = depersist(xp, f, CoverageInfo.class);
                    catalog.add(c);

                    LOGGER.info("Loaded coverage '" + cs.getName() + "'");
                  } catch (Exception e) {
                    LOGGER.log(Level.WARNING, "Failed to load coverage '" + cd.getName() + "'", e);
                    continue;
                  }

                  f = new File(cd, "layer.xml");
                  if (f.exists()) {
                    try {
                      LayerInfo l = depersist(xp, f, LayerInfo.class);
                      catalog.add(l);

                      LOGGER.info("Loaded layer '" + l.getName() + "'");
                    } catch (Exception e) {
                      LOGGER.log(
                          Level.WARNING, "Failed to load layer coverage '" + c.getName() + "'", e);
                    }
                  }
                } else {
                  LOGGER.warning("Ignoring coverage directory " + cd.getAbsolutePath());
                }
              }
            } else {
              f = new File(sd, "wmsstore.xml");
              if (f.exists()) {
                WMSStoreInfo wms = null;
                try {
                  wms = depersist(xp, f, WMSStoreInfo.class);
                  catalog.add(wms);

                  LOGGER.info("Loaded wmsstore '" + wms.getName() + "'");
                } catch (Exception e) {
                  LOGGER.log(Level.WARNING, "Failed to load wms store '" + sd.getName() + "'", e);
                  continue;
                }

                // load wms layers
                for (File cd : list(sd, DirectoryFileFilter.INSTANCE)) {
                  f = new File(cd, "wmslayer.xml");
                  if (f.exists()) {
                    WMSLayerInfo wl = null;
                    try {
                      wl = depersist(xp, f, WMSLayerInfo.class);
                      catalog.add(wl);

                      LOGGER.info("Loaded wms layer'" + wl.getName() + "'");
                    } catch (Exception e) {
                      LOGGER.log(
                          Level.WARNING, "Failed to load wms layer '" + cd.getName() + "'", e);
                      continue;
                    }

                    f = new File(cd, "layer.xml");
                    if (f.exists()) {
                      try {
                        LayerInfo l = depersist(xp, f, LayerInfo.class);
                        catalog.add(l);

                        LOGGER.info("Loaded layer '" + l.getName() + "'");
                      } catch (Exception e) {
                        LOGGER.log(
                            Level.WARNING,
                            "Failed to load cascaded wms layer '" + wl.getName() + "'",
                            e);
                      }
                    }
                  } else {
                    LOGGER.warning("Ignoring coverage directory " + cd.getAbsolutePath());
                  }
                }
              } else if (!isConfigDirectory(sd)) {
                LOGGER.warning("Ignoring store directory '" + sd.getName() + "'");
                continue;
              }
            }
          }
        }

        // load hte layer groups for this workspace
        File layergroups = resourceLoader.find(wsd, "layergroups");
        if (layergroups != null) {
          loadLayerGroups(layergroups, catalog, xp);
        }
      }
    } else {
      LOGGER.warning("No 'workspaces' directory found, unable to load any stores.");
    }

    // namespaces

    // layergroups
    File layergroups = resourceLoader.find("layergroups");
    if (layergroups != null) {
      loadLayerGroups(layergroups, catalog, xp);
    }
    xp.setUnwrapNulls(true);
    catalog.resolve();
    return catalog;
  }
  @Test
  public void testHarvestImageMosaic() throws Exception {
    // Upload of the Mosaic via REST
    URL zip = MockData.class.getResource("watertemp.zip");
    InputStream is = null;
    byte[] bytes;
    try {
      is = zip.openStream();
      bytes = IOUtils.toByteArray(is);
    } finally {
      IOUtils.closeQuietly(is);
    }

    MockHttpServletResponse response =
        putAsServletResponse(
            "/rest/workspaces/gs/coveragestores/watertemp2/file.imagemosaic",
            bytes,
            "application/zip");
    assertEquals(201, response.getStatusCode());

    // check the response contents
    String content = response.getOutputStreamContent();
    Document d = dom(new ByteArrayInputStream(content.getBytes()));

    XMLAssert.assertXpathEvaluatesTo("watertemp2", "//coverageStore/name", d);
    XMLAssert.assertXpathEvaluatesTo("ImageMosaic", "//coverageStore/type", d);

    // check the coverage is actually there
    CoverageStoreInfo storeInfo = getCatalog().getCoverageStoreByName("watertemp2");
    assertNotNull(storeInfo);
    CoverageInfo ci = getCatalog().getCoverageByName("watertemp2");
    assertNotNull(ci);
    assertEquals(storeInfo, ci.getStore());

    // Harvesting of the Mosaic
    URL zipHarvest = getClass().getResource("test-data/harvesting.zip");
    // Extract a Byte array from the zip file
    is = null;
    try {
      is = zipHarvest.openStream();
      bytes = IOUtils.toByteArray(is);
    } finally {
      IOUtils.closeQuietly(is);
    }
    // Create the POST request
    MockHttpServletRequest request =
        createRequest("/rest/workspaces/gs/coveragestores/watertemp2/file.imagemosaic");
    request.setMethod("POST");
    request.setContentType("application/zip");
    request.setBodyContent(bytes);
    request.setHeader("Content-type", "application/zip");
    // Get The response
    response = dispatch(request);
    // Get the Mosaic Reader
    GridCoverageReader reader = storeInfo.getGridCoverageReader(null, GeoTools.getDefaultHints());
    // Test if all the TIME DOMAINS are present
    String[] metadataNames = reader.getMetadataNames();
    assertNotNull(metadataNames);
    assertEquals("true", reader.getMetadataValue("HAS_TIME_DOMAIN"));
    assertEquals(
        "2008-10-31T00:00:00.000Z,2008-11-01T00:00:00.000Z,2008-11-02T00:00:00.000Z",
        reader.getMetadataValue(metadataNames[0]));
  }