/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.constellation.ws.embedded; import org.apache.sis.util.logging.Logging; import org.apache.sis.xml.MarshallerPool; import org.constellation.util.Util; import org.geotoolkit.image.io.XImageIO; import org.geotoolkit.internal.io.IOUtilities; import javax.imageio.ImageReader; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.StringReader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.io.IOUtils; import org.geotoolkit.util.FileUtilities; /** * Launches a Grizzly server in a thread at the beginning of the testing process * and kill it when it is done. * * @version $Id$ * * @author Cédric Briançon (Geomatys) * @since 0.3 */ public abstract class AbstractGrizzlyServer { protected static final Logger LOGGER = Logging.getLogger("org.constellation.ws.embedded"); /** * The grizzly server that will received some HTTP requests. */ protected static GrizzlyThread grizzly = null; protected static MarshallerPool pool; public static void initServer(final String[] resourcePackages, final Map<String, Object> soapServices) { initServer(resourcePackages, soapServices, null); } /** * Initialize the Grizzly server, on which WCS and WMS requests will be sent, * and defines a PostGrid data provider. */ public static void initServer(final String[] resourcePackages, final Map<String, Object> soapServices, final String uriSuffix) { // Protective test in order not to launch a new instance of the grizzly server for // each sub classes. if (grizzly != null) { LOGGER.info("GRIZZLY is not shutDown"); return; } /* Instanciates the Grizzly server, but not start it at this moment. * The implementation waits for the data provider to be defined for * starting the server. */ grizzly = new GrizzlyThread(resourcePackages, soapServices, uriSuffix); // Starting the grizzly server grizzly.start(); } /** * Stop the grizzly server, if it is still alive. */ public static void finish() { if (grizzly != null) { if (grizzly.isAlive()) { grizzly.cstlServer.shutdown(); grizzly.interrupt(); } File f = new File("derby.log"); if (f.exists()) { f.delete(); } grizzly = null; } } public void waitForStart() throws Exception { boolean ex = true; int cpt = 0; while (ex) { Thread.sleep(1 * 2000); final URL u; final String suffix; if (grizzly.getUriSuffix() != null) { suffix = "/" + grizzly.getUriSuffix(); } else { suffix = ""; } if (grizzly != null && grizzly.getCurrentPort() != null) { u = new URL("http://localhost:" + grizzly.getCurrentPort() + suffix + "/1/OGC/spec/list"); } else { u = new URL("http://localhost:9090//1/OGC/spec/list"); } ex = false; URLConnection conec = u.openConnection(); try { conec.getInputStream(); } catch (IOException e) { ex = true; } if (cpt == 100) { throw new Exception("The grizzly server never start"); } cpt++; } } public void waitForSoapStart(String instance) throws Exception { waitForSoapStart(instance, 100); } public void waitForSoapStart(String instance, int max) throws Exception { boolean ex = true; int cpt = 0; while (ex) { Thread.sleep(1 * 2000); final URL u; final String suffix; if (grizzly.getUriSuffix() != null) { suffix = "/" + grizzly.getUriSuffix(); } else { suffix = ""; } if (grizzly != null && grizzly.getCurrentPortSoap()!= null) { u = new URL("http://localhost:" + grizzly.getCurrentPortSoap() + suffix + "/" + instance + "?wsdl"); } else { u = new URL("http://localhost:9090/1/user/access"); } ex = false; URLConnection conec = u.openConnection(); try { conec.getInputStream(); } catch (IOException e) { ex = true; } if (cpt == max) { throw new Exception("The grizzly server never start"); } cpt++; } } /** * Thread that launches a Grizzly server in a separate thread. * Requests will be done on this working server. */ protected static class GrizzlyThread extends Thread { private final CstlEmbeddedService cstlServer; private final Map<String, Object> soapServices; public GrizzlyThread(final String[] resourcePackages, final Map<String, Object> soapServices) { this(resourcePackages, soapServices, null); } public GrizzlyThread(final String[] resourcePackages, final Map<String, Object> soapServices, final String uriSuffix) { this.soapServices = soapServices; if (resourcePackages != null) { cstlServer = new CstlEmbeddedService(new String[]{}, resourcePackages, uriSuffix); } else { cstlServer = new CstlEmbeddedService(new String[]{}, uriSuffix); } } public Integer getCurrentPort() { return cstlServer.currentPort; } public Integer getCurrentPortSoap() { return cstlServer.portsoap; } public String getUriSuffix() { return cstlServer.uriSuffix; } /** * Runs a Grizzly server for five minutes. */ @Override public void run() { cstlServer.duration = 5*60*1000; cstlServer.findAvailablePort = true; if (soapServices != null) { cstlServer.serviceInstanceSOAP.putAll(soapServices); } cstlServer.runAll(); } } protected static String getStringResponse(final URLConnection conec) throws UnsupportedEncodingException, IOException { InputStream is; if (((HttpURLConnection)conec).getResponseCode() == 200) { is = conec.getInputStream(); } else { is = ((HttpURLConnection)conec).getErrorStream(); } final StringWriter sw = new StringWriter(); final BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); char [] buffer = new char[1024]; int size; while ((size = in.read(buffer, 0, 1024)) > 0) { sw.append(new String(buffer, 0, size)); } String xmlResult = sw.toString(); return xmlResult; } /** * Already in FileUtilities ??? */ protected static String getStringFromFile(String filePath) throws UnsupportedEncodingException, IOException { final StringWriter sw = new StringWriter(); final BufferedReader in = new BufferedReader(new InputStreamReader(Util.getResourceAsStream(filePath), "UTF-8")); char [] buffer = new char[1024]; int size; while ((size = in.read(buffer, 0, 1024)) > 0) { sw.append(new String(buffer, 0, size)); } String xmlExpResult = sw.toString(); //we unformat the expected result xmlExpResult = xmlExpResult.replace("\n", ""); return xmlExpResult; } protected static void postRequestFile(URLConnection conec, String filePath, String contentType) throws IOException { conec.setDoOutput(true); conec.setRequestProperty("Content-Type", contentType); final OutputStreamWriter wr = new OutputStreamWriter(conec.getOutputStream()); final InputStream is = Util.getResourceAsStream(filePath); final StringWriter sw = new StringWriter(); final BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); char[] buffer = new char[1024]; int size; while ((size = in.read(buffer, 0, 1024)) > 0) { sw.append(new String(buffer, 0, size)); } wr.write(sw.toString()); wr.flush(); in.close(); } protected static void putRequestFile(URLConnection conec, String filePath, String contentType) throws IOException { HttpURLConnection httpCon = (HttpURLConnection) conec; httpCon.setRequestMethod("PUT"); conec.setDoOutput(true); conec.setRequestProperty("Content-Type", contentType); final OutputStreamWriter wr = new OutputStreamWriter(conec.getOutputStream()); final InputStream is = Util.getResourceAsStream(filePath); final StringWriter sw = new StringWriter(); final BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); char[] buffer = new char[1024]; int size; while ((size = in.read(buffer, 0, 1024)) > 0) { sw.append(new String(buffer, 0, size)); } wr.write(sw.toString()); wr.flush(); in.close(); } protected static void postRequestFile(URLConnection conec, String filePath) throws IOException { postRequestFile(conec, filePath, "text/xml"); } protected static void putRequestFile(URLConnection conec, String filePath) throws IOException { putRequestFile(conec, filePath, "text/xml"); } protected static void postRequestPlain(URLConnection conec, String request) throws IOException { conec.setDoOutput(true); conec.setRequestProperty("Content-Type", "text/plain"); final OutputStreamWriter wr = new OutputStreamWriter(conec.getOutputStream()); wr.write(request); wr.flush(); } /** * Returned the {@link BufferedImage} from an URL requesting an image. * * @param url The url of a request of an image. * @param mime The mime type of the image to return. * * @return The {@link BufferedImage} or {@code null} if an error occurs. * @throws IOException */ protected static BufferedImage getImageFromURL(final URL url, final String mime) throws IOException { // Try to get the image from the url. final InputStream in = url.openStream(); final ImageReader reader = XImageIO.getReaderByMIMEType(mime, in, true, true); final BufferedImage image = reader.read(0); XImageIO.close(reader); reader.dispose(); // For debugging, uncomment the JFrame creation and the Thread.sleep further, // in order to see the image in a popup. // javax.swing.JFrame frame = new javax.swing.JFrame(); // frame.setContentPane(new javax.swing.JLabel(new javax.swing.ImageIcon(image))); // frame.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); // frame.pack(); // frame.setVisible(true); // try { // Thread.sleep(5 * 1000); // frame.dispose(); // } catch (InterruptedException ex) { // assumeNoException(ex); // } return image; } protected static BufferedImage getImageFromPostKvp(final URL url, final Map<String, String> parameters, final String mime) throws IOException { final URLConnection conec = url.openConnection(); conec.setDoOutput(true); conec.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); final OutputStreamWriter wr = new OutputStreamWriter(conec.getOutputStream()); final StringBuilder sb = new StringBuilder(); for (Entry<String, String> entry : parameters.entrySet()) { sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&"); } sb.deleteCharAt(sb.length() -1); wr.write(sb.toString()); wr.flush(); // Try to get the image from the url. final InputStream in = conec.getInputStream(); final ImageReader reader = XImageIO.getReaderByMIMEType(mime, in, true, true); final BufferedImage image = reader.read(0); XImageIO.close(reader); reader.dispose(); // For debugging, uncomment the JFrame creation and the Thread.sleep further, // in order to see the image in a popup. // javax.swing.JFrame frame = new javax.swing.JFrame(); // frame.setContentPane(new javax.swing.JLabel(new javax.swing.ImageIcon(image))); // frame.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); // frame.pack(); // frame.setVisible(true); // try { // Thread.sleep(5 * 1000); // frame.dispose(); // } catch (InterruptedException ex) { // assumeNoException(ex); // } return image; } /** * Initializes the data directory in unzipping the jar containing the resources * into a temporary directory. * * @return The root output directory where the data are unzipped. * @throws IOException */ public static File initDataDirectory() throws IOException { final ClassLoader classloader = Thread.currentThread().getContextClassLoader(); String styleResource = classloader.getResource("org/constellation/ws/embedded/wms111/styles").getFile(); if (styleResource.indexOf('!') != -1) { styleResource = styleResource.substring(0, styleResource.indexOf('!')); } if (styleResource.startsWith("file:")) { styleResource = styleResource.substring(5); } final File styleJar = new File(styleResource); if (!styleJar.exists()) { throw new IOException("Unable to find the style folder: "+ styleJar); } final File tmpDir = new File(System.getProperty("java.io.tmpdir")); File outputDir = new File(tmpDir, "Constellation"); if (!outputDir.exists()) { outputDir.mkdir(); } if (styleJar.isDirectory()) { FileUtilities.copy(styleJar, outputDir); } else { final InputStream in = new FileInputStream(styleJar); IOUtilities.unzip(in, outputDir); in.close(); } return outputDir; } protected static void postRequestObject(URLConnection conec, Object request) throws IOException, JAXBException { postRequestObject(conec, request, pool); } protected static void postRequestObject(URLConnection conec, Object request, MarshallerPool pool) throws IOException, JAXBException { conec.setDoOutput(true); conec.setRequestProperty("Content-Type", "application/xml"); final OutputStreamWriter wr = new OutputStreamWriter(conec.getOutputStream()); final StringWriter sw = new StringWriter(); Marshaller marshaller = pool.acquireMarshaller(); marshaller.marshal(request, sw); wr.write(sw.toString()); wr.flush(); } protected static void putRequestObject(URLConnection conec, Object request, MarshallerPool pool) throws IOException, JAXBException { HttpURLConnection httpCon = (HttpURLConnection) conec; httpCon.setRequestMethod("PUT"); conec.setDoOutput(true); conec.setRequestProperty("Content-Type", "application/xml"); final OutputStreamWriter wr = new OutputStreamWriter(conec.getOutputStream()); final StringWriter sw = new StringWriter(); Marshaller marshaller = pool.acquireMarshaller(); marshaller.marshal(request, sw); wr.write(sw.toString()); wr.flush(); } protected static Object unmarshallResponsePut(final URLConnection conec) throws JAXBException, IOException { HttpURLConnection httpCon = (HttpURLConnection) conec; httpCon.setRequestMethod("PUT"); return unmarshallStream(conec.getInputStream()); } protected static Object unmarshallResponsePost(final URLConnection conec) throws JAXBException, IOException { HttpURLConnection httpCon = (HttpURLConnection) conec; httpCon.setRequestMethod("POST"); return unmarshallStream(conec.getInputStream()); } protected static Object unmarshallResponseDelete(final URLConnection conec) throws JAXBException, IOException { HttpURLConnection httpCon = (HttpURLConnection) conec; httpCon.setRequestMethod("DELETE"); return unmarshallStream(conec.getInputStream()); } protected static Object unmarshallResponse(final URLConnection conec) throws JAXBException, IOException { return unmarshallStream(conec.getInputStream()); } protected static Object unmarshallResponse(final URL url) throws JAXBException, IOException { final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); InputStream is; if (conn.getResponseCode() == 200) { is = conn.getInputStream(); } else { is = conn.getErrorStream(); } return unmarshallStream(is); } private static Object unmarshallStream(final InputStream is) throws IOException, JAXBException { //JDK-8 : ensure xml reader are allowed to access external DTD files when needed System.setProperty("javax.xml.accessExternalSchema", "all"); System.setProperty("javax.xml.accessExternalDTD", "all"); Unmarshaller unmarshaller = pool.acquireUnmarshaller(); StringWriter writer = new StringWriter(); IOUtils.copy(is, writer, "UTF-8"); Object obj; try { obj = unmarshaller.unmarshal(new StringReader(writer.toString())); pool.recycle(unmarshaller); } catch (JAXBException ex) { LOGGER.log(Level.WARNING, "JAXB Error received while trying to read:{0}", writer.toString()); throw ex; } if (obj instanceof JAXBElement) { obj = ((JAXBElement) obj).getValue(); } return obj; } protected static String removeUpdateSequence(final String xml) { String s = xml; s = s.replaceAll("updateSequence=\"[^\"]*\" ", ""); return s; } /** FOR SOAP TODO see if well need it public void waitForStart() throws Exception { final URL u = new URL("http://localhost:9191/wps/wsdl?"); boolean ex = true; while (ex) { Thread.sleep(1 * 1000); ex = false; URLConnection conec = u.openConnection(); try { conec.getInputStream(); } catch (ConnectException e) { ex = true; } } } */ }