Java tutorial
package uk.ac.susx.tag.method51.webapp.handler; /* * #%L * CodingInstanceHandler.java - method51 - University of Sussex - 2,013 * %% * Copyright (C) 2013 - 2014 University of Sussex * %% * 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. * #L% */ import org.apache.http.*; import org.apache.http.client.HttpClient; import org.apache.http.client.HttpResponseException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.ContentType; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.eclipse.jetty.server.Request; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.ac.susx.tag.method51.core.coding.Coder; import uk.ac.susx.tag.method51.core.organise.Job; import uk.ac.susx.tag.method51.core.params.codec.DecodeException; import uk.ac.susx.tag.method51.core.params.codec.EncodeException; import uk.ac.susx.tag.method51.twitter.params.MySQLConnectionParams; import uk.ac.susx.tag.method51.webapp.jetty.RequestException; import uk.ac.susx.tag.method51.webapp.params.standardvalidators.NonEmptyStringValidator; import uk.ac.susx.tag.method51.webapp.params.DoSomethingAfterValidatingMyParams; import uk.ac.susx.tag.method51.webapp.params.Params; import uk.ac.susx.tag.method51.webapp.params.standardvalidators.AllowedValidator; import uk.ac.susx.tag.method51.webapp.params.standardvalidators.BooleanValidator; import uk.ac.susx.tag.method51.webapp.server.CodingServer; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.net.ServerSocket; import java.net.URI; import java.net.URISyntaxException; import java.util.*; import static org.apache.commons.io.FilenameUtils.concat; import static uk.ac.susx.tag.method51.core.params.Params.instance; /** * Created with IntelliJ IDEA. * User: sw206 * Date: 19/06/2013 * Time: 16:19 * To change this template use File | Settings | File Templates. */ public class CodingInstanceHandler extends AbstractJobHandler<CodingInstanceHandler.Options> { private static final Logger LOG = LoggerFactory.getLogger(CodingInstanceHandler.class); private Set<Integer> portRange; private final String modelsFolder; public CodingInstanceHandler(File optsFile) throws IOException, DecodeException, EncodeException { super(Options.class, optsFile, "coding-instances"); modelsFolder = options.modelsFolder.get(); if (options.instancePortRange.get().size() == 2) { portRange = new HashSet<>(); int begin = options.instancePortRange.get().get(0); int end = options.instancePortRange.get().get(1); for (int i = begin; i < end; ++i) { portRange.add(i); } } else { portRange = new HashSet<>(options.instancePortRange.get()); } } @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { target = target.replaceFirst(options.serverLoc.get(), ""); if ("/delete".equals(target)) { deleteJob(target, baseRequest, request, response); } else if ("/rename".equals(target)) { renameJob(target, baseRequest, request, response); } else if (!handleDefaultJobRequests(target, baseRequest, request, response)) { if ("/start_instance".equals(target)) { startInstance(target, baseRequest, request, response); } else if (target.startsWith("/coding")) { coding(target, baseRequest, request, response); } else if (target.equals("/list")) { list(target, baseRequest, request, response); } else { notFound(target, response); } } baseRequest.setHandled(true); } /** * Re-issue the request to an instance. * * @param target * @param baseRequest * @param request * @param response * @throws IOException */ private void coding(final String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { new DoSomethingWithTheSpecifiedJobID(request, response) { public void something(String jid) throws IOException { Integer port = project.m51(jid).getPort(); //int port = ((Number)j.getMeta("port")).intValue(); HttpClient httpclient = new DefaultHttpClient(); String method = request.getMethod(); String target = "/coding" + request.getParameter("_target"); URIBuilder builder = new URIBuilder(); Set<String> ignore = new HashSet<>(); ignore.add("id"); ignore.add("_target"); builder.setHost("localhost").setScheme("http").setPort(port).setPath(target); try { HttpUriRequest uriRequest; if ("GET".equals(method)) { for (Map.Entry<String, String[]> e : request.getParameterMap().entrySet()) { String key = e.getKey(); if (!ignore.contains(key)) { builder.setParameter(e.getKey(), e.getValue()[0]); } } URI uri = builder.build(); uriRequest = new HttpGet(uri); } else { URI uri = builder.build(); List<NameValuePair> params = new ArrayList<>(); for (Map.Entry<String, String[]> e : request.getParameterMap().entrySet()) { String key = e.getKey(); if (!ignore.contains(key)) { params.add(new BasicNameValuePair(key, e.getValue()[0])); } } uriRequest = new HttpPost(uri); ((HttpPost) uriRequest).setEntity(new UrlEncodedFormEntity(params)); } LOG.info("re-issuing request: {}", uriRequest.toString()); HttpResponse r = httpclient.execute(uriRequest); StatusLine statusLine = r.getStatusLine(); HttpEntity entity = r.getEntity(); if (statusLine.getStatusCode() >= 400) { try { ContentType contentType = ContentType.get(entity); String responseBody = EntityUtils.toString(entity, contentType.getCharset()); throw new RequestException(statusLine.getReasonPhrase() + responseBody, statusLine.getStatusCode()); } catch (IOException | ParseException | NullPointerException e) { EntityUtils.consume(entity); throw new RequestException(statusLine.getReasonPhrase(), statusLine.getStatusCode()); } } response.setStatus(statusLine.getStatusCode()); ContentType contentType = ContentType.get(entity); if (contentType == null) { error("null content type!", response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } else { String responseBody = EntityUtils.toString(entity, contentType.getCharset()); response.setContentType(contentType.toString()); response.setCharacterEncoding(contentType.getCharset().toString()); response.getWriter().print(responseBody); } } catch (URISyntaxException e) { error(e.getMessage(), response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } } }; } private void list(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { File f = new File(modelsFolder); List<String> names = new ArrayList<>(Arrays.asList(f.list(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(Coder.SAMPLE_SUFFIX); } }))); for (int i = 0; i < names.size(); ++i) { names.set(i, names.get(i).replace(Coder.SAMPLE_SUFFIX, "")); } Collections.sort(names); okHereIsYourJson("models", names, response); } /** * Start new instance. * * @param target * @param baseRequest * @param request * @param response * @throws IOException */ private void startInstance(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { Params params = new Params(); params.addValidator("name", new NonEmptyStringValidator(true)); params.addValidator("wp", new BooleanValidator()); new DoSomethingAfterValidatingMyParams(params, request, response) { @Override public void something() throws IOException, EncodeException, DecodeException { String name = request.getParameter("name"); boolean nameConflict = false; for (String jobId : project.listJobIds()) { Job job = project.getJob(jobId); if (job.name.get().equals(name)) { nameConflict = true; } } if (nameConflict) { error("Coding instances with name \"" + name + "\" already exists!"); } else { // ServerSocket serverSocket = null; // boolean closed = true; // Iterator<Integer> itr = portRange.iterator(); // // int port = -1; // // Set<Integer> inUsePorts = getPortsInUse(); // // while (closed && itr.hasNext()) { // // port = itr.next(); // // if(inUsePorts.contains(port)) { // continue; // } // // try { // serverSocket = new ServerSocket(port); // serverSocket.close(); // closed = false; // } catch (IOException e) { // closed = true; // } finally { // if(serverSocket != null && !serverSocket.isClosed()) { // serverSocket.close(); // } // } // } //if(closed) { if (false) { error("No ports available in range"); } else { Job job = instance(Job.class); String id = project.addJob(name, job); //CodingServer.Options codingServer = instance(CodingServer.Options.class); // not sure if this is used Coder.Options coder = instance(Coder.Options.class); job.setMeta("output_prefix", id); coder.modelDir.set(new File(options.modelsFolder.get())); // this is used to name model files and so forth. is crazy shit. coder.setName(id); //File choFile = project.jobFile(id, "coding-handler.json"); //coder.toFile(choFile); //codingServer.setHandlerConfigFile(choFile); //codingServer.setPort(port); //job.setMeta("port", port); if (request.getParameter("wp") != null && Boolean.valueOf(request.getParameter("wp"))) { job.setMeta("wp", true); } else { job.setMeta("wp", false); } //job.addComponent(codingServer); job.addComponent(coder); project.setJob(id, job); project.startJob(id, false); okHereIsYourJson("id", id, response); } } } }; } protected void renameJob(final String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { Params params = new Params(); params.addValidator("to", new NonEmptyStringValidator(true)); params.addValidator("id", new AllowedValidator(true)); params.addValidator("from", new AllowedValidator(true)); new DoSomethingAfterValidatingMyParams(params, request, response) { @Override public void something() throws IOException { new DoSomethingWithTheSpecifiedJobID(request, response) { @Override public void something(String jid) throws IOException { if (project.jobIsRunning(jid)) { error("Can't rename a job while it is running"); } else { String to = request.getParameter("to"); String newId = project.rename(jid, to); String fromPath = concat(modelsFolder, jid); String toPath = concat(modelsFolder, newId); CodingHandler.Options cho = uk.ac.susx.tag.method51.core.params.Params.fromFile( CodingHandler.Options.class, project.jobFile(newId, "coding-handler.json")); cho.name.set(newId); cho.toFile(project.jobFile(newId, "coding-handler.json")); Job j = project.getJob(newId); j.setMeta("output_prefix", newId); //CodingServer.Options serverOpts = (CodingServer.Options) j.components.get().get(0).opts.get(); //serverOpts.setHandlerConfigFile(project.jobFile(newId, "coding-handler.json")); project.setJob(newId, j); Coder.rename(fromPath, toPath); okHereIsYourJson("id", newId, response); } } }; } }; } protected void deleteJob(final String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { new DoSomethingWithTheSpecifiedJobID(request, response) { @Override public void something(String jid) throws IOException { Coder.delete(new File(modelsFolder, jid).getPath()); projectHandler.delete.handle(target, baseRequest, request, response); } }; } private Set<Integer> getPortsInUse() throws IOException, DecodeException { Set<Integer> ports = new HashSet<>(); for (String jid : project.listAllJobIds()) { Job j = project.getJob(jid); ports.add(((Number) j.getMeta("port")).intValue()); } return ports; } // public static class Options extends AbstractJobHandler.Options { public final Param<String> modelsFolder = new Param<>(); { modelsFolder.doc("Directory for all models"); modelsFolder.defaultValue("data/models"); } public final Param<List<Integer>> instancePortRange = new Param<>(); { List<Integer> range = new LinkedList<>(); range.add(49125); range.add(65535); instancePortRange.defaultValue(range); instancePortRange.doc("ports that are to be used for coding instances"); } } }