001    /***************************************************************************/
002    /*  Copyright (C) 2010-2011, Sebastian Hellmann                            */
003    /*  Note: If you need parts of NLP2RDF in another licence due to licence   */
004    /*  incompatibility, please mail hellmann@informatik.uni-leipzig.de        */
005    /*                                                                         */
006    /*  This file is part of NLP2RDF.                                          */
007    /*                                                                         */
008    /*  NLP2RDF is free software; you can redistribute it and/or modify        */
009    /*  it under the terms of the GNU General Public License as published by   */
010    /*  the Free Software Foundation; either version 3 of the License, or      */
011    /*  (at your option) any later version.                                    */
012    /*                                                                         */
013    /*  NLP2RDF is distributed in the hope that it will be useful,             */
014    /*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
015    /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the           */
016    /*  GNU General Public License for more details.                           */
017    /*                                                                         */
018    /*  You should have received a copy of the GNU General Public License      */
019    /*  along with this program. If not, see <http://www.gnu.org/licenses/>.   */
020    /***************************************************************************/
021    
022    package org.nlp2rdf.webservice;
023    
024    import com.hp.hpl.jena.ontology.OntModel;
025    import com.hp.hpl.jena.ontology.OntModelSpec;
026    import com.hp.hpl.jena.rdf.model.ModelFactory;
027    import com.hp.hpl.jena.rdf.model.RDFWriter;
028    import com.jamonapi.Monitor;
029    import com.jamonapi.MonitorFactory;
030    import org.nlp2rdf.core.ErrorHandling;
031    import org.slf4j.Logger;
032    import org.slf4j.LoggerFactory;
033    
034    import javax.servlet.ServletException;
035    import javax.servlet.http.HttpServlet;
036    import javax.servlet.http.HttpServletRequest;
037    import javax.servlet.http.HttpServletResponse;
038    import java.io.*;
039    import java.security.InvalidParameterException;
040    
041    
042    public abstract class NIFServlet extends HttpServlet {
043        private static Logger log = LoggerFactory.getLogger(NIFServlet.class);
044        private int counter = 0;
045    
046        @Override
047        protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
048            handle(httpServletRequest, httpServletResponse);
049        }
050    
051        @Override
052        protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
053            handle(httpServletRequest, httpServletResponse);
054        }
055    
056        public abstract void execute(NIFParameters nifParameters, OntModel diff) throws Exception;
057    
058        /**
059         * this method answers GET and POST requests, which are treated the same.
060         * - Validates parameters
061         * - does the work (execute)
062         *
063         * @param httpServletRequest
064         * @param httpServletResponse
065         * @throws ServletException
066         * @throws IOException
067         */
068        private void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
069    
070            //this is the model that will be filled in the execute method
071            OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM, ModelFactory.createDefaultModel());
072            String requestUrl = httpServletRequest.getRequestURL().toString();
073            NIFParameters nifParameters = null;
074            try {
075    
076                //Validate and normalize input
077                Monitor mon = MonitorFactory.getTimeMonitor("NIFParameters.getInstance").start();
078                nifParameters = NIFParameters.getInstance(httpServletRequest);
079                log.debug("NIFParameters Object created: " + logMonitor(mon.stop()));
080    
081                //execute the task
082                mon = MonitorFactory.getTimeMonitor("NIFServlet.execute").start();
083    
084                execute(nifParameters, model);
085                log.debug("NIF Component executed task: " + logMonitor(mon.stop()));
086                long triplesFromComponent = model.size();
087    
088                //output is an inofficial parameter, fully merges input and output
089                long triplesFromInput = 0;
090                if (nifParameters.inputWasRDF() && nifParameters.getOutput().equals("full")) {
091                    OntModel inputModel = nifParameters.getInputAsOntModel();
092                    //merge
093                    model.add(inputModel);
094                    triplesFromInput = inputModel.size();
095                }
096    
097    
098                //write the response
099                write(httpServletResponse, model, nifParameters.getFormat());
100                log.info("output (" + nifParameters.getFormat() + ", " + nifParameters.getOutput() + ") written, triples from input: " + triplesFromInput + ", added by component: " + triplesFromComponent);
101                writeJamonLog();
102    
103            } catch (IllegalArgumentException e) {
104                String msg = e.getMessage() + printParameterMap(httpServletRequest);
105                log.error(msg);
106                eu.lod2.nlp2rdf.schema.error.Error fatalerror = ErrorHandling.createError(true, requestUrl, msg, model);
107                fatalerror.addSource(requestUrl);
108                if (nifParameters != null) {
109                    write(httpServletResponse, model, nifParameters.getFormat());
110                } else {
111                    write(httpServletResponse, model, "rdfxml");
112                }
113    
114            } catch (Exception e) {
115                String msg = "An error occured: " + e.getMessage() + printParameterMap(httpServletRequest);
116                log.error(msg, e);
117                eu.lod2.nlp2rdf.schema.error.Error fatalerror = ErrorHandling.createError(true, requestUrl, msg, model);
118                fatalerror.addSource(requestUrl);
119                if (nifParameters != null) {
120                    write(httpServletResponse, model, nifParameters.getFormat());
121                } else {
122                    write(httpServletResponse, model, "rdfxml");
123                }
124            }
125        }
126    
127        protected static String logMonitor(Monitor m) {
128            return "needed: " + m.getLastValue() + " ms. (" + m.getTotal() + " total)";
129        }
130    
131        protected void write(HttpServletResponse httpServletResponse, OntModel out, String format) throws IOException {
132            if (format.equalsIgnoreCase("rdfxml")) {
133                write(httpServletResponse, out, "RDF/XML", "application/rdf+xml");
134            } else if (format.equalsIgnoreCase("turtle")) {
135                write(httpServletResponse, out, "TURTLE", "text/rdf+n3");
136            } else if (format.equalsIgnoreCase("n3")) {
137                write(httpServletResponse, out, "N3", "text/rdf+n3");
138            } else if (format.equalsIgnoreCase("ntriples")) {
139                write(httpServletResponse, out, "N-TRIPLE", "text/rdf+n3");
140            } else if (format.equalsIgnoreCase("json")) {
141                throw new InvalidParameterException("There is no JSON output implemented at the moment. Sorry!");
142            }
143    
144        }
145    
146        protected void write(HttpServletResponse httpServletResponse, OntModel out, String jenaFormat, String contentType) throws IOException {
147            httpServletResponse.setContentType(contentType);
148            httpServletResponse.setCharacterEncoding("UTF-8");
149    
150            //there are some problems with dl-learner, if individuals are not typed correctly
151            /*for (ExtendedIterator<Individual> it = out.listIndividuals(); it.hasNext(); ) {
152                it.next().addOntClass(OWL.Thing);
153            }
154            for (ExtendedIterator<ObjectProperty> it = out.listObjectProperties(); it.hasNext(); ) {
155                it.next().addRDFType(OWL.ObjectProperty);
156            }
157            for (ExtendedIterator<DatatypeProperty> it = out.listDatatypeProperties(); it.hasNext(); ) {
158                it.next().addRDFType(OWL.DatatypeProperty);
159            }
160            for (ExtendedIterator<OntClass> it = out.listClasses(); it.hasNext(); ) {
161                it.next().addRDFType(OWL.Class);
162            } */
163    
164            out.setNsPrefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
165            out.setNsPrefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
166            out.setNsPrefix("owl", "http://www.w3.org/2002/07/owl#");
167    
168    
169            out.setNsPrefix("sso", "http://nlp2rdf.lod2.eu/schema/sso/");
170            out.setNsPrefix("str", "http://nlp2rdf.lod2.eu/schema/string/");
171            out.setNsPrefix("topic", "http://nlp2rdf.lod2.eu/schema/topic/");
172            out.setNsPrefix("error", "http://nlp2rdf.lod2.eu/schema/error/");
173    
174    
175            out.setNsPrefix("olia", "http://purl.org/olia/olia.owl#");
176            out.setNsPrefix("olia-top", "http://purl.org/olia/olia-top.owl#");
177            out.setNsPrefix("olia_system", "http://purl.org/olia/system.owl#");
178    
179            out.setNsPrefix("penn", "http://purl.org/olia/penn.owl#");
180            out.setNsPrefix("penn-syntax", "http://purl.org/olia/penn-syntax.owl#");
181            out.setNsPrefix("stanford", "http://purl.org/olia/stanford.owl#");
182    
183            out.setNsPrefix("brown", "http://purl.org/olia/brown.owl#");
184    
185    
186            //this is the printer where the output has to be on
187            PrintWriter pw = httpServletResponse.getWriter();
188            RDFWriter writer = out.getWriter(jenaFormat);
189            writer.setProperty("showXmlDeclaration", "true");
190            //writer.setProperty("showDoctypeDeclaration", "true");
191            writer.write(out, pw, "");
192            pw.close();
193    
194    
195        }
196    
197    
198        public static String printParameterMap(HttpServletRequest httpServletRequest) {
199    
200            log.error("printing map:\n" +
201                    httpServletRequest.getRequestURL() + "\n" +
202                    httpServletRequest.getContextPath() + "\n" +
203                    httpServletRequest + "\n" +
204                    "parameters: " + httpServletRequest.getParameterMap().keySet() + "\n" +
205                    "");
206            StringBuffer buf = new StringBuffer();
207            for (Object key : httpServletRequest.getParameterMap().keySet()) {
208                buf.append("\nParameter: " + key + " Values: ");
209                for (String s : httpServletRequest.getParameterValues((String) key)) {
210                    buf.append(((s.length() > 200) ? s.substring(0, 200) + "..." : s) + " ");
211                }
212            }
213            return buf.toString();
214        }
215    
216        public synchronized void writeJamonLog() {
217            counter++;
218            if (counter % 100 == 0) {
219                try {
220                    // Create file
221                    FileWriter fstream = new FileWriter("log/jamonlog.html");
222                    BufferedWriter out = new BufferedWriter(fstream);
223                    out.write(MonitorFactory.getReport());
224                    //Close the output stream
225                    out.close();
226                } catch (Exception e) {//Catch exception if any
227                    //we don't care
228                    //System.err.println("Error: " + e.getMessage());
229                }
230            }
231        }
232    
233    }