/* * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata * * Portions of this software were developed by the Unidata Program at the * University Corporation for Atmospheric Research. * * Access and use of this software shall impose the following obligations * and understandings on the user. The user is granted the right, without * any fee or cost, to use, copy, modify, alter, enhance and distribute * this software, and any derivative works thereof, and its supporting * documentation for any purpose whatsoever, provided that this entire * notice appears in all copies of the software, derivative works and * supporting documentation. Further, UCAR requests that the user credit * UCAR/Unidata in any publications that result from the use of this * software or in any product that includes this software. The names UCAR * and/or Unidata, however, may not be used in any advertising or publicity * to endorse or promote any products or commercial entity unless specific * written permission is obtained from UCAR/Unidata. The user also * understands that UCAR/Unidata is not obligated to provide the user with * any support, consulting, training or assistance of any kind with regard * to the use, operation and performance of this software nor to provide * the user with any updates, revisions, new versions or "bug fixes." * * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * User: rkambic * Date: Oct 13, 2010 * Time: 11:19:08 AM */ package thredds.server.radarServer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; import thredds.catalog.*; import thredds.server.config.TdsContext; import thredds.servlet.HtmlWriter; import thredds.util.TdsPathUtils; import ucar.nc2.time.CalendarDateRange; import ucar.unidata.geoloc.LatLonRect; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.*; /** * Returns catalogs/datasets for the RadarServer data */ @Controller public class CatalogRadarServerController extends AbstractController { private org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(getClass()); @Autowired private TdsContext tdsContext; /** * The view to forward to in case an dataset needs to be created. */ //private static final String CREATE_VIEW = "forward:createdataset.htm"; /** * The model key used to retrieve the message from the model. */ private static final String MODEL_KEY = "message"; /** * The unique key for retrieving the text associated with this message. */ private static final String MSG_CODE = "message.create.dataset"; public CatalogRadarServerController() { } protected String getControllerPath() { return "/radarServer/"; } /** * Spring Framework controller * * @param request HttpServletRequest * @param response HttpServletResponse * @return ModelAndView * @throws Exception */ // @RequestMapping(value = {"/radarServer/**/catalog.xml", "/radarServer/**/catalog.html", "/radarServer/**/dataset.xml", "/radarServer/**/dataset.html"}, // method = {RequestMethod.GET, RequestMethod.HEAD}) protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { DatasetRepository.init(tdsContext); try { String path = TdsPathUtils.extractPath(request, getControllerPath()); if (path == null) path = ""; // return main catalog xml or html if (path.equals("catalog.xml") || path.equals("dataset.xml")) { // InvCatalogFactory factory = DataRootHandler.getInstance().getCatalogFactory(false); InvCatalogFactory factory = InvCatalogFactory.getDefaultFactory(false); // no validation String catAsString = factory.writeXML(DatasetRepository.cat); PrintWriter pw = response.getWriter(); pw.println(catAsString); pw.flush(); return null; } if (path.equals("catalog.html") || path.equals("dataset.html")) { try { HtmlWriter.getInstance().writeCatalog(request, response, DatasetRepository.cat, true); // show catalog as HTML } catch (Exception e) { log.error("Radar HtmlWriter failed ", e); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "radarServer HtmlWriter error " + path); } return null; } InvCatalogImpl catalog = DatasetRepository.cat; // default is the complete radarCollection catalog if (path.contains("level2/catalog.") || path.contains("level3/catalog.") || path.contains("level2/dataset.") || path.contains("level3/dataset.")) { catalog = level2level3catalog(DatasetRepository.cat, path); if (catalog == null) { response.sendError(HttpServletResponse.SC_BAD_REQUEST); return null; } // returns specific dataset information, ie level2/IDD used by IDV } else if (path.endsWith("dataset.xml") || path.endsWith("catalog.xml")) { Map<String, Object> model = datasetInfoXml(DatasetRepository.cat, path); if (model == null) { response.sendError(HttpServletResponse.SC_BAD_REQUEST); return null; } return new ModelAndView("datasetXml", model); } if (catalog == null) { return null; // ModelAndView mav = new ModelAndView(CREATE_VIEW); // WTF ?? // mav.addObject(MODEL_KEY, MSG_CODE); // return mav; } else { if (path.endsWith(".html")) { HtmlWriter.getInstance().writeCatalog(request, response, catalog, true); return null; } else return new ModelAndView("threddsInvCatXmlView", "catalog", catalog); } } catch (RadarServerException e) { throw e; // pass it onto Spring exceptionResolver } catch (Throwable e) { log.error("handleRequestInternal(): Problem handling request.", e); throw new RadarServerException("handleRequestInternal(): Problem handling request.", e); } } /* * handles level2 and level3 type of catalog requests */ private InvCatalogImpl level2level3catalog(InvCatalogImpl cat, String pathInfo) throws RadarServerException, IOException { InvCatalogImpl tCat = null; try { // extract dataset path String dsPath; if (pathInfo.indexOf("/dataset") > 0) { dsPath = pathInfo.substring(0, pathInfo.indexOf("/dataset")); } else if (pathInfo.indexOf("/catalog") > 0) { dsPath = pathInfo.substring(0, pathInfo.indexOf("/catalog")); } else { log.error("RadarServer.datasetInfoXml", "Invalid url request"); throw new RadarServerException("Invalid url request"); } // clone catalog ByteArrayOutputStream os = new ByteArrayOutputStream(10000); InvCatalogFactory factory = InvCatalogFactory.getDefaultFactory(false); factory.writeXML(cat, os, true); tCat = factory.readXML( new ByteArrayInputStream(os.toByteArray()), DatasetRepository.catURI); // modify clone for only requested datasets Iterator parents = tCat.getDatasets().iterator(); while (parents.hasNext()) { ArrayList<InvDatasetImpl> delete = new ArrayList<InvDatasetImpl>(); InvDatasetImpl top = (InvDatasetImpl) parents.next(); Iterator tDatasets = top.getDatasets().iterator(); while (tDatasets.hasNext()) { InvDatasetImpl ds = (InvDatasetImpl) tDatasets.next(); if (ds instanceof InvDatasetScan) { InvDatasetScan ids = (InvDatasetScan) ds; if (ids.getPath() == null) continue; if (ids.getPath().contains(dsPath)) { ids.setXlinkHref(ids.getPath() + "/dataset.xml"); } else { delete.add(ds); } } } // remove datasets for (InvDatasetImpl idi : delete) { top.removeDataset(idi); } } } catch (Throwable e) { log.error("RadarServer.level2level3catalog", "Invalid url request"); throw new RadarServerException("Invalid catalog request", e); } return tCat; } /** * @param cat radarCollections catalog * @param pathInfo requested dataset by path * @return model dataset object to be used by datasetXml.jsjp * @throws RadarServerException controlled exception with information about failure * @throws IOException major */ private Map<String, Object> datasetInfoXml(InvCatalogImpl cat, String pathInfo) throws RadarServerException, IOException { // dataset results are stored in model Map<String, Object> model = new HashMap<String, Object>(); InvDatasetScan ds = null; boolean found = false; try { // extract dataset path String dsPath; if (pathInfo.indexOf("/dataset") > 0) { dsPath = pathInfo.substring(0, pathInfo.indexOf("/dataset")); } else if (pathInfo.indexOf("/catalog") > 0) { dsPath = pathInfo.substring(0, pathInfo.indexOf("/catalog")); } else { log.error("RadarServer.datasetInfoXml", "Invalid url request"); throw new RadarServerException("Invalid url request"); } // search for dataset by dsPath Iterator parents = cat.getDatasets().iterator(); InvDatasetImpl top = (InvDatasetImpl) parents.next(); Iterator tDatasets = top.getDatasets().iterator(); while (tDatasets.hasNext()) { InvDatasetImpl idsi = (InvDatasetImpl) tDatasets.next(); if (idsi instanceof InvDatasetScan) { ds = (InvDatasetScan) idsi; if (ds.getPath() == null) continue; if (ds.getPath().contains(dsPath)) { found = true; break; } else { continue; } } } } catch (Throwable e) { log.error("RadarServer.datasetInfoXml", e); throw new RadarServerException("CatalogRadarServerController.datasetInfoXml", e); } if (!found) { log.error("RadarServer.datasetInfoXml", "Invalid url request"); throw new RadarServerException("Invalid url request"); } // create dataset by storing necessary information in model object that will // be displayed by datasetXml.jsp // add ID model.put("ID", ds.getID()); model.put("urlPath", ds.getPath()); model.put("dataFormat", ds.getDataFormatType()); model.put("documentation", ds.getSummary()); CalendarDateRange dr = ds.getCalendarDateCoverage(); /* if (pathInfo.contains("IDD")) { pw.print(rm.getStartDateTime(ds.getPath())); } else { pw.print(dr.getStart().toDateTimeStringISO()); } */ //TODO: check //pw.print(dr.getStart().toDateTimeStringISO()); model.put("tstart", dr.getStart().toString()); model.put("tend", dr.getEnd().toString()); ThreddsMetadata.GeospatialCoverage gc = ds.getGeospatialCoverage(); LatLonRect bb = new LatLonRect(); gc.setBoundingBox(bb); model.put("north", gc.getLatNorth()); model.put("south", gc.getLatSouth()); model.put("east", gc.getLonEast()); model.put("west", gc.getLonWest()); if (ds.getVariables().size() > 0) { ThreddsMetadata.Variables cvs = ds.getVariables().get(0); List vl = cvs.getVariableList(); ArrayList<RsVar> variables = new ArrayList<>(); for (int j = 0; j < vl.size(); j++) { ThreddsMetadata.Variable v = (ThreddsMetadata.Variable) vl.get(j); RsVar rsv = new RsVar(); rsv.setName(v.getName()); rsv.setVname(v.getVocabularyName()); rsv.setUnits(v.getUnits()); variables.add(rsv); } model.put("variables", variables); } // not necessary to get stations, IDV does separate request for stations //String[] stations = rm.stationsDS(radarType, dataLocation.get(ds.getPath())); //rm.printStations(stations, pw, radarType ); return model; } /* * Used to store the information about a Radar variable from catalog */ public static class RsVar { private String name; private String vname; private String units; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getVname() { return vname; } public void setVname(String vname) { this.vname = vname; } public String getUnits() { return units; } public void setUnits(String units) { this.units = units; } } }