package net.sourceforge.seqware.queryengine.webservice.controller; import net.sf.beanlib.hibernate.UnEnhancer; import net.sourceforge.seqware.queryengine.webservice.security.SeqWareVerifier; import net.sourceforge.seqware.webservice.resources.SeqwareAccessionIDResource; import net.sourceforge.seqware.webservice.resources.SeqwareAccessionResource; import net.sourceforge.seqware.webservice.resources.filters.ExperimentIDFilter; import net.sourceforge.seqware.webservice.resources.filters.IUSIDFilter; import net.sourceforge.seqware.webservice.resources.filters.LaneIDFilter; import net.sourceforge.seqware.webservice.resources.filters.SampleIDFilter; import net.sourceforge.seqware.webservice.resources.queries.EnvironmentResource; import net.sourceforge.seqware.webservice.resources.queries.FileProvenanceResource; import net.sourceforge.seqware.webservice.resources.queries.ProcessIdProcessResource; import net.sourceforge.seqware.webservice.resources.queries.RunWorkflowResource; import net.sourceforge.seqware.webservice.resources.queries.SampleHierarchyResource; import net.sourceforge.seqware.webservice.resources.queries.TriggerFileProvenanceResource; import net.sourceforge.seqware.webservice.resources.queries.WorkflowReportResource; import net.sourceforge.seqware.webservice.resources.queries.WorkflowRunIDProcessingsResource; import net.sourceforge.seqware.webservice.resources.queries.WorkflowRunIDWorkflowResource; import net.sourceforge.seqware.webservice.resources.queries.WorkflowRunIdFilesResource; import net.sourceforge.seqware.webservice.resources.queries.WorkflowRunReportResource; import net.sourceforge.seqware.webservice.resources.queries.WorkflowRuntimeResource; import net.sourceforge.seqware.webservice.resources.tables.ExperimentIDResource; import net.sourceforge.seqware.webservice.resources.tables.ExperimentLibraryDesignResource; import net.sourceforge.seqware.webservice.resources.tables.ExperimentResource; import net.sourceforge.seqware.webservice.resources.tables.ExperimentSpotDesignReadSpecResource; import net.sourceforge.seqware.webservice.resources.tables.ExperimentSpotDesignResource; import net.sourceforge.seqware.webservice.resources.tables.FileChildLimitedWorkflowRunsResource; import net.sourceforge.seqware.webservice.resources.tables.FileChildWorkflowRunsResource; import net.sourceforge.seqware.webservice.resources.tables.FileIDResource; import net.sourceforge.seqware.webservice.resources.tables.FileLinkReportResource; import net.sourceforge.seqware.webservice.resources.tables.FileResource; import net.sourceforge.seqware.webservice.resources.tables.FileReverseHierarchyDisplayResource; import net.sourceforge.seqware.webservice.resources.tables.IusIDResource; import net.sourceforge.seqware.webservice.resources.tables.IusResource; import net.sourceforge.seqware.webservice.resources.tables.LaneIDResource; import net.sourceforge.seqware.webservice.resources.tables.LaneResource; import net.sourceforge.seqware.webservice.resources.tables.LibrarySelectionResource; import net.sourceforge.seqware.webservice.resources.tables.LibrarySourceResource; import net.sourceforge.seqware.webservice.resources.tables.LibraryStrategyResource; import net.sourceforge.seqware.webservice.resources.tables.OrganismResource; import net.sourceforge.seqware.webservice.resources.tables.PlatformResource; import net.sourceforge.seqware.webservice.resources.tables.ProcessIDResource; import net.sourceforge.seqware.webservice.resources.tables.ProcessResource; import net.sourceforge.seqware.webservice.resources.tables.ProcessingStructureResource; import net.sourceforge.seqware.webservice.resources.tables.RootSampleResource; import net.sourceforge.seqware.webservice.resources.tables.SampleIDResource; import net.sourceforge.seqware.webservice.resources.tables.SampleResource; import net.sourceforge.seqware.webservice.resources.tables.SequencerRunIDResource; import net.sourceforge.seqware.webservice.resources.tables.SequencerRunResource; import net.sourceforge.seqware.webservice.resources.tables.StudyIDResource; import net.sourceforge.seqware.webservice.resources.tables.StudyResource; import net.sourceforge.seqware.webservice.resources.tables.StudyTypeResource; import net.sourceforge.seqware.webservice.resources.tables.WorkflowIDResource; import net.sourceforge.seqware.webservice.resources.tables.WorkflowParamIDResource; import net.sourceforge.seqware.webservice.resources.tables.WorkflowParamResource; import net.sourceforge.seqware.webservice.resources.tables.WorkflowParamValueIDResource; import net.sourceforge.seqware.webservice.resources.tables.WorkflowParamValueResource; import net.sourceforge.seqware.webservice.resources.tables.WorkflowResource; import net.sourceforge.seqware.webservice.resources.tables.WorkflowRunIDResource; import net.sourceforge.seqware.webservice.resources.tables.WorkflowRunResource; import org.restlet.Component; import org.restlet.Context; import org.restlet.Request; import org.restlet.Response; import org.restlet.Restlet; import org.restlet.data.ChallengeScheme; import org.restlet.data.Method; import org.restlet.data.Protocol; import org.restlet.data.Reference; import org.restlet.data.Status; import org.restlet.ext.wadl.ApplicationInfo; import org.restlet.ext.wadl.DocumentationInfo; import org.restlet.ext.wadl.WadlApplication; import org.restlet.routing.Router; import org.restlet.security.ChallengeAuthenticator; /** * <p> * SeqWareWebServiceApplication class. * </p> * * @author morgantaschuk * @version $Id: $Id */ public class SeqWareWebServiceApplication extends WadlApplication { /** * Creates a root Restlet that will receive all incoming calls. * * @return a {@link org.restlet.Restlet} object. */ @Override public synchronized Restlet createInboundRoot() { final Component component = new Component(); component.getClients().add(Protocol.CLAP); ChallengeAuthenticator guard = getGuard(); // String rootURL = ""; // if (EnvUtil.getProperty("urlhack") != null) { rootURL = EnvUtil.getProperty("urlhack"); } // We don't want to use CGLIB since it is a huge memory hog // see for more information: http://beanlib.svn.sourceforge.net/viewvc/beanlib/trunk/beanlib-doc/faq.html UnEnhancer.setDefaultCheckCGLib(false); String version = "queryengine"; // if (EnvUtil.getProperty("version") != null) { rootURL = EnvUtil.getProperty("version"); } // Create a router Restlet that routes each call to a // new instance of HelloWorldResource. Router router = new Router(getContext()); router.setDefaultMatchingQuery(false); router.setRoutingMode(Router.MODE_LAST_MATCH); // I don't know if this is needed anymore getConnectorService().getClientProtocols().add(Protocol.FILE); Restlet slashRedirect = new OptionalSlashRedirect(getContext()); router.attachDefault(EnvironmentResource.class); /* * New version of webservices */ router.attach("/SWA/", SeqwareAccessionResource.class); router.attach("/SWA/{SWA}", SeqwareAccessionIDResource.class); router.attach("/experiments", ExperimentResource.class); router.attach("/experiments/", slashRedirect); router.attach("/experiments/{experimentId}", ExperimentIDResource.class); router.attach("/experiments/{experimentId}/samples", SampleIDFilter.class); // router.attach("/experiments/{ID}/processes", Resource.class); // router.attach("/experiments/{ID}/processes/{ID}", Resource.class); // // TODO: make sure sequencer run, lane, and IUS have post methods! router.attach("/platforms", PlatformResource.class); router.attach("/platforms/", slashRedirect); router.attach("/studytypes", StudyTypeResource.class); router.attach("/studytypes/", slashRedirect); router.attach("/libraryselections", LibrarySelectionResource.class); router.attach("/libraryselections/", slashRedirect); router.attach("/librarysources", LibrarySourceResource.class); router.attach("/librarysources/", slashRedirect); router.attach("/librarystrategies", LibraryStrategyResource.class); router.attach("/librarystrategies/", slashRedirect); router.attach("/organisms", OrganismResource.class); router.attach("/organisms/", slashRedirect); router.attach("/experimentspotdesigns", ExperimentSpotDesignResource.class); router.attach("/experimentspotdesigns/", slashRedirect); router.attach("/experimentlibrarydesigns", ExperimentLibraryDesignResource.class); router.attach("/experimentlibrarydesigns/", slashRedirect); router.attach("/experimentspotdesignreadspecs", ExperimentSpotDesignReadSpecResource.class); router.attach("/experimentspotdesignreadspecs/", slashRedirect); router.attach("/files", FileResource.class); router.attach("/files/", slashRedirect); router.attach("/files/{fileId}", FileIDResource.class); router.attach("/ius", IusResource.class); router.attach("/ius/", slashRedirect); router.attach("/ius/{iusId}", IusIDResource.class); router.attach("/ius/{iusId}/lane", LaneIDFilter.class); router.attach("/lanes", LaneResource.class); router.attach("/lanes/", slashRedirect); router.attach("/lanes/{laneId}", LaneIDResource.class); router.attach("/lanes/{laneId}/ius", IUSIDFilter.class); router.attach("/processes", ProcessResource.class); router.attach("/processes/", slashRedirect); router.attach("/processes/{processId}", ProcessIDResource.class); router.attach("/processes/{processId}/parents", new ProcessIdProcessResource(getContext())); // router.attach("/processes/{ID}/parents", Resource.class); // router.attach("/processes/{ID}/parents/{ID}", Resource.class); // router.attach("/processes/{ID}/children", Resource.class); // router.attach("/processes/{ID}/children/{ID}", Resource.class); // router.attach("/samples", SampleResource.class); router.attach("/samples/", slashRedirect); router.attach("/samples/{sampleId}", SampleIDResource.class); router.attach("/samples/{parentId}/children", SampleIDFilter.class); router.attach("/samples/{childId}/parents", SampleIDFilter.class); router.attach("/samples/{sampleId}/ius", IUSIDFilter.class); router.attach("/samples/root", RootSampleResource.class); router.attach("/samples/root/", slashRedirect); // router.attach("/samples/{ID}/processes", Resource.class); // router.attach("/samples/{ID}/processes/{ID}", Resource.class); // router.attach("/sequencerruns", SequencerRunResource.class); router.attach("/sequencerruns/", slashRedirect); router.attach("/sequencerruns/{sequencerRunId}", SequencerRunIDResource.class); router.attach("/sequencerruns/{sequencerRunId}/lanes", LaneIDFilter.class); // router.attach("/sequencer_runs/{ID}/lanes", Resource.class); // router.attach("/sequencer_runs/{ID}/lanes/{ID}", Resource.class); // router.attach("/sequencer_runs/{ID}/processes/", Resource.class); // router.attach("/sequencer_runs/{ID}/processes/{ID}", Resource.class); // router.attach("/studies", StudyResource.class); router.attach("/studies/", slashRedirect); router.attach("/studies/{studyId}", StudyIDResource.class); router.attach("/studies/{studyId}/experiments", ExperimentIDFilter.class); // router.attach("/workflowruns", WorkflowRunResource.class); router.attach("/workflowruns/", slashRedirect); router.attach("/workflowruns/{workflowRunId}", WorkflowRunIDResource.class); router.attach("/workflowruns/{workflowRunId}/files", new WorkflowRunIdFilesResource(getContext())); router.attach("/workflowruns/{workflowRunId}/processings", new WorkflowRunIDProcessingsResource(getContext())); router.attach("/workflowruns/{workflowRunId}/workflow", new WorkflowRunIDWorkflowResource(getContext())); router.attach("/workflows", WorkflowResource.class); router.attach("/workflows/", slashRedirect); router.attach("/workflows/{workflowId}", WorkflowIDResource.class); router.attach("/workflows/{workflowId}/runs", new RunWorkflowResource(getContext())); router.attach("/workflows/{workflowId}/runs/", slashRedirect); router.attach("/workflowparams", WorkflowParamResource.class); router.attach("/workflowparams/", slashRedirect); router.attach("/workflowparams/{workflowParamId}", WorkflowParamIDResource.class); router.attach("/workflowparamvalues", WorkflowParamValueResource.class); router.attach("/workflowparamvalues/", slashRedirect); router.attach("/workflowparamvalues/{workflowParamValueId}", WorkflowParamValueIDResource.class); /* * Reports */ router.attach("/reports/file-provenance", new FileProvenanceResource(getContext())); router.attach("/reports/file-provenance/generate", new TriggerFileProvenanceResource(getContext())); // the following collides with the non-variable paths. // router.attach("/reports/studies/{studyId}", new CycleCheckResource(getContext())); router.attach("/reports/workflows/{workflowId}", new WorkflowReportResource(getContext())); WorkflowRunReportResource wrrr = new WorkflowRunReportResource(getContext()); router.attach("/reports/workflowruns/{workflowRunId}", wrrr); router.attach("/reports/workflowruns", wrrr); router.attach("/reports/workflows/{workflowId}/runs", wrrr); router.attach("/reports/workflowruns/", slashRedirect); router.attach("/reports/workflows/{workflowId}/runs/", slashRedirect); router.attach("/reports/workflowruns/{workflowRunId}/stderr", wrrr); router.attach("/reports/workflowruns/{workflowRunId}/stdout", wrrr); router.attach("/reports/workflowruns/{workflowRunId}/stderr/", slashRedirect); router.attach("/reports/workflowruns/{workflowRunId}/stdout/", slashRedirect); // A report giving runtime info for workflows router.attach("/reports/workflowruntimes", new WorkflowRuntimeResource(getContext())); // A report giving workflow runs that are relevant for a group of files router.attach("/reports/fileworkflowruns", FileChildWorkflowRunsResource.class); router.attach("/reports/fileworkflowruns/", slashRedirect); router.attach("/reports/fileworkflowruns/limit", FileChildLimitedWorkflowRunsResource.class); router.attach("/reports/fileworkflowruns/limit/", slashRedirect); // STATIC COMPONENTS router.attach("/x/report/filelinkreport", FileLinkReportResource.class); router.attach("/x/report/filelinkreport/{swas}", FileLinkReportResource.class); router.attach("/x/report/reversehierarchy/{swa}", FileReverseHierarchyDisplayResource.class); // Directory directory = new Directory(getContext(), "war:///WEB-INF/html"); // router.attachDefault(directory); // router.attach("/" + version + "/static", directory); router.attach("/processingstructure", new ProcessingStructureResource(getContext())); router.attach("/sample/parents", new SampleHierarchyResource(getContext())); guard.setNext(router); return guard; } private ChallengeAuthenticator getGuard() { // FIXME: double slash is an artifact of the groove proxy server // get the ROOT URL for various uses // String rootURL = ""; // if (EnvUtil.getProperty("urlhack") != null) { rootURL = EnvUtil.getProperty("urlhack"); } // Guard the restlet with BASIC authentication. ChallengeAuthenticator guard = new ChallengeAuthenticator(null, ChallengeScheme.HTTP_BASIC, "SeqWare metadata Web service"); // Instantiates a Verifier of identifier/secret couples based on a // simple Map. SeqWareVerifier verifier = new SeqWareVerifier(); guard.setVerifier(verifier); return guard; } /** * {@inheritDoc} * * @return */ @Override public ApplicationInfo getApplicationInfo(Request request, Response response) { ApplicationInfo result = super.getApplicationInfo(request, response); DocumentationInfo docInfo = new DocumentationInfo("SeqWare Web Service Application"); docInfo.setTitle("First resource sample application."); result.setDocumentation(docInfo); return result; } /** * http://restlet-discuss.1400322.n2.nabble.com/Proper-handling-of-at-the-end-of-the-requested-URI-td5819896.html */ protected static class OptionalSlashRedirect extends Restlet { public OptionalSlashRedirect(Context context) { super(context); } public OptionalSlashRedirect() { } @Override public void handle(Request request, Response response) { super.handle(request, response); Method m = request.getMethod(); if (m.equals(Method.GET) || m.equals(Method.HEAD)) { Reference ref = request.getOriginalRef().getTargetRef(); String path = ref.getPath(); if (path.endsWith("/")) { path = path.substring(0, path.length() - 1); } else { path = path + "/"; } ref.setPath(path); response.redirectPermanent(ref); } else { response.setStatus(Status.CLIENT_ERROR_NOT_FOUND); } } } }