PageRenderTime 28ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStyleManager.java

http://github.com/geosolutions-it/geoserver-manager
Java | 791 lines | 372 code | 82 blank | 337 comment | 93 complexity | a737cbb2a0857cc0d42b9b912f10012d MD5 | raw file
  1. /*
  2. * GeoServer-Manager - Simple Manager Library for GeoServer
  3. *
  4. * Copyright (C) 2007,2015 GeoSolutions S.A.S.
  5. * http://www.geo-solutions.it
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. package it.geosolutions.geoserver.rest.manager;
  26. import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
  27. import it.geosolutions.geoserver.rest.HTTPUtils;
  28. import it.geosolutions.geoserver.rest.Util;
  29. import it.geosolutions.geoserver.rest.decoder.RESTStyle;
  30. import it.geosolutions.geoserver.rest.decoder.RESTStyleList;
  31. import java.io.ByteArrayInputStream;
  32. import java.io.File;
  33. import java.io.IOException;
  34. import java.io.InputStream;
  35. import java.net.URL;
  36. import java.net.URLEncoder;
  37. import java.nio.charset.Charset;
  38. import javax.xml.parsers.DocumentBuilder;
  39. import javax.xml.parsers.DocumentBuilderFactory;
  40. import javax.xml.parsers.ParserConfigurationException;
  41. import javax.xml.xpath.XPath;
  42. import javax.xml.xpath.XPathConstants;
  43. import javax.xml.xpath.XPathExpression;
  44. import javax.xml.xpath.XPathExpressionException;
  45. import javax.xml.xpath.XPathFactory;
  46. import org.slf4j.Logger;
  47. import org.slf4j.LoggerFactory;
  48. import org.w3c.dom.Document;
  49. import org.xml.sax.SAXException;
  50. /**
  51. *
  52. * @author ETj (etj at geo-solutions.it)
  53. */
  54. public class GeoServerRESTStyleManager extends GeoServerRESTAbstractManager {
  55. private final static Logger LOGGER = LoggerFactory.getLogger(GeoServerRESTStyleManager.class);
  56. /**
  57. * Default constructor.
  58. *
  59. * @param restURL GeoServer REST API endpoint
  60. * @param username GeoServer REST API authorized username
  61. * @param password GeoServer REST API password for the former username
  62. */
  63. public GeoServerRESTStyleManager(URL restURL, String username, String password)
  64. throws IllegalArgumentException {
  65. super(restURL, username, password);
  66. }
  67. /**
  68. * Check if a Style exists in the configured GeoServer instance.
  69. * @param name the name of the style to check for.
  70. * @return <TT>true</TT> on HTTP 200, <TT>false</TT> on HTTP 404
  71. * @throws RuntimeException if any other HTTP code than 200 or 404 was retrieved.
  72. */
  73. public boolean existsStyle(String name) throws RuntimeException {
  74. return existsStyle(name, Util.DEFAULT_QUIET_ON_NOT_FOUND);
  75. }
  76. /**
  77. * Check if a Style exists in the configured GeoServer instance. User can choose if log a possible exception or not
  78. * @param name the name of the style to check for.
  79. * @param quietOnNotFound if true, mute exception if false is returned
  80. * @return <TT>true</TT> on HTTP 200, <TT>false</TT> on HTTP 404
  81. * @throws RuntimeException if any other HTTP code than 200 or 404 was retrieved.
  82. */
  83. public boolean existsStyle(String name, boolean quietOnNotFound) {
  84. String url = buildXmlUrl(null, name);
  85. String composed = Util.appendQuietOnNotFound(quietOnNotFound, url);
  86. return HTTPUtils.exists(composed , gsuser, gspass);
  87. }
  88. /**
  89. * Get summary info about all Styles.
  90. *
  91. * @return summary info about Styles as a {@link RESTStyleList}
  92. */
  93. public RESTStyleList getStyles() {
  94. String url = "/rest/styles.xml";
  95. if (LOGGER.isDebugEnabled()) {
  96. LOGGER.debug("### Retrieving Styles list from " + url);
  97. }
  98. String response = HTTPUtils.get(gsBaseUrl + url, gsuser, gspass);
  99. return RESTStyleList.build(response);
  100. }
  101. public RESTStyle getStyle(String name) {
  102. String url = buildXmlUrl(null, name);
  103. if (LOGGER.isDebugEnabled()) {
  104. LOGGER.debug("### Retrieving Style " + name + " from " + url);
  105. }
  106. String response = HTTPUtils.get(url, gsuser, gspass);
  107. return RESTStyle.build(response);
  108. }
  109. /**
  110. * Get the SLD body of a Style.
  111. */
  112. public String getSLD(String styleName) {
  113. String url = buildUrl(null, styleName, ".sld");
  114. if (LOGGER.isDebugEnabled()) {
  115. LOGGER.debug("### Retrieving SLD body from " + url);
  116. }
  117. return HTTPUtils.get( url, gsuser, gspass);
  118. }
  119. //=========================================================================
  120. // Workspaces
  121. //=========================================================================
  122. /**
  123. *
  124. * @since GeoServer 2.2
  125. */
  126. public boolean existsStyle(String workspace, String name) {
  127. return existsStyle(workspace, name, Util.DEFAULT_QUIET_ON_NOT_FOUND);
  128. }
  129. /**
  130. *
  131. * @since GeoServer 2.6
  132. */
  133. public boolean existsStyle(String workspace, String name, boolean quietOnNotFound) {
  134. String url = buildXmlUrl(workspace, name);
  135. String composed = Util.appendQuietOnNotFound(quietOnNotFound, url);
  136. return HTTPUtils.exists(composed , gsuser, gspass);
  137. }
  138. /**
  139. * Get summary info about Styles in a workspace.
  140. *
  141. * @return summary info about Styles as a {@link RESTStyleList}
  142. * @since GeoServer 2.2
  143. */
  144. public RESTStyleList getStyles(String workspace) {
  145. String url = "/rest/workspaces/"+workspace+"/styles.xml";
  146. if (LOGGER.isDebugEnabled()) {
  147. LOGGER.debug("### Retrieving Styles list from " + url);
  148. }
  149. String response = HTTPUtils.get(gsBaseUrl + url, gsuser, gspass);
  150. return RESTStyleList.build(response);
  151. }
  152. /**
  153. *
  154. * @since GeoServer 2.2
  155. */
  156. public RESTStyle getStyle(String workspace, String name) {
  157. String url = buildXmlUrl(workspace, name);
  158. if (LOGGER.isDebugEnabled()) {
  159. LOGGER.debug("### Retrieving Style " + name + " from " + url);
  160. }
  161. String response = HTTPUtils.get(url, gsuser, gspass);
  162. return RESTStyle.build(response);
  163. }
  164. /**
  165. * Get the SLD body of a Style.
  166. * @since GeoServer 2.2
  167. */
  168. public String getSLD(String workspace, String name) {
  169. String url = buildUrl(workspace, name, ".sld");
  170. if (LOGGER.isDebugEnabled()) {
  171. LOGGER.debug("### Retrieving SLD body from " + url);
  172. }
  173. return HTTPUtils.get(url, gsuser, gspass);
  174. }
  175. //=========================================================================
  176. // Publishing
  177. //=========================================================================
  178. /**
  179. * Store and publish a Style.
  180. *
  181. * @param sldBody the full SLD document as a String.
  182. *
  183. * @return <TT>true</TT> if the operation completed successfully.
  184. */
  185. public boolean publishStyle(String sldBody) {
  186. /*
  187. * This is the equivalent call with cUrl:
  188. *
  189. * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: application/vnd.ogc.sld+xml' \ -d @$FULLSLD \
  190. * http://$GSIP:$GSPORT/$SERVLET/rest/styles}
  191. */
  192. try {
  193. return publishStyle(sldBody, null);
  194. } catch (IllegalArgumentException e) {
  195. if (LOGGER.isErrorEnabled()) {
  196. LOGGER.error(e.getLocalizedMessage(), e);
  197. }
  198. }
  199. return false;
  200. }
  201. /**
  202. * Store and publish a Style, assigning it a name.
  203. *
  204. * @param sldBody the full SLD document as a String.
  205. * @param name the Style name.
  206. *
  207. * @return <TT>true</TT> if the operation completed successfully.
  208. * @throws IllegalArgumentException if the style body is null or empty.
  209. */
  210. public boolean publishStyle(final String sldBody, final String name)
  211. throws IllegalArgumentException {
  212. /*
  213. * This is the equivalent call with cUrl:
  214. *
  215. * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: application/vnd.ogc.sld+xml' \ -d @$FULLSLD \
  216. * http://$GSIP:$GSPORT/$SERVLET/rest/styles?name=name}
  217. */
  218. if (sldBody == null || sldBody.isEmpty()) {
  219. throw new IllegalArgumentException("The style body may not be null or empty");
  220. }
  221. String sUrl = buildPostUrl(null, name);
  222. final String result = HTTPUtils.post(sUrl, sldBody, "application/vnd.ogc.sld+xml", gsuser, gspass);
  223. return result != null;
  224. }
  225. /**
  226. * Store and publish a Style.
  227. *
  228. * @param sldFile the File containing the SLD document.
  229. *
  230. * @return <TT>true</TT> if the operation completed successfully.
  231. */
  232. public boolean publishStyle(File sldFile) {
  233. return publishStyle(sldFile, null);
  234. }
  235. /**
  236. * Store and publish a Style, assigning it a name.
  237. *
  238. * @param sldFile the File containing the SLD document.
  239. * @param name the Style name.
  240. *
  241. * @return <TT>true</TT> if the operation completed successfully.
  242. */
  243. public boolean publishStyle(File sldFile, String name) {
  244. String sUrl = buildPostUrl(null, name);
  245. LOGGER.debug("POSTing new style " + name + " to " + sUrl);
  246. String result = HTTPUtils.post(sUrl, sldFile, GeoServerRESTPublisher.Format.SLD.getContentType(), gsuser, gspass);
  247. return result != null;
  248. }
  249. /**
  250. * Store and publish a Style, assigning it a name and choosing the raw
  251. * format.
  252. *
  253. * @param sldBody the full SLD document as a String.
  254. * @param name the Style name.
  255. * @param raw the raw format
  256. *
  257. * @return <TT>true</TT> if the operation completed successfully.
  258. */
  259. public boolean publishStyle(final String sldBody, final String name, final boolean raw) {
  260. /*
  261. * This is the equivalent call with cUrl:
  262. *
  263. * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: application/vnd.ogc.sld+xml' \ -d @$FULLSLD \
  264. * http://$GSIP:$GSPORT/$SERVLET/rest/styles?name=$name&raw=$raw}
  265. */
  266. if (sldBody == null || sldBody.isEmpty()) {
  267. throw new IllegalArgumentException("The style body may not be null or empty");
  268. }
  269. StringBuilder sUrl = new StringBuilder(buildPostUrl(null, name));
  270. Util.appendParameter(sUrl, "raw", ""+raw);
  271. String contentType = GeoServerRESTPublisher.Format.SLD.getContentType();
  272. if(!this.checkSLD10Version(sldBody)){
  273. contentType = GeoServerRESTPublisher.Format.SLD_1_1_0.getContentType();
  274. }
  275. LOGGER.debug("POSTing new style " + name + " to " + sUrl + " using version: " + contentType);
  276. String result = HTTPUtils.post(sUrl.toString(), sldBody, contentType, gsuser, gspass);
  277. return result != null;
  278. }
  279. /**
  280. * Store and publish a Style, assigning it a name and choosing the raw
  281. * format.
  282. *
  283. * @param sldFile the File containing the SLD document.
  284. * @param name the Style name.
  285. * @param raw the raw format
  286. *
  287. * @return <TT>true</TT> if the operation completed successfully.
  288. */
  289. public boolean publishStyle(final File sldFile, final String name, final boolean raw) {
  290. /*
  291. * This is the equivalent call with cUrl:
  292. *
  293. * {@code curl -u admin:geoserver -XPOST \ -H 'Content-type: application/vnd.ogc.sld+xml' \ -d @$FULLSLD \
  294. * http://$GSIP:$GSPORT/$SERVLET/rest/styles?name=$name&raw=$raw}
  295. */
  296. StringBuilder sUrl = new StringBuilder(buildPostUrl(null, name));
  297. Util.appendParameter(sUrl, "raw", ""+raw);
  298. String contentType = GeoServerRESTPublisher.Format.SLD.getContentType();
  299. if(!this.checkSLD10Version(sldFile)){
  300. contentType = GeoServerRESTPublisher.Format.SLD_1_1_0.getContentType();
  301. }
  302. LOGGER.debug("POSTing new style " + name + " to " + sUrl + " using version: " + contentType);
  303. String result = HTTPUtils.post(sUrl.toString(), sldFile, contentType, gsuser, gspass);
  304. return result != null;
  305. }
  306. /**
  307. * Update a Style.
  308. *
  309. * @param sldFile the File containing the SLD document.
  310. * @param name the Style name.
  311. * @param raw the raw format
  312. *
  313. * @return <TT>true</TT> if the operation completed successfully.
  314. * @throws IllegalArgumentException if the style body or name are null or empty.
  315. */
  316. public boolean updateStyle(final File sldFile, final String name, final boolean raw)
  317. throws IllegalArgumentException {
  318. /*
  319. * This is the equivalent call with cUrl:
  320. *
  321. * {@code curl -u admin:geoserver -XPUT \ -H 'Content-type: application/vnd.ogc.sld+xml' \ -d @$FULLSLD \
  322. * http://$GSIP:$GSPORT/$SERVLET/rest/styles?name=$name&raw=$raw}
  323. */
  324. if (sldFile == null) {
  325. throw new IllegalArgumentException("Unable to updateStyle using a null parameter file");
  326. } else if (name == null || name.isEmpty()) {
  327. throw new IllegalArgumentException("The style name may not be null or empty");
  328. }
  329. StringBuilder sUrl = new StringBuilder(buildUrl(null, name, null));
  330. Util.appendParameter(sUrl, "raw", ""+raw);
  331. String contentType = GeoServerRESTPublisher.Format.SLD.getContentType();
  332. if(!this.checkSLD10Version(sldFile)){
  333. contentType = GeoServerRESTPublisher.Format.SLD_1_1_0.getContentType();
  334. }
  335. LOGGER.debug("PUTting style " + name + " to " + sUrl + " using version: " + contentType);
  336. String result = HTTPUtils.put(sUrl.toString(), sldFile, contentType, gsuser, gspass);
  337. return result != null;
  338. }
  339. /**
  340. * Update a Style.
  341. *
  342. * @param sldBody the new SLD document as a String.
  343. * @param name the Style name.
  344. * @param raw the raw format
  345. *
  346. * @return <TT>true</TT> if the operation completed successfully.
  347. * @throws IllegalArgumentException if the style body or name are null or empty.
  348. */
  349. public boolean updateStyle(final String sldBody, final String name, final boolean raw)
  350. throws IllegalArgumentException {
  351. /*
  352. * This is the equivalent call with cUrl:
  353. *
  354. * {@code curl -u admin:geoserver -XPUT \ -H 'Content-type: application/vnd.ogc.sld+xml' \ -d @$FULLSLD \
  355. * http://$GSIP:$GSPORT/$SERVLET/rest/styles?name=$name&raw=$raw}
  356. */
  357. if (sldBody == null || sldBody.isEmpty()) {
  358. throw new IllegalArgumentException("The style body may not be null or empty");
  359. } else if (name == null || name.isEmpty()) {
  360. throw new IllegalArgumentException("The style name may not be null or empty");
  361. }
  362. StringBuilder sUrl = new StringBuilder(buildUrl(null, name, null));
  363. Util.appendParameter(sUrl, "raw", ""+raw);
  364. String contentType = GeoServerRESTPublisher.Format.SLD.getContentType();
  365. if(!this.checkSLD10Version(sldBody)){
  366. contentType = GeoServerRESTPublisher.Format.SLD_1_1_0.getContentType();
  367. }
  368. LOGGER.debug("PUTting style " + name + " to " + sUrl + " using version: " + contentType);
  369. String result = HTTPUtils.put(sUrl.toString(), sldBody, contentType, gsuser, gspass);
  370. return result != null;
  371. }
  372. /**
  373. * Update a Style.
  374. *
  375. * @param sldBody the new SLD document as a String.
  376. * @param name the Style name to update.
  377. *
  378. * @return <TT>true</TT> if the operation completed successfully.
  379. * @throws IllegalArgumentException if the style body or name are null or empty.
  380. */
  381. public boolean updateStyle(final String sldBody, final String name)
  382. throws IllegalArgumentException {
  383. /*
  384. * This is the equivalent call with cUrl:
  385. *
  386. * {@code curl -u admin:geoserver -XPUT \ -H 'Content-type: application/vnd.ogc.sld+xml' \ -d @$FULLSLD \
  387. * http://$GSIP:$GSPORT/$SERVLET/rest/styles/$NAME}
  388. */
  389. if (sldBody == null || sldBody.isEmpty()) {
  390. throw new IllegalArgumentException("The style body may not be null or empty");
  391. } else if (name == null || name.isEmpty()) {
  392. throw new IllegalArgumentException("The style name may not be null or empty");
  393. }
  394. final String sUrl = buildUrl(null, name, null);
  395. final String result = HTTPUtils.put(sUrl, sldBody, "application/vnd.ogc.sld+xml", gsuser, gspass);
  396. return result != null;
  397. }
  398. /**
  399. * Update a Style.
  400. *
  401. * @param sldFile the File containing the SLD document.
  402. * @param name the Style name.
  403. *
  404. * @return <TT>true</TT> if the operation completed successfully.
  405. * @throws IllegalArgumentException if the sldFile file or name are null or name is empty.
  406. */
  407. public boolean updateStyle(final File sldFile, final String name)
  408. throws IllegalArgumentException {
  409. if (sldFile == null) {
  410. throw new IllegalArgumentException("Unable to updateStyle using a null parameter file");
  411. } else if (name == null || name.isEmpty()) {
  412. throw new IllegalArgumentException("The style name may not be null or empty");
  413. }
  414. final String sUrl = buildUrl(null, name, null);
  415. final String result = HTTPUtils.put(sUrl, sldFile,
  416. "application/vnd.ogc.sld+xml", gsuser, gspass);
  417. return result != null;
  418. }
  419. /**
  420. * Remove a Style.
  421. * <P>
  422. * The Style will be unpublished, and (optionally) the SLD file will be removed.
  423. *
  424. * @param styleName the name of the Style to remove.
  425. * @param purge remove the related SLD file from disk.
  426. *
  427. * @return <TT>true</TT> if the operation completed successfully.
  428. * @throws IllegalArgumentException if styleName is null or empty.
  429. */
  430. public boolean removeStyle(String styleName, final boolean purge)
  431. throws IllegalArgumentException {
  432. if (styleName == null || styleName.isEmpty())
  433. throw new IllegalArgumentException(
  434. "Check styleName parameter, it may never be null or empty");
  435. // check style name
  436. // TODO may we want to throw an exception instead of
  437. // change style name?
  438. if(styleName.contains(":"))
  439. LOGGER.warn("Style name is going to be changed ["+styleName+"]");
  440. styleName = styleName.replaceAll(":", "_");
  441. // currently REST interface does't support URLencoded URL
  442. // styleName = URLEncoder.encode(styleName);
  443. String sUrl = buildUrl(null, styleName, null);
  444. if (purge) {
  445. sUrl += "?purge=true";
  446. }
  447. return HTTPUtils.delete(sUrl, gsuser, gspass);
  448. }
  449. /**
  450. * Remove a Style.
  451. * <P>
  452. * The Style will be unpublished and the related SLD file will be removed.
  453. *
  454. * @param styleName the name of the Style to remove.
  455. *
  456. * @return <TT>true</TT> if the operation completed successfully.
  457. */
  458. public boolean removeStyle(String styleName) {
  459. try {
  460. return removeStyle(styleName, true);
  461. } catch (IllegalArgumentException e) {
  462. if (LOGGER.isErrorEnabled()) {
  463. LOGGER.error(e.getLocalizedMessage(), e);
  464. }
  465. }
  466. return false;
  467. }
  468. //=========================================================================
  469. // Publishing in workspace
  470. //=========================================================================
  471. /**
  472. * Store and publish a Style.
  473. *
  474. * @param sldBody the full SLD document as a String.
  475. *
  476. * @return <TT>true</TT> if the operation completed successfully.
  477. * @since GeoServer 2.2
  478. */
  479. public boolean publishStyleInWorkspace(final String workspace, String sldBody) {
  480. try {
  481. return publishStyleInWorkspace(workspace, sldBody, null);
  482. } catch (IllegalArgumentException e) {
  483. if (LOGGER.isErrorEnabled()) {
  484. LOGGER.error(e.getLocalizedMessage(), e);
  485. }
  486. }
  487. return false;
  488. }
  489. /**
  490. * Store and publish a Style, assigning it a name.
  491. *
  492. * @param sldBody the full SLD document as a String.
  493. * @param name the Style name.
  494. *
  495. * @return <TT>true</TT> if the operation completed successfully.
  496. * @throws IllegalArgumentException if the style body is null or empty.
  497. * @since GeoServer 2.2
  498. */
  499. public boolean publishStyleInWorkspace(final String workspace, final String sldBody, final String name)
  500. throws IllegalArgumentException {
  501. if (sldBody == null || sldBody.isEmpty()) {
  502. throw new IllegalArgumentException("The style body may not be null or empty");
  503. }
  504. String sUrl = buildPostUrl(workspace, name);
  505. final String result = HTTPUtils.post(sUrl, sldBody, "application/vnd.ogc.sld+xml", gsuser, gspass);
  506. return result != null;
  507. }
  508. /**
  509. * Store and publish a Style.
  510. *
  511. * @param sldFile the File containing the SLD document.
  512. *
  513. * @return <TT>true</TT> if the operation completed successfully.
  514. * @since GeoServer 2.2
  515. */
  516. public boolean publishStyleInWorkspace(final String workspace, File sldFile) {
  517. return publishStyleInWorkspace(workspace, sldFile, null);
  518. }
  519. /**
  520. * Store and publish a Style, assigning it a name.
  521. *
  522. * @param sldFile the File containing the SLD document.
  523. * @param name the Style name.
  524. *
  525. * @return <TT>true</TT> if the operation completed successfully.
  526. * @since GeoServer 2.2
  527. */
  528. public boolean publishStyleInWorkspace(final String workspace, File sldFile, String name) {
  529. String sUrl = buildPostUrl(workspace, name);
  530. LOGGER.debug("POSTing new style " + name + " to " + sUrl);
  531. String result = HTTPUtils.post(sUrl, sldFile, GeoServerRESTPublisher.Format.SLD.getContentType(), gsuser, gspass);
  532. return result != null;
  533. }
  534. /**
  535. * Update a Style.
  536. *
  537. * @param sldBody the new SLD document as a String.
  538. * @param name the Style name to update.
  539. *
  540. * @return <TT>true</TT> if the operation completed successfully.
  541. * @throws IllegalArgumentException if the style body or name are null or empty.
  542. * @since GeoServer 2.2
  543. */
  544. public boolean updateStyleInWorkspace(final String workspace, final String sldBody, final String name)
  545. throws IllegalArgumentException {
  546. if (sldBody == null || sldBody.isEmpty()) {
  547. throw new IllegalArgumentException("The style body may not be null or empty");
  548. } else if (name == null || name.isEmpty()) {
  549. throw new IllegalArgumentException("The style name may not be null or empty");
  550. }
  551. final String sUrl = buildUrl(workspace, name, null);
  552. final String result = HTTPUtils.put(sUrl, sldBody,
  553. "application/vnd.ogc.sld+xml", gsuser, gspass);
  554. return result != null;
  555. }
  556. /**
  557. * Update a Style.
  558. *
  559. * @param sldFile the File containing the SLD document.
  560. * @param name the Style name.
  561. *
  562. * @return <TT>true</TT> if the operation completed successfully.
  563. * @throws IllegalArgumentException if the sldFile file or name are null or name is empty.
  564. * @since GeoServer 2.2
  565. */
  566. public boolean updateStyleInWorkspace(final String workspace, final File sldFile, final String name)
  567. throws IllegalArgumentException {
  568. if (sldFile == null) {
  569. throw new IllegalArgumentException("Unable to updateStyle using a null parameter file");
  570. } else if (name == null || name.isEmpty()) {
  571. throw new IllegalArgumentException("The style name may not be null or empty");
  572. }
  573. final String sUrl = buildUrl(workspace, name, null);
  574. final String result = HTTPUtils.put(sUrl, sldFile,
  575. "application/vnd.ogc.sld+xml", gsuser, gspass);
  576. return result != null;
  577. }
  578. /**
  579. * Remove a Style.
  580. * <P>
  581. * The Style will be unpublished, and (optionally) the SLD file will be removed.
  582. *
  583. * @param styleName the name of the Style to remove.
  584. * @param purge remove the related SLD file from disk.
  585. *
  586. * @return <TT>true</TT> if the operation completed successfully.
  587. * @throws IllegalArgumentException if styleName is null or empty.
  588. * @since GeoServer 2.2
  589. */
  590. public boolean removeStyleInWorkspace(final String workspace, String styleName, final boolean purge)
  591. throws IllegalArgumentException {
  592. if (styleName == null || styleName.isEmpty())
  593. throw new IllegalArgumentException(
  594. "Check styleName parameter, it may never be null or empty");
  595. // check style name
  596. // TODO may we want to throw an exception instead of change style name?
  597. if(styleName.contains(":"))
  598. LOGGER.warn("Style name is going to be changed ["+styleName+"]");
  599. styleName = styleName.replaceAll(":", "_");
  600. styleName = URLEncoder.encode(styleName);
  601. String sUrl = buildUrl(workspace, styleName, null);
  602. if (purge) {
  603. sUrl += "?purge=true";
  604. }
  605. return HTTPUtils.delete(sUrl, gsuser, gspass);
  606. }
  607. /**
  608. * Remove a Style.
  609. * <P>
  610. * The Style will be unpublished and the related SLD file will be removed.
  611. *
  612. * @param styleName the name of the Style to remove.
  613. *
  614. * @return <TT>true</TT> if the operation completed successfully.
  615. * @since GeoServer 2.2
  616. */
  617. public boolean removeStyleInWorkspace(final String workspace, String styleName) {
  618. try {
  619. return removeStyleInWorkspace(workspace, styleName, true);
  620. } catch (IllegalArgumentException e) {
  621. if (LOGGER.isErrorEnabled()) {
  622. LOGGER.error(e.getLocalizedMessage(), e);
  623. }
  624. }
  625. return false;
  626. }
  627. //=========================================================================
  628. // Util methods
  629. //=========================================================================
  630. /**
  631. * Creates a URL for the given stylename with the name in querystring
  632. * @param workspace nullable workspace name
  633. * @param name style name
  634. * @return
  635. */
  636. protected String buildPostUrl(final String workspace, String name) {
  637. StringBuilder sUrl = new StringBuilder(gsBaseUrl.toString()).append("/rest");
  638. if(workspace != null)
  639. sUrl.append("/workspaces/").append(workspace);
  640. sUrl.append("/styles");
  641. if ( name != null && !name.isEmpty()) {
  642. sUrl.append("?name=").append(URLEncoder.encode(name));
  643. }
  644. return sUrl.toString();
  645. }
  646. protected String buildXmlUrl(final String workspace, final String name) {
  647. return buildUrl(workspace, name, ".xml");
  648. }
  649. /**
  650. * Creates a URL for the given stylename with the name in the REST path
  651. * @param workspace nullable workspace name
  652. * @param name style name
  653. * @param ext nullable output extension (e.g. ".xml" ".sld")
  654. */
  655. protected String buildUrl(final String workspace, final String name, final String ext) {
  656. StringBuilder sUrl = new StringBuilder(gsBaseUrl.toString()).append("/rest");
  657. if(workspace != null)
  658. sUrl.append("/workspaces/").append(workspace);
  659. sUrl.append("/styles/").append(URLEncoder.encode(name));
  660. if(ext != null)
  661. sUrl.append(ext);
  662. return sUrl.toString();
  663. }
  664. private boolean checkSLD10Version(String sldBody) {
  665. boolean result = false;
  666. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  667. try {
  668. DocumentBuilder builder = factory.newDocumentBuilder();
  669. InputStream stream = new ByteArrayInputStream(sldBody.getBytes(Charset.forName("UTF-8")));
  670. Document doc = builder.parse(stream);
  671. result = this.checkSLD10Version(doc);
  672. } catch (SAXException ex) {
  673. LOGGER.error("Error parsing SLD file: " + ex);
  674. } catch (IOException ex) {
  675. LOGGER.error("Error parsing SLD file: " + ex);
  676. } catch (ParserConfigurationException ex) {
  677. LOGGER.error("Error parsing SLD file: " + ex);
  678. }
  679. return result;
  680. }
  681. private boolean checkSLD10Version(File fileSLD) {
  682. boolean result = false;
  683. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  684. try {
  685. DocumentBuilder builder = factory.newDocumentBuilder();
  686. Document doc = builder.parse(fileSLD);
  687. result = this.checkSLD10Version(doc);
  688. } catch (SAXException ex) {
  689. LOGGER.error("Error parsing SLD file: " + ex);
  690. } catch (IOException ex) {
  691. LOGGER.error("Error parsing SLD file: " + ex);
  692. } catch (ParserConfigurationException ex) {
  693. LOGGER.error("Error parsing SLD file: " + ex);
  694. }
  695. return result;
  696. }
  697. private boolean checkSLD10Version(Document doc) {
  698. boolean result = false;
  699. try {
  700. XPathFactory xPathfactory = XPathFactory.newInstance();
  701. XPath xpath = xPathfactory.newXPath();
  702. XPathExpression expr = xpath.compile("//@version='1.0.0'");
  703. result = (Boolean)expr.evaluate(doc, XPathConstants.BOOLEAN);
  704. } catch (XPathExpressionException ex) {
  705. LOGGER.error("Error parsing SLD file: " + ex);
  706. }
  707. return result;
  708. }
  709. }